Skip to content

Token Management

Overview

The Token Management API (client.token) provides methods for managing OAuth 2.0 tokens throughout their lifecycle:

  • Retrieving access tokens with automatic refresh
  • Token Exchange (RFC 8693)
  • Token Introspection (RFC 7662)
  • Token Revocation (RFC 7009)

Getting Access Tokens

Automatic Refresh

getAccessToken() returns a valid access token, automatically refreshing it if expired:

const accessToken = await client.token.getAccessToken();
// Use the token
const response = await fetch('https://api.example.com/data', {
headers: { Authorization: `Bearer ${accessToken}` },
});

The SDK handles the refresh flow automatically:

  1. Checks if the stored access token is still valid
  2. If expired (or within the refreshSkewSeconds window), uses the refresh token to obtain a new access token
  3. Saves the new tokens to storage
  4. Returns the new access token

Getting the Full Token Set

const tokens = await client.token.getTokens();
if (tokens) {
console.log(tokens.accessToken);
console.log(tokens.refreshToken);
console.log(tokens.idToken);
console.log(tokens.expiresAt); // epoch seconds
console.log(tokens.scope);
}

Getting the ID Token

const idToken = await client.token.getIdToken();
if (idToken) {
// Decode claims (for display purposes only — always verify on server)
const claims = decodeIdToken(idToken);
console.log(claims.sub, claims.name, claims.email);
}

Checking Authentication State

const isAuthenticated = client.token.isAuthenticated();

TokenSet

PropertyTypeDescription
accessTokenstringOAuth 2.0 access token
refreshTokenstring | undefinedRefresh token
idTokenstring | undefinedOIDC ID token
tokenType'Bearer'Token type
expiresAtnumberExpiration time (epoch seconds)
scopestring | undefinedGranted scopes

Token Exchange (RFC 8693)

Token Exchange allows you to exchange one token for another — for example, exchanging an access token for one with a different audience (impersonation, delegation, cross-service calls).

const result = await client.token.exchange({
subjectToken: currentAccessToken,
subjectTokenType: 'access_token',
audience: 'https://api.internal.example.com',
scope: 'read:data',
});
console.log(result.tokens.accessToken);
console.log(result.issuedTokenType);

TokenExchangeRequest

ParameterTypeDefaultDescription
subjectTokenstringRequiredThe token to exchange
subjectTokenTypestring'access_token''access_token', 'refresh_token', or 'id_token'
audiencestringTarget audience for the new token
scopestringRequested scopes for the new token
requestedTokenTypestringDesired token type
actorTokenstringActor token (for delegation)
actorTokenTypestringActor token type

TokenExchangeResult

PropertyTypeDescription
tokensTokenSetThe exchanged tokens
issuedTokenTypestringThe type of token issued

Token Introspection (RFC 7662)

Introspection checks whether a token is active and retrieves its metadata:

const info = await client.token.introspect({
token: accessToken,
tokenTypeHint: 'access_token',
});
if (info.active) {
console.log('Token is valid');
console.log('Subject:', info.sub);
console.log('Scopes:', info.scope);
console.log('Expires:', info.exp);
} else {
console.log('Token is inactive or expired');
}

IntrospectTokenOptions

ParameterTypeDefaultDescription
tokenstringRequiredThe token to introspect
tokenTypeHintstring'access_token', 'refresh_token', or 'id_token'

IntrospectionResponse

PropertyTypeDescription
activebooleanWhether the token is active
scopestring | undefinedToken scopes
client_idstring | undefinedClient that requested the token
usernamestring | undefinedResource owner username
token_typestring | undefinedToken type
expnumber | undefinedExpiration timestamp
iatnumber | undefinedIssued at timestamp
substring | undefinedSubject identifier
audstring | undefinedAudience
issstring | undefinedIssuer
jtistring | undefinedToken identifier

Token Revocation (RFC 7009)

Revoke a token when it is no longer needed:

await client.token.revoke({
token: refreshToken,
tokenTypeHint: 'refresh_token',
});

RevokeTokenOptions

ParameterTypeDefaultDescription
tokenstringRequiredThe token to revoke
tokenTypeHintstring'access_token' or 'refresh_token'

Multi-Tab Token Refresh

When multiple browser tabs are open, the SDK prevents concurrent refresh requests using an operation ID mechanism:

  • The leader tab performs the refresh
  • Other tabs wait for the leader to complete and then read the updated tokens from storage
  • This prevents token race conditions and unnecessary refresh requests
// The SDK handles this automatically.
// Each tab calls getAccessToken() and the SDK coordinates internally.
const accessToken = await client.token.getAccessToken();

Token Events

The SDK emits events during token operations. See Events for details.

EventDescription
token:refreshingToken refresh started
token:refreshedToken refresh succeeded
token:refresh_failedToken refresh failed
token:expiringToken is about to expire
token:expiredToken has expired
token:exchangedToken exchange completed
client.on('token:refreshed', (event) => {
console.log('Token refreshed, expires at:', event.expiresAt);
});
client.on('token:refresh_failed', (event) => {
console.log('Refresh failed:', event.error.code);
if (!event.willRetry) {
// Final failure — redirect to login
redirectToLogin();
}
});

Next Steps