Token Exchange (RFC 8693)
El problema: un token no sirve para todo
En una arquitectura moderna, una solicitud puede atravesar múltiples servicios:
Usuario → Frontend → API Gateway → Servicio de pedidos → Servicio de pagos → Servicio de notificacionesCada servicio en esta cadena tiene diferentes niveles de confianza, diferentes scopes y diferentes audiencias. Usar el mismo token en todas partes crea problemas:
| Problema | Descripción |
|---|---|
| Tokens con excesivos privilegios | El token del frontend tiene read:users write:orders manage:payments pero el Servicio de Pagos solo necesita process:payments |
| Audiencia incorrecta | Un token emitido para frontend-app no debería ser aceptado por payment-service |
| Suplantación | Un admin necesita depurar la cuenta de un usuario actuando como ese usuario |
| Delegación | El Servicio A necesita llamar al Servicio B en nombre del usuario, pero el Servicio B necesita saber tanto el usuario original como la identidad del servicio que llama |
El Token Exchange de OAuth 2.0 (RFC 8693) proporciona un protocolo estandarizado para intercambiar un token de seguridad por otro, con control preciso sobre el sujeto, la audiencia y el scope del token resultante.
Cómo funciona el Token Exchange
La solicitud de Token Exchange
POST /api/auth/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:token-exchange
&subject_token=eyJhbGciOiJSUzI1NiJ9...
&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=process:payments
&actor_token=eyJhbGciOiJSUzI1NiJ9...
&actor_token_type=urn:ietf:params:oauth:token-type:access_tokenParámetros de la solicitud
| Parámetro | Requerido | Descripción |
|---|---|---|
grant_type | Sí | Siempre urn:ietf:params:oauth:grant-type:token-exchange |
subject_token | Sí | El token que se está intercambiando |
subject_token_type | Sí | El tipo del subject token |
requested_token_type | Opcional | El tipo deseado para el token de salida |
audience | Opcional | El servicio o API de destino que consumirá el nuevo token |
scope | Opcional | Los scopes solicitados. Debe ser un subconjunto de los scopes del subject token. |
actor_token | Opcional | El token de la parte que realiza el intercambio (el “actor”) |
actor_token_type | Condicional | Requerido si actor_token está presente |
Casos de uso
1. Delegación (service-to-service)
El Servicio de Pedidos llama al Servicio de Pagos en nombre del usuario:
POST /api/auth/token
grant_type=urn:ietf:params:oauth:grant-type:token-exchange
&subject_token=<token_del_usuario>
&actor_token=<token_del_servicio_de_pedidos>
&audience=payment-service
&scope=process:paymentsEl token resultante contiene:
{
"sub": "usr_alice",
"act": { "sub": "svc_order-service" },
"aud": "payment-service",
"scope": "process:payments"
}El claim act indica que el Servicio de Pedidos actúa en nombre de Alice — sin suplantar a Alice.
2. Suplantación (para depuración de admin)
Un admin obtiene un token con sub establecido a otro usuario:
POST /api/auth/token
grant_type=urn:ietf:params:oauth:grant-type:token-exchange
&subject_token=<token_del_admin>
&requested_subject=usr_target_userLa suplantación requiere el permiso impersonation:grant en el access token del admin. Este permiso debe otorgarse explícitamente en la Consola — no se incluye por defecto en ningún rol, ni siquiera en el de administrador.
3. Restricción de audiencia
Reducir un token de amplio alcance a un token de propósito específico:
POST /api/auth/token
grant_type=urn:ietf:params:oauth:grant-type:token-exchange
&subject_token=<token_amplio>
&audience=analytics-service
&scope=read:eventsTipos de tokens
RFC 8693 define URNs estandarizados para tipos de tokens:
| URN del tipo de token | Descripción |
|---|---|
urn:ietf:params:oauth:token-type:access_token | Access token de OAuth 2.0 |
urn:ietf:params:oauth:token-type:refresh_token | Refresh token de OAuth 2.0 |
urn:ietf:params:oauth:token-type:id_token | ID token de OpenID Connect |
urn:ietf:params:oauth:token-type:jwt | JWT genérico |