ADR 0028 — Sign in with Apple is the application identity provider
Status
Accepted. Revises ADR 0005.
Context
Sprint 01 shipped a signed HTTP-only ia_session cookie with no external IdP (MAIL-73 / ADR 0005). That cookie shape is still correct: claims are an allowlist, CSRF lives inside the signed cookie, and Microsoft Graph / Gmail tokens stay in the MAIL-74 secret store.
The owner then chose Sign in with Apple as the application identity provider (MAIL-181). Application login is a different concern from mailbox provider OAuth (ADR 0011 / ADR 0015). The owner session (POST /api/session/owner) remains an ops escape when OWNER_SESSION_ENABLED is true; it is not a second product IdP.
Decision
- Apple is the only application IdP for this story.
- Map Apple
subtoinbox_agent.users.identity_subject. A User exists independently of anyconnected_accountsrow. - After Apple identity is verified, issue the existing
ia_session+ CSRF cookie. Session claims stayv,userId,iat,exp,csrf. - Never copy Apple tokens, Microsoft Graph tokens, or Gmail tokens into the app session or the public principal view.
- Keep unauthenticated API access as
UNAUTHENTICATED. - Store Apple OIDC
state/nonceininbox_agent.apple_auth_states(migration0020_apple_identity.sql) because Apple'sform_postcallback is a cross-site POST and cannot rely on aSameSite=Laxcookie. - Document Apple Developer registration and callback URLs. Store credentials only as environment variable names; never commit
.p8files or secret values.
Alternatives considered
- Keep owner-session-only login — rejected. MAIL-181 requires a real user completing Sign in with Apple.
- Auth0 / Clerk / Google as the app IdP — rejected for this story.
- Put mailbox provider tokens in the session after Apple login — rejected. ADR 0004 / MAIL-74 remain the only token store.
- Replace
ia_sessionwith an Apple access token cookie — rejected. The Sprint 01 session shape stays.
Consequences
/loginand/api/auth/apple/startbegin Sign in with Apple./api/auth/apple/callbackupserts User and setsia_session.- Verify Apple
id_tokenas RS256 against the RSA JWKS athttps://appleid.apple.com/auth/keys. The Sign in with Apple.p8is ES256 and is only used to mint the client secret. - Preview and production stay 503 on those routes until
APPLE_CLIENT_ID,APPLE_TEAM_ID,APPLE_KEY_ID, andAPPLE_PRIVATE_KEYare set per host. - Microsoft Graph OAuth still requires an existing app session. Connect Microsoft may use the Apple session or the owner-session escape.
- ADR 0005 remains the session-cookie and CSRF decision. This ADR replaces only the “no external IdP” clause.
