Authentication and Authorization
This domain checks that you can pick the right OIDC/OAuth 2.0 flow, choose between the org and a custom authorization server, validate tokens correctly, and reason about policies, scopes and claims.
Flows
- Authorization Code + PKCE (
code_challenge_method=S256) for SPAs, native and mobile apps, and server-side web; confidential clients add a client secret. Okta requires PKCE for SPA app types. - Client Credentials for machine-to-machine: access token only - no ID token, no refresh token.
- Device Authorization for input-constrained devices.
- Interaction Code for embedded sign-in with Identity Engine via the Sign-In Widget or SDKs.
- Implicit and Resource Owner Password are legacy; do not propose them.
Which authorization server
- Org AS (
/oauth2/v1/authorize) issues tokens only for Okta's own APIs - not for your custom audience. - Custom AS (
/oauth2/{id}/v1/..., includingdefault) is required for your own APIs. Its access policies and rules decide which clients and users may obtain tokens, which grant types apply, token lifetimes, and whether claims are included.
Tokens and claims
- ID token: JWT with
iss(AS issuer),aud(client_id),sub,exp,iat,nonce,auth_time. Validate the signature via the/v1/keysJWKS, theniss,aud,expandnonce. - Access token: what the resource server checks. It may be opaque or a JWT; if a JWT, validate locally via JWKS, otherwise call
/v1/introspect. - Refresh token: on a custom AS it requires the
offline_accessscope, and rotation is configured on the AS. - Claims are driven by
scopeplus expression-based mappings such asuser.profile.department, or agroupsclaim filtered by a group-name regex.
Worked example
An SPA's /token call returns invalid_grant. Two likely causes: the code_verifier does not hash (S256) to the original code_challenge, or the code was already redeemed. The exchange happens once, within the code lifetime, and the redirect_uri must be byte-identical to the value sent at /authorize.
Traps
Wildcards or fragments in redirect_uri (https required except localhost, and match is exact); skipping state or nonce validation; comparing aud against the API audience in an ID token; and using the org AS for a custom API, which fails policy evaluation.