Blog · Guides

ID token vs access token: identity and authorization are different tokens

An ID token tells the client who the user is; an access token lets the client call an API. Why mixing them up causes outages and security bugs, with a validation checklist for each.

Casdoor Team · November 1, 2026 · 3 min read

This guide is written by the team that builds Casdoor and describes the standards as published (listed under Sources), with notes on how Casdoor implements them as of November 1, 2026. Spotted a mistake? Tell us.

OIDC logins produce two tokens with similar-looking names and completely different jobs:

  • The ID token tells the client who the user is.
  • The access token lets the client call an API.

Sending one where the other belongs is a common source of bugs — and occasionally of security holes. This article explains the difference and how to handle each.

The ID token

A signed JWT issued by the OpenID provider. Its audience is the client: it exists so the client can verify that the user authenticated and read basic claims.

Typical claims:

Claim Meaning
iss Issuer
sub Stable user identifier
aud The client ID this token was issued to
exp, iat Expiry and issue time
nonce Binds the token to the login request
name, email Profile claims, per scopes

Rules:

  • Validate it on the client (signature, issuer, audience, expiry, nonce).
  • Never send it to APIs. The API has no use for it and should not accept it as an authorization credential.
  • Do not use it as a long-term session. Persist the claims you need server-side; keep tokens short.

The access token

An OAuth token that represents a grant, not a person. Its audience is the resource server, and it carries scopes that say what the client may do.

Rules:

  • Validate it on the API: signature or introspection, issuer, audience, scopes, expiry.
  • Treat it as opaque on the client unless the API design documents otherwise.
  • Never use it for identity. An access token may be a JWT with a user ID in it; that does not make it a login credential.
  • Keep it short-lived, with refresh tokens for continuity.

Side by side

ID token Access token
Purpose Authentication: who is the user Authorization: what may the client do
Audience The client (your app) The resource server (your API)
Typical format JWT Opaque or JWT
Validated by The client The API
Sent to APIs No Yes, in the Authorization header
Lifetime Short Short, renewed by refresh token
Claims User identity Scopes, grant context

The mistakes that actually happen

1. The API accepts ID tokens as authorization. An ID token is addressed to the client, not the API. Accepting it means any client that can get an ID token for itself can call the API with it. Check the aud claim on the API side.

2. The client uses the access token as identity. Access tokens can be opaque; parsing them for a user ID is undefined behavior that breaks the day the provider rotates formats.

3. Profile data is read from the access token. If you need richer claims, call the userinfo endpoint with the access token, or request the scopes that put them in the ID token.

4. Tokens are stored where XSS can reach them. Single-page apps storing both tokens in localStorage turn any XSS into full account takeover. Prefer httpOnly cookies with a backend-for-frontend, or memory-only storage.

5. No audience check anywhere. Both tokens are JWTs; both validate as signatures; without an audience check, they are interchangeable. That is exactly what you do not want.

The refresh token

A third token, for continuity: the client exchanges it for new access tokens without bothering the user. It is not used for identity or for API calls, and it is as sensitive as a password.

  • Rotate it on use when the provider supports rotation.
  • Revoke it on logout, password change and suspicious activity.
  • Store it server-side where possible.

A validation checklist

Client, for the ID token:

  1. Signature against the provider's JWKS.
  2. iss matches the provider.
  3. aud contains this client ID.
  4. Not expired, with a small clock skew.
  5. nonce matches the request.
  6. Algorithm is expected; reject none.

API, for the access token:

  1. Signature or introspection.
  2. iss matches the provider.
  3. aud contains this API.
  4. Required scopes are present.
  5. Not expired.
  6. Revocation checked where the token is long-lived.

If both sides run the right checks, mixing the tokens is impossible by construction.

Related reading: what OpenID Connect is, what OAuth 2.0 is and OAuth grant types.