docs: add ADR-0009 for the authentication flow (OIDC Auth Code + PKCE via MSAL Node)
Pin the BFF authentication mechanics: OAuth 2.0 Authorization Code Flow with PKCE, executed server-side via @azure/msal-node's ConfidentialClientApplication. Tokens are held in the BFF session and never reach the browser; the SPA only ever sees the opaque __Host-portal_session cookie. Token validation enforces the tenant allowlist from ADR-0008 (iss check) and maps the audience claim to our Audience enum at the validation step. Refresh-token rotation is enabled via MSAL acquireTokenSilent. Cookies use the __Host- prefix (forces Secure/Path=/, no Domain) with HttpOnly/SameSite=Lax. CSRF uses the double-submit pattern with a matching X-CSRF-Token header on every state-changing request, enforced by a NestJS interceptor and injected client-side by an Angular HTTP interceptor. Logout is RP-initiated against Entra's end_session_endpoint. Routes are pinned: GET /auth/login, GET /auth/callback, POST /auth/logout, GET /auth/me. AuthGuard is registered globally - public routes must be explicitly opted in. Local dev runs over HTTPS via mkcert to keep cookie behaviour identical to prod. All Entra-specific values come from environment variables; the BFF refuses to start without them. decisions/README.md index updated. CLAUDE.md gains an explicit 'Authentication flow' line pointing to ADR-0009.
This commit is contained in:
@@ -37,7 +37,8 @@ The structural choices are recorded as ADRs and summarized below. Any change to
|
||||
- **Backend (`portal-bff`):** NestJS at the latest stable major, mounted on the Express adapter (Fastify adapter swappable later) — see [ADR-0005](decisions/0005-backend-stack-nestjs.md).
|
||||
- **Persistence:** PostgreSQL (latest stable major) via Prisma — see [ADR-0006](decisions/0006-persistence-postgresql-prisma.md).
|
||||
- **Sessions / cache:** Redis self-hosted — to be locked-in in phase 2.
|
||||
- **Identity:** multi-tenant Microsoft Entra ID with B2B invitation for workforce in v1, dual-audience design ready for future External ID activation — see [ADR-0008](decisions/0008-identity-model-entra-workforce-dual-audience.md). The OIDC Auth Code + PKCE flow via `@azure/msal-node` will be locked-in by a follow-up phase-2 ADR.
|
||||
- **Identity:** multi-tenant Microsoft Entra ID with B2B invitation for workforce in v1, dual-audience design ready for future External ID activation — see [ADR-0008](decisions/0008-identity-model-entra-workforce-dual-audience.md).
|
||||
- **Authentication flow:** OIDC Authorization Code + PKCE via `@azure/msal-node`, executed entirely on the BFF; SPA never holds tokens; `__Host-` prefixed cookies, double-submit CSRF, RP-initiated logout — see [ADR-0009](decisions/0009-auth-flow-oidc-pkce-msal-node.md).
|
||||
- **Observability:** Pino structured logs + OpenTelemetry traces with W3C Trace Context propagation — to be locked-in in phase 2.
|
||||
- **Local quality gates:** Husky + lint-staged + commitlint with Conventional Commits — see [ADR-0007](decisions/0007-pre-commit-hooks-and-conventional-commits.md).
|
||||
- **Runtime:** Node.js latest LTS major.
|
||||
|
||||
Reference in New Issue
Block a user