Skip to Content

Token Exchange (RFC 8693)

Dans les architectures microservices, un seul token émis au login n’est souvent pas adapté à tous les services de la chaîne d’appels. Les problèmes courants :

  • Le token a trop de privilèges pour un service spécifique (violation du principe du moindre privilège)
  • Le token a le mauvais audience pour le service cible
  • Un admin doit usurper l’identité d’un utilisateur pour les opérations de support
  • Un service intermédiaire doit déléguer l’identité de l’utilisateur original à un service downstream

Token Exchange (RFC 8693) fournit un mécanisme standard pour échanger un token existant contre un nouveau token avec une portée, un audience ou un sujet différent.

La Requête d’Échange

POST /api/auth/token Content-Type: application/x-www-form-urlencoded Authorization: Bearer ORIGINAL_ACCESS_TOKEN grant_type=urn:ietf:params:oauth:grant-type:token-exchange &subject_token=ORIGINAL_ACCESS_TOKEN &subject_token_type=urn:ietf:params:oauth:token-type:access_token &requested_token_type=urn:ietf:params:oauth:token-type:access_token &audience=payment-service &scope=payments:read payments:create

Paramètres :

ParamètreRequisDescription
subject_tokenOuiToken représentant l’identité à échanger
subject_token_typeOuiType du subject_token (access_token, id_token, refresh_token)
requested_token_typeNonType du token désiré en retour
audienceNonService(s) destinataire(s) du nouveau token
scopeNonScopes pour le nouveau token (doit être sous-ensemble du sujet)
actor_tokenNonToken de l’acteur qui effectue la délégation
actor_token_typeNonType de l’actor_token

Impersonation vs Délégation

Token Exchange supporte deux modes fondamentaux avec des significations et cas d’usage différents.

Impersonation

L’acteur agit en tant que le sujet. Le token résultant ne peut pas être distingué de celui que le sujet aurait obtenu directement.

Cas d’usage : Support technique qui doit tester un problème spécifique à l’utilisateur.

// Token résultant { "sub": "user_alice", // Alice est le sujet "act": { "sub": "user_admin" // Admin est l'acteur (trace d'audit) } }

L’impersonation requiert la permission impersonate:users sur le compte de l’acteur.

Délégation

L’acteur agit en faveur de le sujet, mais son identité est clairement distincte. Le sujet original reste visible dans le token.

Cas d’usage : API Gateway qui délègue la requête d’Alice au service Order, qui la délègue ensuite au service Payment.

// Token résultant { "sub": "user_alice", // Alice est toujours le sujet "act": { "sub": "service_api_gateway" // Acteur direct } }

La délégation requiert la permission delegate:tokens sur le compte du service acteur.

Chaînes de Délégation

Pour les architectures microservices profondes, le claim act peut être imbriqué pour tracer toute la chaîne de délégation :

{ "sub": "user_alice", "act": { "sub": "service_order", "act": { "sub": "service_payment", "act": { "sub": "service_notification" } } } }

La profondeur maximale de chaîne par défaut est 5 niveaux. Cela prévient les chaînes de délégation infinies et aide à détecter les cycles accidentels.

La profondeur de chaîne maximale est configurable par application dans Administration → Applications → [Application] → Token Exchange.

Propriétés de Sécurité

Réduction de Portée Uniquement

Les tokens échangés ne peuvent jamais avoir plus de scopes que le token sujet original. Tenter d’étendre les scopes résulte en un 400 Bad Request.

Piste d’Audit

Tous les échanges de tokens sont enregistrés dans les audit logs avec :

  • Identité de l’acteur
  • Identité du sujet
  • Type d’opération (impersonation/délégation)
  • Scopes demandés vs accordés
  • Audience du token résultant

Durée de Vie Réduite

Les tokens échangés ont par défaut une durée de vie de 50% du temps restant du token sujet. Cela limite la fenêtre d’exposition si un token intermédiaire est compromis.

Configuration dans la Console

Dans Administration → Applications → [Application] → Token Exchange :

ParamètreDescription
Activer Token ExchangeActiver le grant type pour cette application
Permettre l’impersonationPermettre aux acteurs d’usurper l’identité d’autres utilisateurs
Permettre la délégationPermettre aux services de déléguer les identités utilisateur
Profondeur max de chaîneNiveaux d’imbrication act maximum (défaut : 5)
Durée de vie token échangéPourcentage du temps restant du sujet (défaut : 50%)

Exemple TypeScript — Microservice

// order-service délègue à payment-service pour Alice async function createPaymentOnBehalfOfUser( userToken: string, paymentDetails: PaymentDetails ): Promise<string> { // Échanger le token utilisateur contre un token payment-service scoped const exchangeRes = await fetch('https://auth.yourdomain.com/api/auth/token', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', Authorization: `Bearer ${SERVICE_TOKEN}`, // token du service order }, 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', actor_token: SERVICE_TOKEN, actor_token_type: 'urn:ietf:params:oauth:token-type:access_token', audience: 'payment-service', scope: 'payments:create', // NB : scope réduit — pas accès à tout le token utilisateur original }), }) const { access_token } = await exchangeRes.json() // Utiliser le token échangé pour appeler payment-service const paymentRes = await fetch('https://payments.internal/api/payments', { method: 'POST', headers: { Authorization: `Bearer ${access_token}` }, body: JSON.stringify(paymentDetails), }) return paymentRes.json() }

Concepts Associés

  • Tokens — Structure des access tokens, claims et durées de vie
  • OAuth 2.0 & OIDC — Le cadre d’autorisation sous-jacent
  • Fine-Grained Authorization — Combiner Token Exchange et FGA pour le contrôle d’accès M2M
  • DPoP — Lier les tokens échangés à des clés cryptographiques