How to handle token audience changes when an AI agent acts on behalf of a user?
-
We have a scenario where a user authenticated in a web interface holds a token with a
webaudience. The user interacts with an AI agent through a chat interface, and that agent may need to call downstream services (such as an MCP server) on the user's behalf. However, those downstream services require a token with a different audience (e.g.mcp) rather than the originalwebaudience.The challenge is: how should the user authorize the AI agent to act on their behalf with the correct audience and scopes for the downstream service? We want to ensure the agent can make requests with the appropriate token audience without requiring the user to re-authenticate or manually exchange tokens.
Is OAuth 2.0 Token Exchange (RFC 8693) the right approach here? If so, how should we structure the exchange request so the agent receives a token with the new audience while preserving the user's identity and authorization context?
-
OAuth 2.0 Token Exchange (RFC 8693) is indeed designed for this kind of scenario. It allows you to exchange an existing token (the user's
web-audience token) for a new token with a different audience (e.g.mcp) while maintaining the user's identity and authorization context.Important Note: FusionAuth does not currently implement RFC 8693 (OAuth 2.0 Token Exchange) natively. There is an open GitHub issue tracking this feature request. However, FusionAuth provides alternative approaches to achieve similar outcomes.
How Token Exchange Works (RFC 8693 Concept)
- User authenticates and receives a token with
audience: web. - AI agent receives a request from the user via the chat interface.
- Agent exchanges the token: The agent (or a backend service acting on its behalf) calls the token exchange endpoint, providing:
- The original
web-audience token as thesubject_token - The desired new audience (
mcp) in theaudienceparameter - Optionally, a narrower set of scopes if the downstream service requires fewer permissions
- The original
- New token issued: The authorization server returns a new token with
audience: mcp, tied to the same user identity. - Agent calls downstream service using the new token.
Example Token Exchange Request
POST /oauth2/token Content-Type: application/x-www-form-urlencoded grant_type=urn:ietf:params:oauth:grant-type:token-exchange &subject_token=<user-web-token> &subject_token_type=urn:ietf:params:oauth:token-type:access_token &audience=mcp &scope=mcp:read mcp:writeCurrent Alternatives in FusionAuth
Since RFC 8693 isn't supported yet, here are the recommended approaches:
1. Issue a JWT API
Use the Issue a JWT endpoint to exchange a token from one application for a token for another application. This is FusionAuth's implementation of SSO for access tokens:
GET /api/jwt/issue?applicationId={targetApplicationId} Authorization: Bearer <existing_access_token>This returns a new JWT with the target application's audience, preserving the user's identity. The user must be registered in both applications.
2. JWT Populate Lambda
Use a JWT Populate Lambda to customize the
audclaim directly. You can add multiple audiences to avoid token swapping:function populate(jwt, user, registration) { // Add multiple audiences jwt.aud = ['web', 'mcp', 'https://api.example.com']; }3. Vend a JWT API
For more complex delegation scenarios, use the Vend a JWT endpoint to create a custom JWT with free-form claims (except reserved claims like
iat,exp,amr, andcnf).Key Considerations
- Authorization: The agent should be a registered OAuth client with permission to perform token exchanges. You may want to restrict which clients can exchange tokens and for which audiences.
- Scope narrowing: The new token can have a subset of the original token's scopes, ensuring least-privilege access to the downstream service.
- User consent: Depending on your security requirements, you may want to prompt the user to authorize the agent's access to the downstream service the first time this exchange happens.
- Application registration: When using the Issue JWT approach, ensure the user is registered in both the source and target applications.
This approach avoids re-authentication and cleanly separates concerns: the user holds their
webtoken, and the agent dynamically obtains the correct token for each downstream service it needs to call.Related Documentation
- OAuth 2.0 Grant Types - Token Exchange Grant - Overview of RFC 8693 token exchange
- Issue a JWT API - Exchange tokens between applications (FusionAuth's current solution)
- Vend a JWT API - Create custom JWTs for complex scenarios
- JWT Populate Lambda - Customize JWT claims including audience
- GitHub Issue #1471 - Track RFC 8693 implementation progress
- User authenticates and receives a token with
-
D dan has marked this topic as solved
-
D dan moved this topic from Staged