Authentication
People sign in through a registered OpenID Connect directory. The server verifies their identity and issues a separate, opaque application-session cookie. Directory tokens never become browser API credentials. For a walkthrough, see Create your workspace.
Directory prerequisites
Register a web application supporting authorization code with PKCE S256. Allow the exact dashboard
callback, ending in /auth/callback. Enable openid, email, and profile. Standard web
applications use a client secret, encrypted and write-only in the platform. The Other preset can
also use a public client when the directory supports PKCE without a secret.
Client authentication must match the registered application: client_secret_basic sends encoded
credentials in the Authorization header, client_secret_post sends them in the form body, and
none is reserved for an explicitly supported public PKCE client. Okta defaults to Basic; the Auth0
guide selects POST. Google and Entra web registrations support POST. Sign-in uses the directory's
normal prompting policy rather than forcing a provider-specific reauthentication parameter.
The directory must issue a signed ID token for that client ID. Its access token may be opaque: SRE Platform neither uses it as an API credential nor retains it. No custom API audience, token gateway or refresh-token permission is required for browser sign-in.
The API creates single-use state, nonce and PKCE values and persists them server-side. The callback must come from the browser that started the attempt. The API verifies signature, issuer, client audience, authorized party when present, expiry, issued-at time and nonce. Provider selection is by exact stored provider identifier, not by whichever row shares an issuer. Separate clients may use the same company-directory issuer.
Discovery, signing keys and code exchange use public-DNS validation, IP-pinned HTTPS with hostname verification, no redirects, a five-second timeout and a 64 KiB response limit. Provider error bodies and secrets are not reflected to the browser.
Email and domain proof
The standard email claim is trusted only when email_verified is true. Otherwise the platform
requires a one-time mailbox code through configured SMTP before creating a user session or accepting
the email. Configure email delivery in Platform settings before enabling directories that do not
supply verified-email claims. Missing or failed SMTP delivery prevents sign-in and gives a safe,
actionable error. Codes never appear in the platform notification inbox.
The identity remains the exact issuer and configured subject claim, never the email address. The original OIDC subject and optional provider session identifier are retained with the session. Changing email does not relink an identity.
Mailbox verification does not establish company ownership. A new workspace separately requires the generated DNS TXT record for its declared domain. Its founder can complete setup while DNS is pending; ordinary members cannot use an unverified directory.
Browser sessions and deployment
A browser receives a random credential in a host-only HttpOnly, SameSite=Lax cookie. Production
cookies are Secure and use the __Host- prefix. Only a hash is stored in the database. Browser
storage contains non-secret setup and routing metadata, not upstream tokens or client secrets.
The dashboard and API must be on the same site, for example app.example.com and api.example.com.
Use HTTPS for both in production. Cross-origin API calls include credentials, and CORS_ORIGINS
must list the exact dashboard origin. Configure both values on the API:
DASHBOARD_BASE_URL=https://app.example.com
CORS_ORIGINS=https://app.example.com
DASHBOARD_BASE_URL sets the trusted browser origin and the /auth/callback URL sent to the
directory. It is independent of CORS_ORIGINS; setting CORS alone is insufficient. Production
startup rejects an HTTP dashboard URL, including the local-development default.
Mutating cookie requests, including anonymous sign-in starts and completion, require the configured Origin and the application's CSRF header. Reverse-proxy headers do not switch secure cookies off. HTTP is supported only by explicit development mode.
Session lifetimes are platform settings: SESSION_IDLE_SECONDS bounds idle time,
SESSION_ABSOLUTE_SECONDS bounds the time since directory authentication, and
MAX_TOKEN_LIFETIME_SEC separately caps legacy API and local password bearer tokens. Their ranges
and defaults are listed in Platform settings. A platform administrator can change
them without restarting. Idle activity never changes the original authentication timestamp or
absolute expiry. Increasing a timeout cannot resurrect an expired or revoked session. Absolute
timeout changes apply when a new session is created.
Log out revokes the current browser session, including outstanding incident-stream tickets. Sign out everywhere persists the user's revocation cutoff and asks all API replicas to close their live streams. Every HTTP request and stream recheck consults durable account, session, provider, workspace and membership gates, so a missed live notification cannot restore access. A token issued before a revocation cutoff cannot become a fresh application session.
Ending sessions from the directory
OpenID Connect back-channel logout lets an enabled directory end SRE Platform browser sessions without waiting for their idle or absolute expiry. Enable Provider-initiated logout on an installation sign-in method in Platform administration → Identity providers, or on a workspace sign-in method in Workspace settings → Authentication. Copy the URL shown there into that same OIDC client's back-channel logout setting. The URL contains the provider ID and must be registered exactly.
Before enabling it, verify that the provider's discovery document advertises
backchannel_logout_supported: true, or that its current documentation explicitly supports OpenID
Connect Back-Channel Logout for this client. If session-specific logout is required, also verify
backchannel_logout_session_supported: true. Front-channel logout metadata and a browser logout URL
describe a different protocol and are not sufficient.
The endpoint is public because the signed logout_token is its credential. It accepts only a form
encoded POST whose signature, issuer and audience match that exact active, opted-in provider. The
audience is the browser client ID. The token must have a recent numeric iat, a numeric exp, a
unique token ID, the standard back-channel logout event with a JSON-object value, no nonce, and a
subject or provider session ID. The specification recommends an empty event object but permits
provider extensions. A SHA-256 hash of each token ID is stored in a durable provider-scoped receipt;
the raw token ID is never stored. That receipt and the session effects commit in one transaction, so
a replay is rejected without risking a split claim and revocation. Expired receipts are removed in
bounded batches during later deliveries. Tokens signed with RS256 are accepted. SRE Platform rejects
every other signing algorithm and any multi-audience token because it does not yet persist a
client-specific signing algorithm or trusted extra audiences.
The optional Require logout+jwt token type setting additionally rejects tokens whose protected
header does not contain exactly typ: logout+jwt. Leave it off for providers that implement the
protocol but omit this recommended media type.
A token with a provider session ID is session-scoped. If it also contains a subject, both values must match the same provider, client and browser session. It does not advance the user-wide cutoff. Only when the session ID is absent does a subject logout map every historical session for that exact provider, client and original OIDC subject, advance each mapped user's durable sign-out cutoff, revoke current matching sessions, and close live streams. Already-ended and unknown sessions still return success. Disabling the capability makes the endpoint return not found before it reads a request body.
The callback must be publicly reachable by the directory over HTTPS; a browser-only or private URL
cannot receive server-to-server delivery. A replica-safe ingress budget accepts 600 attempts per
trusted source address per minute before provider lookup or token verification. Exhaustion returns
429 with Retry-After: 60; retry behavior is provider-specific, so verify it during integration.
Limiter failure returns 503 without processing the token. SRE Platform does not implement
front-channel logout, and it does not retain directory access or refresh tokens to revoke them.
Provider availability is not interchangeable. As checked in September 2026, Auth0 documents this feature for Enterprise-plan tenants. The current Okta OIDC SLO guide and Microsoft identity-platform OIDC guide describe front-channel flows; those guides are not evidence that a tenant can deliver this callback. Use the provider's discovery fields or explicit back-channel documentation as the authority.
Provisioning people with SCIM
SCIM 2.0 lets a workspace directory create, update, deactivate and delete user records before those people sign in. Configure it on a workspace sign-in method in Workspace settings → Authentication, or on an installation sign-in method in Platform administration → Identity providers. The settings screen supplies the exact provider-scoped base URL and a bearer token. Copy the token immediately: only its SHA-256 hash is retained, and the plaintext is never shown again.
Set the directory's SCIM base URL to the copied HTTPS URL, use the copied bearer token, and enable
User provisioning. The service implements the SCIM 2.0 User resource, equality filters for
userName and externalId, pagination, PUT, PATCH and DELETE. Groups, bulk operations, sorting and
password provisioning are not advertised. Each URL and token belongs to one identity provider;
neither can read or mutate another provider's accounts.
Choose the identity mapping deliberately:
| OIDC sign-in identity | SCIM field | When to choose it |
|---|---|---|
| Configured subject claim | externalId |
The directory can provision the same stable employee or directory identifier into both protocols |
| Configured subject claim | userName |
The OIDC subject claim is intentionally the same stable value used as SCIM userName |
SRE Platform never assumes that SCIM externalId equals the OIDC sub. At first sign-in, an exact
match using the selected fields creates a durable link. If that match is absent, a verified email may
link only one active, previously unlinked SCIM account. Unverified email, multiple matches and
already-linked accounts are never guessed. Once linked, email changes cannot move the identity to a
different account.
Enable Require a provisioned account only after the directory has completed its first sync and the expected accounts appear in the settings screen. With it off, unmatched people continue through the existing just-in-time sign-in policy. With it on, unmatched people are denied. A linked account that is inactive or deleted is always denied, even if the requirement is later switched off.
Deactivation and deletion advance the linked user's durable revocation cutoff in the same database
transaction as the directory change. Existing browser sessions, bearer requests and live incident
streams are therefore rejected by their normal authoritative checks. A live revoke message closes
streams quickly, but losing that best-effort message cannot restore access. DELETE leaves an internal
tombstone so ownership history is preserved, while the deleted SCIM resource returns 404 and is
excluded from searches as required by
RFC 7644 section 3.6. Reprovisioning the person
creates a new SCIM resource ID; the old ID is never reused.
Rotate the token immediately if it may have been exposed. Rotation invalidates the previous token, and disabling SCIM removes the stored credential. Tokens expire, so schedule directory-side rotation before the date shown in settings. A disabled or expired credential returns the same authentication failure as an unknown token. Use HTTPS in deployed environments and restrict the token to the target directory application. The endpoint applies a bounded, fail-closed request limit before provider lookup and rejects oversized payloads.
Before enforcing provisioning, verify all of these in a test account:
GET <base-url>/ServiceProviderConfigsucceeds with the bearer token.- Creating a User makes it appear under Provisioned accounts.
- A sign-in whose configured subject matches the selected SCIM field succeeds.
- Setting
activetofalseends that person's current access and prevents a fresh sign-in. - Reactivating the same current resource permits a newly authenticated session.
- Rotating the token makes the previous token fail immediately.
Workspace access and existing API credentials
A workspace binding selects a workspace before membership is evaluated:
- A workspace sign-in method belongs to exactly one workspace, so its binding carries no claim value (a null-claim binding) and the ID token needs no workspace claim.
- An installation sign-in method requires its explicitly configured binding claim in the ID token, and the claim value must match a workspace binding exactly. If that claim is missing or unbound, the person stays signed in but unaffiliated. Configure the claim in the directory's ID token; the platform does not guess from email or another membership.
- Removed memberships and suspended or deleting workspaces remain denied. Reauthentication does not recreate a removed membership or elevate its role.
- Platform-administrator access remains separate from workspace ownership.
Existing installation and local API bearer credentials retain signature, audience, lifetime and revocation verification. Session-only directory rows have no API audience and cannot accept an ID token as an API bearer token. A shared issuer is not eligible for ambiguous issuer-only bearer selection; browser sessions retain exact provider/client selection.
Workspace sign-in method setup persists a provisional registration before sign-in, then attaches only its verified founder. Submission respects open, approval-required or closed registration policy. Provisioning writes the workspace, owner, binding and independent DNS challenge. Durable queue work resumes after a restart. Reloading and returning sign-in resume server state rather than replaying browser credentials.
The platform-operator permission
Platform-administrator access is independent of workspace membership. This lets an unaffiliated administrator operate installation-wide settings without gaining access to customer data.
The grant gates every action in the platform administration area, listed in full under What platform administrators can do: registrations, workspace suspension and bindings, user accounts and administrator grants, installation sign-in methods, platform settings, and support sessions. Outside that area it also gates signal policy control on a workspace's Signals page: changing the policy, running an evaluation, switching enforcement on or back to shadow mode, and editing tag-link rules.
The administrator list is global, not per workspace. Bootstrap may grant a known subject immediately or create an email invitation. On the next sign-in with the matching issuer and trusted email claim, the API accepts that invitation and grants administrator access in one owner transaction. The ordinary application role cannot write that allowlist directly. Development-only local login is the only path that provisions itself automatically.
Signing in with a password, for local development only
For everyday local work, prefer the explicitly enabled local email sign-in.
ALLOW_LOCAL_DEVELOPMENT_LOGIN=true requires exactly NODE_ENV=development, a loopback dashboard origin,
and no trusted proxy hops. It binds the API to 127.0.0.1. The passwordless endpoint checks the
actual socket peer, URL host, exact browser Origin and custom request header; it rejects forwarded
requests. It uses the same short-lived bearer tokens, local identity and provisioning path described
below. The endpoint requires the configured development email; unmatched emails continue to company
sign-in. The browser renews an existing local session, but never starts one on page load or after
sign-out. Both local flags default to off.
The legacy password exchange at POST /auth/local/login remains available to development automation
when explicitly enabled. The dashboard uses the single work-email form, not a separate password page.
The API refuses to start if this is switched on while NODE_ENV is production or unset. An
unknown environment is treated as production. Note that the check is an exact string match, so an
environment named prod or staging is not covered by it.
| Variable | Meaning |
|---|---|
ALLOW_LOCAL_PASSWORD_LOGIN |
Enabled only by the exact string true. Anything else leaves it off. |
LOCAL_LOGIN_EMAIL |
The single local account's address. |
LOCAL_LOGIN_PASSWORD |
The shared password. At least 12 characters. |
It also refuses to start if it is switched on with a missing email, a missing password, or a password under 12 characters, and it logs a loud warning at startup whenever it is armed.
How it behaves when enabled:
- A wrong password and an unknown email give the same generic failure. The response never says which half was wrong, and the password comparison takes the same time either way.
- The session lasts up to 15 minutes and is shortened when
MAX_TOKEN_LIFETIME_SECis lower. Its signing key is generated in memory at startup and never written anywhere, so no private key sits in your environment and every restart invalidates outstanding sessions. - A token is only ever checked against the key set belonging to the issuer it claims. A token signed by the local key while claiming to be from an installation sign-in method is rejected, and the reverse too.
- The local provider and its workspace binding with no claim value are persisted, so workspace selection uses the same binding path as every other sign-in method. Its signing keys remain injected process memory only.
- The first successful local sign-in creates an active
local-devfounding and runs the same atomic workspace provisioner used by OIDC onboarding. It also grants the local account operator permission. This is the only automatic operator grant, and it is unreachable unless a local login mode is on.
When both local modes are switched off their routes do not exist, and any token claiming the local issuer is rejected. The dashboard asks the API which sign-in paths exist rather than assuming, so the login screen can never offer one the API does not serve.