Skip to Content

Token Exchange

Le Token Exchange (RFC 8693) permet à un client d’échanger un access token existant contre un nouveau avec un sujet, une audience ou des scopes différents. Cela active deux patterns enterprise clés : usurpation d’identité (agir comme un autre utilisateur) et délégation (agir au nom d’un utilisateur avec l’acteur original enregistré).

Cas d’usage courants :

  • Un admin usurpe l’identité d’un utilisateur pour déboguer les problèmes qu’il rencontre
  • Un service frontend délègue le token utilisateur à un service backend avec une audience restreinte
  • Un agent du support agit au nom d’un client avec une traçabilité d’audit complète via le claim act
  • Un microservice restreint un token à large scope à un token avec scope minimal pour un service en aval

Usurpation d’Identité vs Délégation

Le token exchange supporte deux patterns distincts :

PatternLe Sujet Change ?Claim actCas d’Usage
Usurpation d’identitéOui — le sub du nouveau token est l’utilisateur cibleContient l’identité de l’acteur originalAdmin déboguant la session d’un utilisateur
DélégationNon — sub reste l’utilisateur originalContient l’identité du service délégantAppel service-service préservant le contexte utilisateur

Usurpation d’Identité

Le claim sub du token résultant est remplacé par l’utilisateur cible. L’acteur original est enregistré dans le claim act pour que l’action soit entièrement vérifiable via audit :

{ "sub": "target-user-id", "iss": "https://auth.votredomaine.com", "type": "user", "act": { "sub": "admin-user-id", "email": "[email protected]" } }

Délégation

Le claim sub reste le même (l’utilisateur original), mais un claim act enregistre le service intermédiaire :

{ "sub": "original-user-id", "iss": "https://auth.votredomaine.com", "type": "user", "aud": "backend-service", "act": { "sub": "frontend-service-client-id" } }

Configuration dans la Console

Active le Token Exchange

Dans la Console Auris, va dans Applications et sélectionne l’application qui effectuera les échanges de tokens. Dans l’onglet Paramètres, active Activer Token Exchange.

Configure les Types d’Échange Autorisés

Sélectionne quels types d’échange l’application est autorisée à effectuer :

TypeDescription
Usurpation d’identitéÉchange un token contre un ayant un sujet différent (nécessite la permission impersonate:users)
DélégationÉchange un token contre un ayant une audience différente (nécessite la permission delegate:tokens)

Assigne les Permissions

Assure-toi que les utilisateurs ou comptes de service effectuant le token exchange ont les permissions appropriées :

  • impersonate:users — Requis pour les échanges d’usurpation d’identité
  • delegate:tokens — Requis pour les échanges de délégation

Ces permissions peuvent être assignées via les rôles dans Console → Rôles → [Rôle] → Permissions.


Implémentation

const AURIS_DOMAIN = 'https://auth.votredomaine.com' const CLIENT_ID = 'votre-client-id' const CLIENT_SECRET = 'votre-client-secret' // Usurpation : Admin agissant comme un utilisateur spécifique async function impersonateUser(adminToken, targetUserId) { const response = await fetch(`${AURIS_DOMAIN}/api/auth/token`, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ grant_type: 'urn:ietf:params:oauth:grant-type:token-exchange', subject_token: adminToken, subject_token_type: 'urn:ietf:params:oauth:token-type:access_token', requested_token_type: 'urn:ietf:params:oauth:token-type:access_token', requested_subject: targetUserId, client_id: CLIENT_ID, client_secret: CLIENT_SECRET, }), }) if (!response.ok) { const error = await response.json() throw new Error(`Token exchange échoué : ${error.error_description}`) } return await response.json() // { access_token: "...", token_type: "Bearer", expires_in: 3600 } } // Délégation : Frontend passant le contexte utilisateur au backend async function delegateToBackend(userToken, backendAudience) { const response = await fetch(`${AURIS_DOMAIN}/api/auth/token`, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ grant_type: 'urn:ietf:params:oauth:grant-type:token-exchange', subject_token: userToken, subject_token_type: 'urn:ietf:params:oauth:token-type:access_token', requested_token_type: 'urn:ietf:params:oauth:token-type:access_token', audience: backendAudience, client_id: CLIENT_ID, client_secret: CLIENT_SECRET, }), }) return await response.json() } // Utilisation const impersonatedToken = await impersonateUser(adminAccessToken, 'user-123') const delegatedToken = await delegateToBackend(userAccessToken, 'billing-service')

Paramètres de la Requête

ParamètreObligatoireDescription
grant_typeOuiDoit être urn:ietf:params:oauth:grant-type:token-exchange
subject_tokenOuiL’access token existant à échanger
subject_token_typeOuiDoit être urn:ietf:params:oauth:token-type:access_token
requested_token_typeNonPar défaut urn:ietf:params:oauth:token-type:access_token
requested_subjectNonID de l’utilisateur cible pour l’usurpation. Omettre pour la délégation.
audienceNonAudience cible pour le nouveau token. Utilisé dans la délégation.
scopeNonScope demandé pour le nouveau token. Ne peut pas dépasser le scope du token original.
client_idOuiLe client ID de l’application
client_secretOuiLe client secret de l’application

Le Claim act

Le token exchange ajoute toujours un claim act (acteur) au token résultant. Ce claim crée une chaîne vérifiable montrant qui a effectivement effectué l’échange :

Usurpation simple

{ "sub": "user-456", "act": { "sub": "admin-123" } }

Délégation en chaîne

Si un token qui contient déjà un claim act est échangé à nouveau, la chaîne s’allonge :

{ "sub": "user-456", "act": { "sub": "service-b", "act": { "sub": "service-a", "act": { "sub": "admin-123" } } } }

Cette chaîne fournit une traçabilité d’audit complète de chaque service et utilisateur impliqué dans la séquence de token exchange.


Valider les Tokens Échangés

Quand ton API reçoit un token avec un claim act, tu peux l’inspecter pour comprendre la chaîne de délégation :

import { verifyToken } from '@auris/js/jwt-verify' async function handleRequest(req) { const payload = await verifyToken(req.headers.authorization.slice(7), { jwksUrl: 'https://auth.votredomaine.com/.well-known/jwks.json', }) // Vérifie s'il s'agit d'un token usurpé ou délégué if (payload.act) { console.log(`Action effectuée par ${payload.act.sub} agissant comme ${payload.sub}`) // Tu pourrais vouloir journaliser ou restreindre certaines opérations pour les tokens usurpés if (isDestructiveOperation(req)) { throw new Error('Les opérations destructives ne sont pas autorisées via des tokens usurpés') } } }

Considérations de Sécurité

  • Application des permissions : L’usurpation d’identité nécessite impersonate:users et la délégation nécessite delegate:tokens. Ce sont des permissions sensibles qui doivent être accordées avec parcimonie.
  • Journal d’audit : Chaque token exchange est enregistré avec l’acteur original, le sujet cible, le type d’échange et le timestamp. Ces logs sont visibles dans la Console Auris sous Logs.
  • Restriction du scope : Les tokens échangés ne peuvent pas avoir un scope plus large que le token original. Tu peux seulement restreindre le scope, jamais l’étendre.
  • Client confidentiel obligatoire : Le token exchange nécessite l’authentification du client. Les clients publics ne peuvent pas effectuer d’échanges.
  • Durée du token : Les tokens échangés ont une durée par défaut plus courte (1 heure) et ne peuvent pas dépasser la durée restante du token original.

L’usurpation d’identité est une capacité puissante. N’assigne la permission impersonate:users qu’aux rôles administrateurs de confiance. Envisage d’ajouter des contrôles supplémentaires dans la couche applicative, comme bloquer l’usurpation pour les opérations destructives ou exiger un motif/numéro de ticket.


Endpoint API

POST/api/auth/token

Endpoint token. Pour le token exchange, définis grant_type=urn:ietf:params:oauth:grant-type:token-exchange avec les paramètres décrits ci-dessus. Nécessite l’authentification du client.

GET/api/oauth/token-exchangesRequires: view:token_exchanges

Liste les récents événements de token exchange. Filtrable par utilisateur, type (usurpation/délégation) et plage de dates.


Permissions Requises

OpérationPermission
Effectuer un échange d’usurpationimpersonate:users
Effectuer un échange de délégationdelegate:tokens
Voir l’historique des token exchangesview:token_exchanges
Activer Token Exchange sur une applicationmanage:applications

Guides Associés