Перейти к основному содержимому

idf-auth

Production-ready identity plane для IDF. Magic-link email + HMAC tenant-signed invites + JWT RS256 + JWKs endpoint.

Live production: auth.intent-design.tech (Ubuntu VPS, docker compose + nginx + certbot, 41 integration tests green).

1. Endpoints

EndpointНазначение
POST /magic-linkIssue nonce → email через Resend
GET /magic-link/callback?token=<nonce>Verify, issue RS256 JWT
POST /invitesTenant-signed HMAC; create invite + email
GET /invites/accept?token=<nonce>Accept invite, issue JWT
POST /revokeTenant-signed; revoke membership
GET /revocations?since=<iso>Pull-endpoint для data plane revocation cache
GET /.well-known/jwks.jsonPublic keys для verify на data plane
GET /health, GET /readyHealth checks

2. Local dev (10 минут)

git clone https://github.com/DubovskiyIM/idf-auth
cd idf-auth
cp .env.example .env

Ключи RS256:

npm run keys:generate
# скопировать PEM в .env как JWT_PRIVATE_KEY_PEM / JWT_PUBLIC_KEY_PEM

Tenant HMAC secret (для invites / revoke):

node -e 'console.log(require("crypto").randomBytes(32).toString("hex"))'
# в .env как TENANT_HMAC_SECRET

Postgres + миграции:

docker run -d -p 5432:5432 -e POSTGRES_PASSWORD=postgres postgres:16-alpine
DATABASE_URL=postgres://postgres:postgres@localhost:5432/postgres npm run db:migrate

Старт:

npm run dev # :4000
curl http://localhost:4000/health # → {"status":"ok"}
curl http://localhost:4000/.well-known/jwks.json # → JWKs

3. Deploy в production

Две проверенные опции:

VPS + Docker Compose (наша prod-инсталляция)

См. DEPLOYMENT-vps.md — Ubuntu 24.04, nginx reverse-proxy, certbot TLS, docker compose с локальным Postgres в том же стеке.

Upshot:

# локально — build amd64 image
docker buildx build --platform linux/amd64 -t idf-auth:amd64 --load .
docker save idf-auth:amd64 -o /tmp/idf-auth-amd64.tar
scp /tmp/idf-auth-amd64.tar root@<vps>:/opt/idf-auth/

# на VPS — reload без потери БД
docker load -i idf-auth-amd64.tar && docker compose up -d --force-recreate auth

Fly.io + Neon Postgres

См. DEPLOYMENT.md. Быстрее настраивается, но платный для high-traffic. Подходит для pet projects и ранней альфы.

4. Интеграция с data plane

Data plane (idf-runtime) цепляется одним env-vars-setом:

IDF_AUTH_JWKS_URL=https://auth.intent-design.tech/.well-known/jwks.json
IDF_AUTH_REVOCATIONS_URL=https://auth.intent-design.tech/revocations
IDF_TENANT_HMAC_SECRET=<shared-secret> # для /invites + /revoke

idf-runtime кэширует JWKs (10 min TTL), pull'ит /revocations?since=<last> раз в 60с, отменяет свой local JWT cache.

5. Тесты

npm test # unit + integration, 41 tests
npm run smoke # E2E против spawned server + testcontainer Postgres

Testcontainers на cold-start может висеть 60с — отключить Ryuk:

echo 'ryuk.disabled=true' >> ~/.testcontainers.properties

Архитектурные решения

  • RS256 (не HS256) — public key distribution через JWKs позволяет data plane verify без shared secret
  • Magic-link, не password — снимает password rotation / breach blast radius; UX ≈ Slack/Notion
  • HMAC tenant signatures на /invites + /revoke — control plane подписывает, auth verify'ит; избегаем shared DB между control и identity plane
  • Nonce TTL = 15 минут — короткий enough чтобы phishing-email с просроченным linkом не работал, длинный enough для пользователя прочитать письмо

Ссылки