OAuth endpoints
ScaiKey exposes a full OIDC provider surface in two flavors: platform (for GLOBAL-scoped apps) and tenant-scoped (for apps that belong to one tenant).
Discovery#
Always start by fetching the discovery document — it's the source of truth for endpoint URLs and supported scopes.
| Flavor | URL |
|---|---|
| Platform | $SCAIKEY/api/v1/platform/oauth/.well-known/openid-configuration |
| Tenant | $SCAIKEY/api/v1/auth/tenants/{slug}/.well-known/openid-configuration |
The discovery doc lists every other endpoint. Read it once at startup with your OIDC library and you mostly don't need this page.
Authorize endpoint#
Starts the authorization_code flow. User-facing — your app redirects the browser here.
1 2 | |
Standard OIDC query parameters: response_type=code, client_id, redirect_uri, scope, state, nonce. PKCE: code_challenge, code_challenge_method=S256.
Optional: prompt=login (force re-auth), prompt=none (silent — fails if no active session), login_hint (prefill email), idp_hint (preselect a federated IdP).
The platform variant redirects unauthenticated users to a tenant-agnostic login page where they enter their email; ScaiKey then determines their tenant. The tenant variant goes straight to that tenant's login page.
Token endpoint#
The workhorse — exchange a grant for tokens.
1 2 | |
Content-Type: application/x-www-form-urlencoded. Client authentication via Authorization: Basic (recommended) or client_id + client_secret form fields.
grant_type=authorization_code#
| Field | Required | Notes |
|---|---|---|
code |
yes | The code from the authorize redirect |
redirect_uri |
yes | Must match what was sent to authorize |
code_verifier |
required for public clients | PKCE verifier |
client_secret |
required for confidential clients |
grant_type=client_credentials#
| Field | Required | Notes |
|---|---|---|
client_secret |
yes | Confidential client only — SPA/NATIVE not allowed |
scope |
no | Space-separated scopes. If omitted, defaults to the app's full allowed_scopes |
grant_type=refresh_token#
| Field | Required | Notes |
|---|---|---|
refresh_token |
yes | The token to exchange |
Refresh tokens are one-time-use — the response includes a new refresh token; the previous one is invalidated.
grant_type=urn:ietf:params:oauth:grant-type:token-exchange#
| Field | Required | Notes |
|---|---|---|
subject_token |
yes | The token to exchange (must be ScaiKey-issued) |
subject_token_type |
yes | urn:ietf:params:oauth:token-type:access_token is the only supported value |
audience |
yes | The target application's client_id or name (case-insensitive lookup) |
requested_token_type |
no | Always returns access_token regardless |
scope |
no | Requested scopes; intersected with subject and target |
client_secret |
yes | Requesting app must be confidential |
The target application's token_exchange_allowed must be true. See Concepts → OAuth and OIDC for the full rules.
grant_type=urn:ietf:params:oauth:grant-type:device_code#
| Field | Required | Notes |
|---|---|---|
device_code |
yes | From the device-authorize call |
Poll this endpoint at the interval in the device-authorize response (default 5 s). Responds with authorization_pending until the user approves, then issues tokens.
UserInfo endpoint#
1 2 | |
Bearer-authenticated. Returns OIDC identity claims for the user the token belongs to. client_credentials tokens (no user) get a 401 here.
JWKS endpoint#
1 2 | |
The platform and tenant flavors return the same keys (signing is shared). Use whichever your library is pointed at.
Revoke endpoint (tenant-scoped only)#
1 | |
Revokes a refresh token. RFC 7009. Returns 200 OK even if the token was unknown (anti-enumeration).
Introspect endpoint (tenant-scoped only)#
1 | |
RFC 7662. Returns { "active": true, ...claims } for a valid access token, { "active": false } otherwise. Useful for opaque-token consumers (though all ScaiKey tokens are JWTs and can be self-verified).
End_session endpoint (RP-initiated logout)#
1 2 | |
Must be reached by a browser redirect, not a server-side call — the endpoint reads the SSO cookie to identify the session.
| Parameter | Notes |
|---|---|
id_token_hint |
Strongly recommended. Signature-verified, expiry-tolerant. Supplies sid (session) and aud (client), enabling token revocation when the cookie is absent. |
post_logout_redirect_uri |
Validated against the client's registered logout_uris (exact) or redirect_uris (same origin: scheme + host + port). Unaccepted values are ignored. |
state |
Echoed back on the redirect. |
client_id |
Identifies the application for redirect validation when id_token_hint is absent. |
Effects:
- Terminates the SSO session (
terminated_reason=user_logout) and clears the SSO cookie. - Revokes refresh tokens bound to that session, plus those of the client named in
id_token_hint. - Does not revoke access tokens — self-contained JWTs, valid until
exp. Introspect if you need immediate revocation.
Then redirects to post_logout_redirect_uri if it passed validation, otherwise to the default logout confirmation page.
Full walkthrough: Login and logout for web applications.
For GLOBAL apps that don't have a tenant slug to put in the URL, use the platform variant — it identifies the session via the SSO cookie, not the URL path.