-
Notifications
You must be signed in to change notification settings - Fork 5
Open
2 / 62 of 6 issues completedDescription
Summary
Enable members (citizens) to sign in to OSCER via a state-configured citizen identity provider (IdP) using OpenID Connect, so they can use one account for OSCER and other government services. When no citizen IdP is configured, members continue using app-managed credentials (e.g. Cognito email/password). Implementation reuses the existing staff SSO stack (OmniAuth, Devise, User model) with a separate provider, config, and provisioner.
Business Value
- Single account for citizens: Members use their existing state portal or citizen IdP account; no separate OSCER password when OIDC is configured
- State flexibility: Each deployment configures its own citizen IdP via
MEMBER_OIDC_*env vars; no state-specific names in code - Security alignment: MFA and password policy are the IdP’s responsibility; app skips in-app MFA for OIDC users
- Optional alongside Cognito: Member OIDC can be the only member auth or offered alongside email/password; login page shows both when both are enabled
Authentication Flow
sequenceDiagram
participant Member
participant OSCER
participant IdP as Citizen IdP
Member->>OSCER: Visit member login (or redirect when OIDC only)
OSCER->>Member: Show "Sign in with your account" and/or email/password
Member->>OSCER: POST /auth/member_oidc (OmniAuth)
OSCER->>Member: Redirect to IdP
Member->>IdP: Login + MFA
IdP->>Member: Redirect to callback with code
Member->>OSCER: GET /auth/member_oidc/callback
OSCER->>IdP: Exchange code for tokens
IdP->>OSCER: ID token
OSCER->>OSCER: MemberOidcProvisioner.provision!(claims)
OSCER->>OSCER: sign_in(user) — no MFA challenge
OSCER->>Member: Redirect to dashboard or return_to
Scope
In Scope
- OIDC redirect flow for members (OmniAuth provider
:member_oidc) - Just-In-Time member user provisioning (find/create by UID, sync email/name; no role mapping)
- MFA bypass for member OIDC users (
mfa_preferenceset toopt_out) - Member login UI: "Sign in with your account" when
MEMBER_OIDC_ENABLED; optional bypass of login screen when OIDC is the only auth - Shared redirect-URI helper and claim extractor (staff + member reuse)
- Generic naming only (
MEMBER_OIDC_*, no state or IdP names in repo) - Local development with Keycloak (optional second realm for citizen IdP)
Out of Scope
- SAML for citizen IdP
- Multiple citizen IdPs per deployment
- Role or group mapping for members (members are non-staff)
- IdP-initiated login
--
Epic Acceptance Criteria
- When
MEMBER_OIDC_ENABLED=true, members can sign in via the configured citizen IdP (OIDC redirect, callback, provision, session) - Member user records are created/updated by UID; email and name synced from IdP claims; no staff role
- Member OIDC users bypass the app’s MFA preference page and Cognito MFA challenge (
mfa_preferenceset toopt_out) - Member login page shows "Sign in with your account" when member OIDC is enabled; when OIDC is the only member auth, app can redirect directly to OIDC flow (bypass login form)
- On failure, redirect to member sign-in path with alert (not necessarily root)
- All config and code use generic names (
MEMBER_OIDC_*,member_oidc); no state or IdP names in repo - Staff SSO behavior unchanged; redirect URI and claim extraction shared where appropriate
- I18n keys for member OIDC (login_success, authentication_failed, not_enabled, button text) are generic
Reactions are currently unavailable