Avnology ID
SDKsTypeScript SDKOAuth 2.1

Token Exchange

Delegate and impersonate users with RFC 8693 token exchange using the TypeScript SDK.

Token Exchange

Token exchange (RFC 8693) enables delegation and impersonation. A trusted service can exchange its own token for a token that represents a user, with full audit trail via the act claim.

exchangeToken()

Exchange a token to act on behalf of a user (delegation) or as a user (impersonation).

client.oauth.exchangeToken(params: TokenExchangeParams): Promise<TokenSet>

Parameters

NameTypeRequiredDescription
subjectTokenstringyesToken of the user to act on behalf of
subjectTokenType"access_token" | "id_token"yesType of the subject token
actorTokenstringnoToken of the actor (for delegation -- who is acting)
actorTokenType"access_token"noType of the actor token
scopesstring[]noRequested scopes for the exchanged token
audiencestringnoTarget audience for the exchanged token

Returns

Promise<TokenSet> -- Exchanged token set. The access token contains an act claim identifying the actor.

Delegation (acting on behalf of a user)

The most common pattern. An admin or support agent gets a token that represents the user, with the act claim recording who is actually making the request.

import { AvnologyId } from "@avnology/sdk-typescript";

const adminClient = new AvnologyId({
  baseUrl: "https://api.id.avnology.com",
  clientId: "app_admin_portal",
  clientSecret: "sk_live_...",
});

// Exchange: admin token -> token acting as user
const delegatedTokens = await adminClient.oauth.exchangeToken({
  subjectToken: userAccessToken,          // The user's token
  subjectTokenType: "access_token",
  actorToken: adminAccessToken,           // The admin's token
  actorTokenType: "access_token",
  scopes: ["openid", "profile", "email"], // Limit to needed scopes
});

// The resulting token represents the user but includes act claim
const claims = adminClient.oauth.decodeIdToken(delegatedTokens.idToken);
console.log(claims.sub);     // "usr_user123" -- the user
console.log(claims.act.sub); // "usr_admin456" -- the admin acting

Impersonation (admin support tool)

For customer support tools that need to see what the user sees.

// Admin initiates impersonation
const impersonationTokens = await adminClient.oauth.exchangeToken({
  subjectToken: "eyJ...",  // Target user's access token
  subjectTokenType: "access_token",
  scopes: ["openid", "profile", "email"],
});

// Use the impersonation token to make API calls as the user
const userClient = new AvnologyId({
  baseUrl: "https://api.id.avnology.com",
  clientId: "app_admin_portal",
});
userClient.setTokens(impersonationTokens);

// This returns the user's data, not the admin's
const session = await userClient.getSession();
console.log(session.identity.email); // User's email

Security constraints

Token exchange has strict security requirements enforced by the server:

RequirementDescription
token_exchange scopeThe client must have the token_exchange scope granted
Admin roleThe actor must have an admin role in the organization
Audit trailAll token exchanges are recorded in the audit log
TTL limitExchanged tokens have a maximum TTL of 1 hour
Depth limitToken exchange chains are limited to depth 1 (no re-delegation)
Rate limitMaximum 10 exchanges per minute per actor

Common errors

Error classHTTP statusWhen
InsufficientScopeError403Client missing token_exchange scope
ForbiddenError403Actor lacks admin role
InvalidGrantError400Subject token invalid or expired
RateLimitError429Too many exchange requests

See also

On this page