Skip to main content

What to do next, from wherever you are

From a rendered error page at /authorize. The client never sees it. Something about the client's registration is wrong — the client_id, the redirect_uri, the tenant in the URL. Fix the request, or the registration, and start again. Nothing was created server-side.

From a redirect carrying error. Match state to the request you started, check iss, and give up on this attempt. login_required has two causes: prompt=none forbade the interaction that was needed, in which case retry without prompt; or the request carried an id_token_hint and somebody else signed in, in which case retrying unchanged will keep failing until the hinted user is the one at the keyboard. invalid_scope, unsupported_response_type, request_not_supported and the PKCE invalid_requests are bugs in the client, not transient failures; retrying unchanged produces the same answer.

From a code. Verify state and iss first. Then redeem it at /token with the same redirect_uri and the code_verifier you kept, within the tenant's code lifetime (60 seconds by default), exactly once. Do not retry a redemption that returned invalid_grant — if it succeeded once, retrying revokes the grant you just received.

From an access token. Send it as Authorization: Bearer … to /userinfo or to your own API. It lives 300 seconds. A resource server validating it should verify the signature against the tenant's JWKS, then typ: at+jwt, iss, exp, and that it is named in aud — and then check scope for whatever the call requires. A resource server named in aud can instead call /introspect (RFC 7662), authenticating with its own client credentials, to learn whether the grant behind the token has since been revoked or its session has ended — the one check local validation alone cannot make before exp. A client holding either the access token or its refresh token can also end the grant deliberately with /revoke (RFC 7009) — see Token introspection and revocation.

From a refresh token. Present it at /token when the access token is about to expire, and replace your stored copy with the one that comes back. Never retry a refresh with the token you already sent: that is indistinguishable from a stolen token being replayed, and it revokes the family. If a refresh returns invalid_grant, discard everything and start Path A over — the grant is gone, whether through reuse detection, expiry, or a replayed authorization code.

From an ID token. It is for the client, not for an API — never send it as a bearer token; /userinfo refuses it. Verify it, read sub, name and email from it, and then it has done its job.

From invalid_client at /token. Check which method the client is registered for. Presenting the right secret the wrong way is refused exactly like the wrong secret.

From here, to administer a tenant rather than act as a client of one. the admin paths documents the admin API — the endpoints under /admin/tenants/{tenant}/ — separately from these pages, because it serves an operator rather than an application integrator. the console paths documents the console gateway under /console, which signs an administrator in and forwards the console's calls to that API.