Blog · Guides

OAuth token exchange: swapping a token for a narrower one

OAuth 2.0 token exchange explained: subject tokens, audience and scope narrowing, delegation vs impersonation, and the mistakes that break the exchange.

Casdoor Team · November 2, 2026 · 5 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 2, 2026. Spotted a mistake? Tell us.

OAuth token exchange (RFC 8693) takes a token you already hold and returns a new token with different properties: a narrower scope, a different audience, or a different token type. It is the standard way for one service to call another on behalf of a user without passing the original token through every hop.

The most common use is an API gateway. The gateway receives a token with broad scopes, exchanges it for a token that only covers the downstream service, and forwards that. If the downstream service is compromised, the attacker gets a token that is useless anywhere else.

What token exchange is for

  • Scope narrowing. Turn a token with read and write access into a read-only token before calling a reporting service.
  • Audience narrowing. Issue a token whose audience is a specific service, so a token issued for one API cannot be replayed at another.
  • Service-to-service calls on behalf of a user. A frontend service exchanges the user's token for a token the backend accepts, instead of sharing the original.
  • Token type conversion. Exchange an access token for an ID token, or a JWT for an access token, when the next service expects a different format.
  • Cross-domain trust. Exchange a token from a trusted external issuer for a local token, without a client secret.

The core request

A token exchange is a POST to the token endpoint with the token exchange grant type:

Parameter Meaning
grant_type urn:ietf:params:oauth:grant-type:token-exchange
subject_token The token being exchanged
subject_token_type access_token, jwt or id_token
scope Optional; must be a subset of the subject token's scope
audience Optional; the service the new token is for
requested_token_type Optional; the type of token you want back

The response contains a new access token, and usually an ID token and refresh token, for the same user as the subject token.

How Casdoor handles it

Casdoor implements the token exchange grant at /api/login/oauth/access_token. The request includes the client ID and secret, the subject token, its type, and optionally a scope and audience.

Casdoor validates the subject token with the certificate of the application that issued it, which the azp claim identifies, not with the certificate of the requesting client. If the requesting client is not the issuer, the subject token's aud claim must include the requesting client ID. Otherwise Casdoor returns invalid_grant. That rule prevents one application from exchanging another application's tokens unless it was explicitly named as an audience.

The exchange is also rejected when:

  • the subject token is revoked or expired;
  • the subject token has no user, for example a client credentials token;
  • the user is forbidden to sign in;
  • the user is not in the organization of the requesting application, and the application is not shared;
  • the audience is not a known application (invalid_target), or is not in the user's organization and not shared.

With subject_token_type set to id_token, Casdoor looks the token up as an ID token; otherwise it treats it as an access token. An external issuer's token can be the subject too, through federated credentials, without a client secret.

Delegation vs impersonation

RFC 8693 describes two models:

  • Impersonation. The new token represents the user. The downstream service sees the user, not the original caller.
  • Delegation. The new token records both the user and the actor (the service that is acting for the user), usually through an actor token. The downstream service can see that the call was made by a service on the user's behalf.

Delegation is more auditable, but it requires the services and the identity provider to carry the actor information through the chain. Impersonation is simpler and common, but it loses the "who called" context. Decide which one your audit and authorization model needs before you build the exchange.

When not to use token exchange

  • Simple service-to-service calls. If no user is involved, use the client credentials grant. There is no user token to exchange.
  • The downstream service accepts the same token. If the audience and scope already match, pass the token through. An extra exchange adds latency and failure modes.
  • You want to broaden access. Token exchange narrows; it does not grant permissions the subject token did not have.
  • As a substitute for authorization. The exchange decides which token to use, not whether the user may perform the action. The downstream service still has to enforce authorization.

Common mistakes

  1. Exchanging a client credentials token. It has no user, so the exchange cannot produce a user token.
  2. Asking for a broader scope. The scope can only be a subset of the subject token's scope.
  3. Forgetting the audience check. A token issued for one service should not be accepted by another; set and validate aud.
  4. Not handling revoked tokens. The exchange must reject a token that has been revoked or has expired, or the new token silently extends the lifetime of a compromised credential.
  5. Logging tokens. Exchange requests and responses contain bearer credentials; keep them out of logs and traces.
  6. Treating the exchange as authentication. The exchange assumes the subject token is already authentic; the caller still has to be authenticated and authorized to perform the exchange.

FAQ

Is token exchange the same as refresh? No. Refresh gets a new access token for the same client and scopes. Token exchange gets a token with different scope, audience or type, potentially for a different service.

Can the new token have more permissions than the original? No. The scope must be a subset, and the audience must be a service the user can access. Exchange is a narrowing operation.

Does Casdoor support actor tokens for delegation? Casdoor's documented exchange flow focuses on the subject token, audience and scope. Check the current OAuth documentation for actor token support before designing a delegation model around it.

Why does the exchange fail with invalid_grant? The subject token is expired, revoked, issued for a different application that did not name the caller as an audience, or belongs to a user outside the requesting application's organization. The error description usually names the reason.

If you need an identity provider that can issue, narrow and exchange tokens for users and services, Casdoor supports token exchange, client credentials, JWT bearer and federated credentials. Casdoor Cloud starts at $6.67/month billed yearly for a dedicated instance. See the Casdoor OAuth documentation for the exact request format.