Safeguard
Security Guides•

Access token vs ID token vs refresh token: who uses which?

Three tokens, three audiences. The ID token is for your app, the access token is for an API, the refresh token is for the authorization server. Do not mix them.

Safeguard Security Team
4 min read

An ID token tells your app who signed in. An access token lets your app call an API. A refresh token lets your app get new access tokens from the authorization server. Each has a different audience, so sending one where another belongs is a common source of bugs and holes.

The three tokens side by side

ID tokenAccess tokenRefresh token
Defined byOpenID ConnectOAuth 2.0OAuth 2.0
Meant forThe client appThe resource server (API)The authorization server
AnswersWho authenticated?What may this client do?Can I get a new access token?
FormatAlways a JWTOften opaque, sometimes a JWTUsually opaque
Sent to an API?NoYesNever

ID token

The OpenID Connect Core spec defines the ID token as a security token with claims about the authentication of an end user by an authorization server. It is a JWT. Your app checks the signature, issuer, audience and expiry, then uses the sub claim as the stable user identifier.

The ID token is addressed to your client. Its audience must include your client ID. It is not meant to be forwarded to an API as proof of permission.

Access token

RFC 6749 describes access tokens as credentials used to access protected resources, representing specific scopes and durations of access. The string is usually opaque to the client. The client does not need to read it. The API either looks it up or, if it is a JWT, validates it locally.

Because an access token is a bearer credential, anyone holding it can use it until it expires. That is why short lifetimes and narrow scopes matter. RFC 9700 says the privileges of an access token should be restricted to the minimum needed.

Refresh token

Refresh tokens are credentials used to obtain new access tokens when the current one expires, or to obtain additional access tokens with the same or narrower scope. Issuing one is optional and left to the authorization server.

Treat it as the most sensitive of the three, because it outlives the access token. RFC 9700 says refresh tokens for public clients must be sender constrained or use refresh token rotation. For confidential clients, they can be used only by the client they were issued to.

Common mistakes

  1. Using the ID token as an API credential. The API was not its audience.
  2. Using an access token as proof of login. It was issued to call an API, and its format may be opaque to your app.
  3. Logging tokens. All three are secrets while valid.
  4. Putting a refresh token where scripts can read it, such as browser storage, without a plan for theft.
  5. Skipping audience checks on the API. A JWT access token is valid for the resource it names, not every API that trusts the same issuer.

A quick test for code review

For every place a token is read, ask who the intended recipient is. If the answer is not the code that receives it, there is a bug. A short list in your design notes, naming which token goes to which component, catches most mix ups before they ship.

Quick check

Can I decode an access token in my front end to read the user's name?

You should not rely on it. Access tokens are meant for the API and may be opaque. Use the ID token or the UserInfo endpoint for profile data.

Do I always get a refresh token?

No. RFC 6749 says issuing a refresh token is optional and at the discretion of the authorization server.

Safeguard's SBOM and dependency scanning shows which auth libraries you ship and which have known advisories. A free scan is available.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.