Identity for AI

Token Exchange in the AuthPlayground

Retargeting trust for enterprise AI.

When Sarah asks her AI assistant to prepare a meeting briefing, the assistant needs to access customer data. In an enterprise AI architecture, the software component performing this work could be a Model Context Protocol (MCP) gateway, an AI agent, or a backend service brokering access to enterprise APIs. In the playground, an API gateway represents this software actor.

The authorization system must track two distinct identities:

  1. Sarah (the human subject): Her authority allows access to customer data (the protected resource).

  2. The API gateway (the software actor): The gateway acts on Sarah’s behalf while accessing those APIs.

The software actor shouldn’t impersonate Sarah or use a broad service credential that loses the connection to her identity. OAuth 2.0 Token Exchange (RFC 8693) solves this problem.

The token exchange model

Token exchange provides a standard way to take an existing, trusted security context and request a new token for a different audience or purpose while preserving the delegation relationship.

Token exchange does more than simply convert a token. RFC 8693 distinguishes the subject from the actor in a delegated access token. The resulting token proves both that the access is for Sarah, and that the API gateway is the specific actor exercising this authority. This is delegation rather than impersonation.

The AuthPlayground implementation

Entities involved: Client application, IdP (authorization server), resource server

The AuthPlayground demonstrates the Token Exchange flow in two steps:

  1. Obtain subject and actor tokens.

  2. Perform the delegation token exchange.

Step 1: Obtain subject and actor tokens

This step begins with an Authorization Code flow that creates both the subject (user) and actor credentials.

In a production architecture, the human subject and software actor typically establish their credentials through separate identity lifecycles. For simplicity, the playground creates both credentials during the same prerequisite step, but they remain distinct identities.

The executed request looks like this:

POST /idp/token
Content-Type: application/x-www-form-urlencoded

{
  "grant_type": "authorization_code",
  "code": "<authorization_code>",
  "redirect_uri": "<callback>",
  "client_id": "playground-demo-client",
  "code_verifier": "<pkce_verifier>"
}

The response contains several artifacts. The access token represents the authenticated user context:

{
  "sub": "demo-user@example.com",
  "scope": "openid delegation",
  "client_id": "playground-demo-client",
  "aud": "playground-demo-client"
}

The ID token represents the same user. Notice the may_act claim. This claim indicates that api-gateway@example.com is eligible to act on behalf of the subject.

{
  "sub": "demo-user@example.com",
  "email": "demo-user@example.com",
  "may_act": {
    "sub": "api-gateway@example.com"
  }
}

The response also contains an actor_token that represents the API gateway identity. This token is used to identify the actor in the delegation exchange.

{
  "sub": "api-gateway@example.com",
  "client_id": "playground-demo-client",
  "iss": "https://.../idp",
  "aud": "https://.../idp"
}

Before token exchange happens, two distinct identities have been established:

  • Subject: The party on whose behalf the token is being requested. In the subject_token this is demo-user@example.com.

  • Actor: The party that will exercise the delegated authority. In the actor_token this is api-gateway@example.com.

Step 2: Perform the delegation token exchange

The client application sends a token exchange request with both tokens to the authorization server:

POST /idp/token
Content-Type: application/x-www-form-urlencoded

{
  "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
  "subject_token": "<id_token>",
  "subject_token_type": "urn:ietf:params:oauth:token-type:id_token",
  "actor_token": "<actor_token>",
  "actor_token_type": "urn:ietf:params:oauth:token-type:access_token",
  "requested_token_type": "urn:ietf:params:oauth:token-type:access_token",
  "audience": "<resource_server>",
  "client_id": "playground-demo-client",
  "scope": "openid read"
}

Important inputs:

  • subject_token: Identifies Sarah as the subject.

  • actor_token: Identifies the API gateway performing the action.

  • requested_token_type: Asks for an OAuth access token.

  • audience: Targets the token to the protected resource.

  • scope: Defines the permissions needed for this operation.

The authorization server evaluates the request using the may_act claim from the subject token to verify that the gateway is authorized to act for Sarah. If policy allows the exchange, the server issues a new access token.

The difference between may_act and act

These claims represent different stages of delegation:

  • Before the exchange: The may_act claim in the subject token expresses an authorized relationship (the gateway is eligible to act for Sarah).

  • After the exchange: The act claim in the new access token identifies the actual actor (the API gateway) currently exercising this delegated authority.

What’s in the exchanged token?

The new composite access token contains:

{
  "sub": "demo-user@example.com",
  "scope": "openid read",
  "client_id": "playground-demo-client",
  "act": {
    "sub": "api-gateway@example.com",
    "iss": "https://.../idp"
  },
  "iss": "https://.../idp",
  "aud": "https://.../rs"
}

This resource-facing token preserves the entire context: the human subject (sub), the software actor (act), the target resource (aud), and the requested permissions (scope).

The same model applies when an MCP gateway brokers access to enterprise systems such as Salesforce or ServiceNow. While specific integrations vary, the principle remains the same: preserve the subject and actor relationship while issuing a security context appropriate for the target.

Retargeting trust

The original identity token was intended for the client application. The exchanged access token is intended for the resource server. Token exchange retargets trust by changing the security context instead of simply copying Sarah’s original token.

ID Token                                 Access Token
sub = Sarah            ------->          sub = Sarah
aud = Client           Token Exchange    act = API Gateway
may_act = API Gateway                    aud = Resource Server
                                         scope = read

How token exchange relates to other protocol concepts

It doesn’t always require a human

While the playground demonstrates human delegation, token exchange also applies to machine-oriented flows where the subject is a workload. The key requirement isn’t a human user, but rather the need to transform a trusted security context into a new token appropriate for the requested target.

It isn’t workload identity

Don’t confuse the actor_token with the broader workload identity problem.

  • Workload identity (SPIFFE / SVID): Establishes trust in a runtime workload (which workload is this?).

  • Token exchange: Transforms an existing security context (what token should be issued for the requested target?).

A production system might use workload identity (such as a SPIFFE JWT-SVID) as a trusted source to establish the actor during a token exchange. The token exchange flow in the playground doesn’t demonstrate this specific integration.

It differs from ID-JAG and transaction tokens

ID-JAG is a specific profile used to carry delegated user identity into another authorization domain. Token exchange can act as a building block for ID-JAG, but they are not synonymous.

Transaction tokens carry trusted transaction context through a workload call chain inside a trust domain. Token exchange is the mechanism used when a calling workload requests a Txn-Token from the token service.

Key takeaways

The key to token exchange is distinguishing between the subject and the actor. In the enterprise AI scenario, Sarah is the subject and the API gateway is the actor.

Before the exchange, may_act indicates that the gateway is eligible to act for Sarah. During the exchange, the client sends Sarah’s subject_token and the gateway’s actor_token. After policy evaluation, the resulting access token keeps Sarah as sub and records the gateway in act.

Token exchange gives the resource-facing security context a much more accurate story than either of these alternatives:

  • Sarah made the API call directly.

  • A generic gateway service account made the API call.

Neither alternative is entirely true. The reality is that the API gateway (or an MCP gateway in an enterprise AI architecture) acts using authority delegated from Sarah for this audience and requested access. Token exchange represents this distinction.