How to Use exchangeToken with Organizations for Multi-Tenant Authentication

To use exchangeToken with organizations for multi-tenant authentication, pass the optional organization parameter when calling exchangeToken() in the Auth0 JavaScript SDK, which Auth0 validates and embeds into the resulting access token payload to scope the request to a specific tenant.

The auth0/auth0-auth-js repository provides a JavaScript SDK that supports OAuth 2.0 Token Exchange (RFC 8693) and Token Vault flows for secure token conversion. When building multi-tenant applications, you can leverage the organization parameter to ensure exchanged tokens contain the specific tenant context, enabling a single application to securely serve users across different Auth0 organizations.

Understanding Token Exchange Flows

The Auth0 JavaScript SDK implements two distinct flows that support the organization parameter for multi-tenant scenarios. Both flows allow you to exchange existing tokens while applying organization-specific policies and claims to the resulting session.

Token Exchange Profiles (RFC 8693)

This flow converts tokens from custom identity providers or legacy systems into Auth0-issued tokens. According to the source code in packages/auth0-auth-js/src/auth-client.ts, the SDK appends the organization parameter to the grant request body at lines 737-739 when invoking the internal #exchangeProfileToken method.

The TypeScript interface ExchangeProfileOptions in packages/auth0-auth-js/src/types.ts (lines 440-447) defines the optional organization field as a string, accepting either an organization ID (e.g., org_abc123) or the organization name.

Token Vault Exchanges

For scenarios where you exchange Auth0 tokens for third-party provider tokens (such as Google or Salesforce), the Token Vault flow applies. The SDK includes the organization parameter in the request body at auth-client.ts lines 921-922 when constructing Token Vault exchange parameters.

The TokenVaultExchangeOptions interface in types.ts (lines 407-414) provides the equivalent type definition for this flow, ensuring type safety when specifying the organization context.

Implementing Organization-Aware Token Exchange

To implement multi-tenant authentication, instantiate the AuthClient and include the organization property in your exchange options. The SDK automatically propagates this value to Auth0's authorization server.

Exchanging Custom Tokens with Organization Context

When integrating with external identity systems, use the Token Exchange Profile flow with an organization ID to ensure the new token is scoped correctly:

import { AuthClient } from '@auth0/auth0-auth-js';

const authClient = new AuthClient({ 
  domain: 'your-domain.auth0.com',
  clientId: 'your-client-id'
});

async function exchangeCustomTokenWithOrg() {
  const response = await authClient.exchangeToken({
    subjectTokenType: 'urn:acme:custom-token',
    subjectToken: '<CUSTOM_TOKEN_FROM_YOUR_BACKEND>',
    audience: 'https://api.example.com',
    scope: 'openid profile read:data',
    organization: 'org_abc123', // Organization ID or name
  });

  console.log('Access token scoped to org:', response.accessToken);
}

Exchanging Auth0 Tokens for External Provider Access

For Token Vault scenarios where you exchange an Auth0 access token for a third-party provider token, maintain the organization context to ensure consistent tenant isolation:

async function exchangeForGoogleWithOrg() {
  const response = await authClient.exchangeToken({
    connection: 'google-oauth2',
    subjectToken: '<AUTH0_ACCESS_TOKEN>',
    organization: 'org_xyz789', // Maintains organization context
  });

  console.log('Google access token for org:', response.accessToken);
}

Maintaining Organization Context During Refresh

While exchangeToken handles initial conversions, you can preserve organization context during token refresh operations using getTokenByRefreshToken:

async function refreshTokenForOrg() {
  const response = await authClient.getTokenByRefreshToken({
    refreshToken: '<REFRESH_TOKEN>',
    organization: 'org_abc123', // Preserves organization claim
    scope: 'openid profile email',
  });

  console.log('Refreshed token includes org claim:', response.accessToken);
}

How Auth0 Validates Organization Context

When you supply the organization parameter, Auth0 performs validation before issuing the new token. The authorization server verifies that the specified organization exists and that the authenticated user is a member of that organization (or is authorized via an organization login hint). Upon successful validation, Auth0 embeds the organization ID directly into the access token payload, allowing your downstream APIs to identify the tenant context without requiring additional database lookups.

Summary

  • The organization parameter enables multi-tenant authentication across both Token Exchange Profiles and Token Vault flows in the auth0-auth-js SDK.
  • Source code in packages/auth0-auth-js/src/auth-client.ts (lines 737-739 and 921-922) automatically appends this parameter to the respective grant request bodies.
  • Type definitions in packages/auth0-auth-js/src/types.ts expose organization as an optional string in both ExchangeProfileOptions (lines 440-447) and TokenVaultExchangeOptions (lines 407-414).
  • Auth0 validates organization membership and embeds the organization ID into the exchanged token's payload for downstream tenant identification.
  • The parameter maintains consistency across initial token exchange and refresh token flows via getTokenByRefreshToken.

Frequently Asked Questions

What is the difference between Token Exchange Profiles and Token Vault in Auth0?

Token Exchange Profiles implement RFC 8693 to convert external or legacy tokens into Auth0-issued tokens. Token Vault performs the inverse operation, exchanging valid Auth0 tokens for third-party provider tokens (such as Google OAuth2 or Salesforce) to call external APIs on behalf of your users. Both flows support the organization parameter as implemented in auth-client.ts.

Can I use an organization name instead of an organization ID with exchangeToken?

Yes. The organization parameter accepts either an organization ID (formatted as org_ followed by alphanumeric characters) or the organization name. The TypeScript definitions in types.ts specify this as a flexible string type for both ExchangeProfileOptions and TokenVaultExchangeOptions.

Does the organization parameter work with refresh token flows?

Yes. While exchangeToken handles initial token conversion, the getTokenByRefreshToken method also accepts an organization parameter to ensure refreshed tokens maintain the same organization context and claims as the original session.

What happens if the user does not belong to the specified organization?

Auth0 validates the user's organization membership before issuing the token. If the user is not a member of the specified organization (and no valid login hint is provided), the token exchange request fails with an authorization error, preventing unauthorized cross-tenant access.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →