mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 21:10:59 +00:00
An OIDC login now resolves the account by the durable (issuer, sub) pair instead of the email claim. First contact stamps the pair — by auto-provision or a one-time link against an existing account matched by verified email — and every later login matches on it alone, so an IdP-side email change refreshes the display email but can never re-point the login at a different account. An email that matches an account already bound to a different identity is rejected and audited (auth.oidc.link_conflict), never silently re-bound. The email gate tightens with it: linking and provisioning now require an explicit email_verified: true — an absent claim is a reject (oidc_email_unverified) rather than a benefit of the doubt, since an IdP that does not assert verification cannot anchor the account match. Provisioned accounts get a lowercased email and the same server-default timezone resolution the register route uses. Migration 0240 adds the nullable users.oidc_issuer / users.oidc_sub columns with a composite unique index.
14 lines
744 B
SQL
14 lines
744 B
SQL
-- v1.28 — OIDC SSO identity pinning.
|
|
--
|
|
-- The (oidc_issuer, oidc_sub) pair pins an account to exactly one IdP
|
|
-- identity: stamped on first OIDC login (auto-provision or one-time link by
|
|
-- verified email), matched on every later OIDC login. Email stays a display
|
|
-- field after the stamp — an IdP-side email change can never re-point the
|
|
-- login at a different account. Both columns are NULL on accounts that never
|
|
-- signed in via SSO; Postgres unique indexes ignore NULL pairs, so the
|
|
-- constraint only bites on actual duplicate identities.
|
|
ALTER TABLE "users" ADD COLUMN "oidc_issuer" TEXT;
|
|
ALTER TABLE "users" ADD COLUMN "oidc_sub" TEXT;
|
|
|
|
CREATE UNIQUE INDEX "users_oidc_issuer_oidc_sub_key" ON "users"("oidc_issuer", "oidc_sub");
|