Identity setup
Configure OpenID Connect sign-in, the groups claim, the first Platform Admin, signing-key refresh and SCIM.
The dashboard signs people in with OpenID Connect (authorization code with PKCE). There are no local passwords and no development login.
Register a client
In your identity provider, create a web application client:
- Redirect URI:
https://ai.example.edu/api/v1/auth/callback, your public URL plus/api/v1/auth/callback. - Grant: authorization code, with S256 PKCE. A public or a confidential client both work.
- Scopes: the gateway asks for
openid email profile. - ID token claims:
email,email_verified: true, and a groups claim that is a list of strings (an empty list when no groups match). An optionalnameis shown as the person's display name.
Then set:
GATEWAY_PUBLIC_URL=https://ai.example.edu
GATEWAY_OIDC_ISSUER=https://login.example.edu
GATEWAY_OIDC_CLIENT_ID=ai-gateway
GATEWAY_OIDC_CLIENT_SECRET=… # confidential clients only
GATEWAY_OIDC_GROUPS_CLAIM=groups # the default- The issuer must be exact, including any path, as published in its discovery document.
- Everything must use HTTPS. Only
GATEWAY_ENV=developmentallows plain HTTP, and only on loopback addresses. - If the issuer can't be reached at startup, the gateway doesn't start.
- Admin › Settings › Sign-in shows the configuration in use and the callback URL to register (never the secret).
The first Platform Admin
Signing in doesn't grant access: a person needs a platform role. Make the first admin with:
open-model-gateway provision-user --email morgan.lee@example.edu --platform-adminIt runs with the migrator's database access. It gives the email the Admin role and allows one first sign-in with that verified email to link to the account. Then map groups in Admin › SSO groups for everyone else. Without --platform-admin, the command grants the User role.
How sign-in works
- People are identified by the issuer and subject, not their email. Changing an email at the identity provider doesn't move anyone to another account.
- Group claims are read at every sign-in, from the signature-checked ID token. A missing or malformed groups claim refuses sign-in without removing anything.
- Sessions last 12 hours and are stored as hashes. The
omg_sessioncookie isHttpOnlyandSameSite=Lax;omg_csrfisSameSite=Strict. Every change in the dashboard must also send a matchingOriginand CSRF header. - The gateway doesn't call the userinfo endpoint and doesn't keep the identity provider's access or refresh tokens.
- Signing out ends the gateway session only, not the identity provider's.
Signing keys
The identity provider's signing keys (JWKS) are fetched at startup and cached:
- for the time its
Cache-Control: max-agesays, between 5 minutes and 24 hours (one hour if it doesn't say); - a token signed with an unknown key triggers one refetch, at most once a minute, shared by concurrent sign-ins;
- if fetching fails, the last good keys are used for up to 6 hours past their expiry, then sign-in fails with
503until a fetch works; - only asymmetric algorithms are accepted (RS, PS, ES and EdDSA).
noneand HMAC are always refused.
Settings › Sign-in shows how many keys are cached, when they were fetched and whether they are current.
SCIM
To let your identity provider push deactivations and group changes, choose a variable name for the token and give it a long random value:
GATEWAY_SCIM_TOKEN_ENV=IDP_SCIM_TOKEN
IDP_SCIM_TOKEN=$(openssl rand -hex 32)The token must be 32 to 1,024 printable characters without spaces. The gateway keeps only its hash; to rotate it, change the value and restart. SCIM needs OIDC. Give the identity provider https://ai.example.edu/scim/v2 and the token as a bearer header. Without GATEWAY_SCIM_TOKEN_ENV, every /scim path returns 404. See SCIM provisioning.
At the edge
Rate-limit /api/v1/auth/* and /scim at your proxy, and keep callback query strings, cookies and Authorization headers out of logs.