36 lines
1.5 KiB
SQL
36 lines
1.5 KiB
SQL
-- 0019_oidc.sql
|
|
--
|
|
-- OIDC bookkeeping. Three independent additions land in one
|
|
-- migration to keep the related changes together:
|
|
--
|
|
-- 1. users.auth_source — 'local' | 'oidc'. Local users get
|
|
-- the default; first OIDC sign-in JITs
|
|
-- a row with auth_source='oidc'.
|
|
-- 2. users.oidc_subject — IdP's stable 'sub' claim. Indexed
|
|
-- uniquely (partial; NULLs allowed).
|
|
-- 3. sessions.id_token — last id_token for OIDC sessions, used
|
|
-- as id_token_hint on RP-initiated
|
|
-- logout. NULL for local sessions.
|
|
-- 4. oidc_state — short-lived state for the OAuth round-
|
|
-- trip (state + PKCE code_verifier).
|
|
-- Swept on the alert engine tick.
|
|
--
|
|
-- All column-level ALTERs (CLAUDE.md preference; safe under
|
|
-- foreign_keys=ON).
|
|
|
|
ALTER TABLE users ADD COLUMN auth_source TEXT NOT NULL DEFAULT 'local'
|
|
CHECK (auth_source IN ('local', 'oidc'));
|
|
ALTER TABLE users ADD COLUMN oidc_subject TEXT;
|
|
|
|
CREATE UNIQUE INDEX users_oidc_subject ON users(oidc_subject)
|
|
WHERE oidc_subject IS NOT NULL;
|
|
|
|
ALTER TABLE sessions ADD COLUMN id_token TEXT;
|
|
|
|
CREATE TABLE oidc_state (
|
|
state_hash TEXT PRIMARY KEY, -- sha256(state) hex; raw never persisted
|
|
code_verifier TEXT NOT NULL,
|
|
created_at TEXT NOT NULL
|
|
);
|
|
CREATE INDEX oidc_state_created ON oidc_state(created_at);
|