ADR 0024. Nest-Owned Portal Auth (Session API + Social IdP Intents)
Status
Accepted.
Context
ADR 0022 chose a Login V2 fork for branded portal sign-in. In the local POC,
password and passkey on Login V2 conflicted with player rules (no email forms,
PlayerPal ID as username, RP id on player.localhost) and with Session API
limits (CreateSession cannot challenge without a user id — zitadel#8899).
Social still needs ZITADEL IdP intents; password/passkey need to stay on the
portal card. Same-origin Nest under player.localhost is required so the
BFF session cookie is first-party after Google return (ADR 0016).
Decision
- Password and passkey for the player portal are owned by Nest against
ZITADEL User + Session APIs (
POST /auth/password-*,/auth/passkey/*,/auth/factors/*). Login V2 is not the password/passkey UX. - Social (Google / Apple / Facebook) starts from Nest (
GET /auth/loginor IdP intent →/auth/idp/success). Creates/links an IAM human whose username ispp_plr_…, throwaway password the player never sees, then issues the PlayerPal BFF cookie. No Login V2 email form (ADR 0012). - Store a public-key mirror in
webauthn_credentialsfor discoverable (usernameless) passkey login on the portal RP. Never store private keys or player PII. Identifier-first passkey may still use Session API withuserId. - Persist opaque IAM subject as
authentication_identities.iam_subjectfor password sign-in (local lookup first; ListUsers by username only when missing). Keepplayer_sessions.iam_user_idfor signed-in factor add. Neither is player PII; neither appears on/v1/me. - Logout clears the PlayerPal cookie only (no ZITADEL
end_sessionhop that parks on Login V2). - Login V2 fork (ADR 0022) remains available for experiments / future skins; it is not the authoritative player password/passkey path for this POC.
Consequences
- Supersedes ADR 0021 item 6 and ADR 0022 items 2 and 5 for the local player portal auth path (see amendment notes on those ADRs).
- WebAuthn RP is the portal host (
WEBAUTHN_RP_DOMAIN/APP_BASE_URL, e.g.player.localhost), notlocalhostLogin V2. - Day-to-day docs: docs/authentication.md, infra/README.md.
- Does not close production IAM vendor choice (§23.2).