Token Exchange (OBO)
Mandaitor implements OAuth 2.0 Token Exchange (RFC 8693) to enable On-Behalf-Of (OBO) delegation chains. This allows AI agents to act on behalf of authenticated users while preserving the original user's identity in the delegation chain.
How It Works
- A user authenticates with their identity provider (Auth0, Okta, Entra ID)
- The user creates a mandate delegating authority to an AI agent
- The AI agent exchanges the user's token for a scoped delegation token
- The delegation token includes the original user's identity (
actclaim) - Downstream services can verify both the agent's identity and the delegating user
API
POST /identity/token-exchange
Request
{
"subject_token": "eyJhbGciOiJSUzI1NiIs...",
"subject_token_type": "urn:ietf:params:oauth:token-type:access_token",
"mandate_id": "mdt_01ABC123",
"scope": "construction.validation.approve",
"audience": "https://downstream-service.example.com"
}
Response
{
"access_token": "eyJpc3MiOiJtYW5kYWl0b3I6...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "construction.validation.approve",
"issued_token_type": "urn:ietf:params:oauth:token-type:access_token",
"delegation": {
"mandate_id": "mdt_01ABC123",
"principal": "oidc:entra:abc-123@def-456",
"delegate": "agent:my-ai-agent",
"provider": "ENTRA_ID"
}
}
Delegation Token Claims
The issued delegation token contains:
| Claim | Description |
|---|---|
iss | mandaitor:<tenant_id> |
sub | Delegate's subject ID |
aud | Target audience (downstream service) |
act.sub | Original user's subject ID |
act.provider | Identity provider that verified the user |
mandate_id | Mandate authorizing the delegation |
scope | Granted scopes from the mandate |
delegation_chain | Full delegation chain metadata |
SDK Usage
import { MandaitorClient } from "@mandaitor/sdk";
const client = new MandaitorClient({
apiKey: "mk_live_...",
tenantId: "tnt_your_tenant",
});
const result = await client.exchangeToken({
subject_token: userAccessToken,
mandate_id: "mdt_01ABC123",
scope: "construction.validation.approve",
audience: "https://downstream-api.example.com",
});
// Use the delegation token
const response = await fetch("https://downstream-api.example.com/action", {
headers: {
Authorization: `Bearer ${result.access_token}`,
},
});
Validation
The token exchange endpoint validates:
- Subject token — Resolved via the identity provider registry
- Mandate existence — The mandate must exist and be
ACTIVE - Principal match — The subject token identity must match the mandate's principal
- Audit trail — A
VERIFICATION_ALLOWEDevent is emitted