# oauth

Google and Microsoft sign-in exchange provider identity tokens for a normal Jobjakt local session.
Microsoft sign-in validates the configured `Auth:MicrosoftTenant` mode, exact issuer/`tid`, audience,
signature, lifetime, and GUID-shaped (`tid`, `oid`) pair. Microsoft email and
`preferred_username` claims are display/contact metadata, not proof of mailbox ownership. Raw
Microsoft bearer tokens are not accepted by application APIs; the exchange endpoint is the only
Microsoft sign-in trust path.

`Auth:MicrosoftTenant` accepts one tenant GUID, `organizations`, `consumers`, or explicit `common`.
It is separate from `Microsoft:TenantId`, which controls Graph mailbox consent. Production requires
the sign-in setting whenever `Auth:MicrosoftClientId` is enabled. The frontend receives the same
value as `NEXT_PUBLIC_MICROSOFT_TENANT`, so its MSAL authority and the backend acceptance policy do
not drift.

`AspNetUsers.MicrosoftTenantId` plus `MicrosoftObjectId` is the unique Microsoft owner. Email is
metadata and never auto-links or merges an existing Jobbjakt account. An authenticated password
user must re-enter the current password to link or unlink; either change revokes every session and
trusted device. Unlink is refused for passwordless accounts to avoid removing their last proven
credential without a provider-reauthentication flow.

Legacy `MicrosoftSubject`/`MicrosoftEmail` values are retained as evidence and are never backfilled.
When exactly one legacy candidate is found, recovery sends a purpose-bound proof to its already
confirmed application email. Confirmation also requires a fresh Microsoft token for the exact same
(`tid`, `oid`) pair. Ambiguous/unconfirmed candidates require administrator-assisted verification;
the application never guesses a tenant or silently merges accounts.

Before enabling this release in production, apply `20260802212509_AddCanonicalMicrosoftIdentity`,
run the counts-only legacy inventory in the deployment runbook, and keep Microsoft sign-in disabled
if ambiguous rows cannot be handled. Rollback may keep the additive columns, but must never restore
email auto-linking.

Gmail and Microsoft Graph mailbox connections use separate OAuth flows and state validation because
they grant mailbox permissions, not application login.

Provider client IDs and secrets belong in environment configuration, never the repository. See
`docs/architecture/authentication.md` and the connected-account settings UI.
