OAuth Token Exchange

How to exchange your OAuth token for b.well's OAuth token

b.well supports the OAuth Token Exchange standard: https://www.rfc-editor.org/rfc/rfc8693.

You can pass your OAuth token to b.well and receive a b.well OAuth token

curl --request POST \
  --url https://api.client-sandbox.icanbwell.com/identity/oauth/token \
  --header 'content-type: application/x-www-form-urlencoded' \
  --data grant_type=urn:ietf:params:oauth:grant-type:token-exchange \
  --data subject_token={{idToken}} \
  --data subject_token_type=urn:ietf:params:oauth:token-type:jwt \
  --data requested_token_type=urn:ietf:params:oauth:token-type:access_token

For Python:

from typing import Dict, Any
import requests


def exchange_token(id_token: str) -> Dict[str, Any]:
    """
    Exchange an ID token for an access token using OAuth 2.0 token exchange.
    
    Args:
        id_token: The JWT ID token to exchange
        
    Returns:
        Dictionary containing the token response with access_token and other fields
        
    Raises:
        requests.exceptions.RequestException: If the HTTP request fails
        requests.exceptions.HTTPError: If the server returns an error status code
    """
    url: str = "https://api.client-sandbox.icanbwell.com/identity/oauth/token"
    
    headers: Dict[str, str] = {
        "content-type": "application/x-www-form-urlencoded"
    }
    
    data: Dict[str, str] = {
        "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
        "subject_token": id_token,
        "subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
        "requested_token_type": "urn:ietf:params:oauth:token-type:access_token"
    }
    
    try:
        response: requests.Response = requests.post(
            url=url,
            headers=headers,
            data=data
        )
        
        # Raise an exception for HTTP error status codes (4xx, 5xx)
        response.raise_for_status()
        
        return response.json()
        
    except requests.exceptions.HTTPError as e:
        print(f"HTTP Error: {e}")
        print(f"Response: {response.text}")
        raise
    except requests.exceptions.RequestException as e:
        print(f"Request failed: {e}")
        raise


# Example usage:
if __name__ == "__main__":
    # Replace with your actual ID token
    id_token: str = "your_id_token_here"
    
    try:
        token_response: Dict[str, Any] = exchange_token(id_token)
        print("Token exchange successful!")
        print(f"Access Token: {token_response.get('access_token')}")
        print(f"Full Response: {token_response}")
    except Exception as e:
        print(f"Token exchange failed: {e}")

The response follows the OAuth Token Exchange standard:

{
  "access_token": "eyJraWQiOiJU....",
  "issued_token_type": "urn:ietf:params:oauth:token-type:access_token",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "eyJjdHk....."
}

You can now use the access_token returned to access b.well APIs.