---
title: "Token Exchange"
description: "How to exchange tokens using OAuth 2.0 Token Exchange (RFC 8693)"
---

# Token Exchange

This example demonstrates how to use OAuth 2.0 Token Exchange (RFC 8693) for token delegation scenarios, from simple resource access to advanced service impersonation.

## Simple Token Delegation

The easiest way to get started with token exchange is using the `get_access_token_for_resource` helper method:

```python
from keycardai.oauth import Client

def simple_token_delegation():
    """
    Simple token delegation example - exchange a user token for resource-specific access.
    """
    with Client("https://zoneid.keycard.cloud") as client:
        # Request access to Google Calendar API
        calendar_token = client.get_access_token_for_resource(
            "https://www.googleapis.com/auth/calendar.readonly",
            "user_access_token"
        )
        print(f"Calendar Access Token: {calendar_token}")
        
        # Request access to GitHub API
        github_token = client.get_access_token_for_resource(
            "https://api.github.com",
            "user_access_token"
        )
        print(f"GitHub Access Token: {github_token}")
        
        return calendar_token, github_token

# Run simple delegation
calendar_token, github_token = simple_token_delegation()
```

## Async Simple Token Delegation

```python
from keycardai.oauth import AsyncClient

async def async_simple_token_delegation():
    """
    Async version of simple token delegation.
    """
    async with AsyncClient("https://zoneid.keycard.cloud") as client:
        # Request access to Google Calendar API
        calendar_token = await client.get_access_token_for_resource(
            "https://www.googleapis.com/auth/calendar.readonly",
            "user_access_token"
        )
        print(f"Calendar Access Token: {calendar_token}")
        
        # Request access to GitHub API
        github_token = await client.get_access_token_for_resource(
            "https://api.github.com",
            "user_access_token"
        )
        print(f"GitHub Access Token: {github_token}")
        
        return calendar_token, github_token

# Run async simple delegation
import asyncio
calendar_token, github_token = asyncio.run(async_simple_token_delegation())
```

## Advanced Token Exchange with Service Impersonation

This example shows a real-world scenario where a service needs to impersonate a user to access multiple APIs on their behalf:

```python
from keycardai.oauth import Client, AsyncClient
from keycardai.oauth.types.models import TokenExchangeRequest

def service_impersonation_example():
    """
    Advanced token exchange example demonstrating service impersonation
    where a service exchanges tokens to access multiple resources on behalf of a user.
    """
    with Client("https://zoneid.keycard.cloud") as client:
        
        # Method 1: Using TokenExchangeRequest object for full control
        request = TokenExchangeRequest(
            subject_token="user_original_token_xyz123",
            subject_token_type="urn:ietf:params:oauth:token-type:access_token",
            audience="api.microservice.company.com",
            actor_token="service_identity_token_abc456", 
            actor_token_type="urn:ietf:params:oauth:token-type:access_token",
            requested_token_type="urn:ietf:params:oauth:token-type:access_token",
            scope="calendar:read drive:write slack:message",
            resource="https://apis.company.com/user-data"
        )
        
        response = client.exchange_token(request)
        print(f"Impersonated Token: {response.access_token}")
        print(f"Token Type: {response.token_type}")
        print(f"Expires In: {response.expires_in} seconds")
        print(f"Issued Token Type: {response.issued_token_type}")
        
        # Method 2: Using keyword arguments for simpler cases
        delegated_response = client.exchange_token(
            subject_token="user_original_token_xyz123",
            subject_token_type="urn:ietf:params:oauth:token-type:access_token",
            audience="api.notifications.company.com",
            scope="notifications:send",
            timeout=30.0
        )
        
        print(f"Delegated Token: {delegated_response.access_token}")
        
        return response, delegated_response

# Run the service impersonation
impersonated_token, delegated_token = service_impersonation_example()
```

## Async Advanced Token Exchange

```python
async def async_service_impersonation_example():
    """
    Async version of advanced token exchange with service impersonation.
    """
    async with AsyncClient("https://zoneid.keycard.cloud") as client:
        
        # Method 1: Using TokenExchangeRequest object for full control
        request = TokenExchangeRequest(
            subject_token="user_original_token_xyz123",
            subject_token_type="urn:ietf:params:oauth:token-type:access_token",
            audience="api.microservice.company.com",
            actor_token="service_identity_token_abc456",
            actor_token_type="urn:ietf:params:oauth:token-type:access_token", 
            requested_token_type="urn:ietf:params:oauth:token-type:access_token",
            scope="calendar:read drive:write slack:message",
            resource="https://apis.company.com/user-data"
        )
        
        response = await client.exchange_token(request)
        print(f"Impersonated Token: {response.access_token}")
        print(f"Token Type: {response.token_type}")
        print(f"Expires In: {response.expires_in} seconds")
        print(f"Issued Token Type: {response.issued_token_type}")
        
        # Method 2: Using keyword arguments for simpler cases
        delegated_response = await client.exchange_token(
            subject_token="user_original_token_xyz123",
            subject_token_type="urn:ietf:params:oauth:token-type:access_token",
            audience="api.notifications.company.com", 
            scope="notifications:send",
            timeout=30.0
        )
        
        print(f"Delegated Token: {delegated_response.access_token}")
        
        return response, delegated_response

# Run the async service impersonation
import asyncio
impersonated_token, delegated_token = asyncio.run(async_service_impersonation_example())
```

## Key Features Demonstrated

- **Service Impersonation**: Using `actor_token` to impersonate users while maintaining audit trails
- **Resource-Specific Tokens**: Requesting tokens for specific audiences and resources
- **Flexible API**: Both `TokenExchangeRequest` objects and keyword arguments supported
- **Scope Management**: Fine-grained permission control with custom scopes
- **Token Metadata**: Access to token expiration, type, and issuer information
- **Async Support**: Full async/await support for high-performance applications