OIDC / OAuth2
The OIDC issuer and signing keys belong to the organization. Within that issuer, each app group has its own member scope. The same customer can have different sub values in two groups, even when the email claim matches. Any compliant client (with a custom SDK count of zero) can integrate by pointing Authority at the org’s issuer.
Issuer & discovery
Section titled “Issuer & discovery”Issuer: https://api.axowl.com/api/public/orgs/{slug}Discovery: {issuer}/.well-known/openid-configurationJWKS: published in discovery; tokens are RS256, per-org keysThe issuer is derived from the host you call, so it always matches the environment you are on —
and it is the exact string in the iss claim your library will validate. Read it from discovery
rather than hard-coding it.
Key rotation
Section titled “Key rotation”Rotating the organization’s signing key (Settings → Keys → Rotate signing key) is safe for live traffic. The new key signs every token issued from that moment; the previous key stays in the JWKS document and is still accepted for verification for a grace period (24 hours by default), so tokens issued before the rotation keep working until they expire. Libraries that cache the JWKS pick up the new key on the first unknown kid — the official SDKs and ASP.NET Core’s JWT bearer handler all do this — so no restart is needed. Every key has its own kid; verify by kid, never by position in the keys array.
Endpoints
Section titled “Endpoints”| Method · Route | Purpose |
|---|---|
GET /authorize | Begin auth-code flow (redirects to hosted login). |
GET /authorize/continue | Resume after login; issues the authorization code. |
POST /token | Exchange code (or refresh token) for tokens. PKCE S256 supported. Rotating refresh tokens. |
GET /userinfo | Identity claims for the bearer token. |
GET /end-session | RP-initiated logout. |
POST /token — body
Section titled “POST /token — body”Send the body as application/x-www-form-urlencoded. No client_secret is needed: PKCE (or the
rotating refresh token) authenticates the client.
| Field | Type | Notes |
|---|---|---|
grant_type | string (required) | authorization_code or refresh_token. Anything else answers unsupported_grant_type. |
code | string | The authorization code from /authorize. Single-use. |
redirect_uri | string | Must equal the one sent to /authorize. |
client_id | string | Must equal the client the code or refresh token was issued to. |
code_verifier | string | PKCE verifier (S256). |
refresh_token | string | Present when grant_type=refresh_token. Rotates on use. |
Errors are 400 with the standard OAuth shape { "error", "error_description" } — invalid_request
for a missing field or wrong content type, invalid_grant for a code or refresh token that is
invalid, expired, already used, or does not match the client, redirect URI or PKCE verifier,
and unauthorized_client when the client is not allowed the refresh_token grant.
POST /token — 200 response
Section titled “POST /token — 200 response”| Field | Type | Notes |
|---|---|---|
access_token | string | RS256-signed access token. |
id_token | string | OIDC ID token. |
token_type | string | Bearer. |
expires_in | integer | Access token lifetime in seconds (set per application). |
scope | string | The granted scopes. |
refresh_token | string | Present when the client is allowed the refresh_token grant. Single-use; each refresh returns a new one. |
Token use and revocation
Section titled “Token use and revocation”Use the access token for userinfo, application APIs and introspection. An ID token identifies the user to its client and can serve as that client’s end-session hint. Check the issuer, the intended audience, the signature, expiration and token use. New tokens carry an issuance time (iat) and a unique identifier (jti), including tokens issued during the same second.
Local SDK signature verification cannot observe logout, a suspended badge, a removed membership or a revoked RP session. Use online introspection when the decision must reflect current access. Single-token revocation applies to the presented credential. An administrative badge block applies across credentials and remains in force until release. On release, tokens issued at or before the cutoff second stay invalid. A legacy token with no issuance time can use its signed not-before time for this check. With neither timestamp it must be replaced.
If an integration currently sends an ID token to an API, switch its Authorization header to the access token before upgrading. Legacy access tokens with a matching signed audience remain usable until expiration or revocation. The gRPC verifier also accepts the legacy application_key claim when it agrees with the audience. Machine tokens issued after reactivation carry a new issuance time. An undated machine token issued before suspension must be replaced.