Intercambio de Tokens
El Intercambio de Tokens (RFC 8693) permite a un cliente intercambiar un access token existente por uno nuevo con un sujeto, audiencia o alcance diferente. Esto habilita dos patrones empresariales clave: suplantación (actuar como otro usuario) y delegación (actuar en nombre de un usuario con el actor original registrado).
Casos de uso comunes:
- Un administrador suplanta a un usuario para depurar problemas que está experimentando
- Un servicio frontend delega su token de usuario a un servicio backend con una audiencia restringida
- Un agente de soporte actúa en nombre de un cliente con auditoría completa a través del claim
act - Un microservicio reduce un token amplio a uno de alcance mínimo para un servicio downstream
Suplantación vs Delegación
El intercambio de tokens soporta dos patrones distintos:
| Patrón | ¿Cambia el Sujeto? | Claim act | Caso de Uso |
|---|---|---|---|
| Suplantación | Sí — el sub del nuevo token es el usuario destino | Contiene la identidad del actor original | Admin depurando la sesión de un usuario |
| Delegación | No — el sub sigue siendo el usuario original | Contiene la identidad del servicio que delega | Llamada servicio a servicio preservando el contexto del usuario |
Suplantación
El claim sub del token resultante se reemplaza por el usuario destino. El actor original se registra en el claim act para que la acción sea completamente auditable:
{
"sub": "target-user-id",
"iss": "https://auth.tudominio.com",
"type": "user",
"act": {
"sub": "admin-user-id",
"email": "[email protected]"
}
}Delegación
El claim sub permanece igual (el usuario original), pero un claim act registra el servicio intermediario:
{
"sub": "original-user-id",
"iss": "https://auth.tudominio.com",
"type": "user",
"aud": "backend-service",
"act": {
"sub": "frontend-service-client-id"
}
}Configuración en la Consola
Activar el Intercambio de Tokens
En la Consola de Auris, ve a Aplicaciones y selecciona la aplicación que realizará los intercambios de tokens. En la pestaña Configuración, activa Habilitar Intercambio de Tokens.
Configurar los Tipos de Intercambio Permitidos
Selecciona qué tipos de intercambio puede realizar la aplicación:
| Tipo | Descripción |
|---|---|
| Suplantación | Intercambiar un token por uno con un sujeto diferente (requiere el permiso impersonate:users) |
| Delegación | Intercambiar un token por uno con una audiencia diferente (requiere el permiso delegate:tokens) |
Asignar Permisos
Asegúrate de que los usuarios o cuentas de servicio que realizan el intercambio de tokens tienen los permisos adecuados:
impersonate:users— Requerido para intercambios de suplantacióndelegate:tokens— Requerido para intercambios de delegación
Estos permisos se pueden asignar a través de roles en Consola → Roles → [Rol] → Permisos.
Implementación
JavaScript
const AURIS_DOMAIN = 'https://auth.tudominio.com'
const CLIENT_ID = 'tu-client-id'
const CLIENT_SECRET = 'tu-client-secret'
// Suplantación: Administrador actuando como un usuario específico
async function suplantarUsuario(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(`Intercambio de token fallido: ${error.error_description}`)
}
return await response.json()
// { access_token: "...", token_type: "Bearer", expires_in: 3600 }
}
// Delegación: Frontend pasando contexto de usuario al backend
async function delegarAlBackend(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()
}
// Uso
const tokenSuplantado = await suplantarUsuario(adminAccessToken, 'user-123')
const tokenDelegado = await delegarAlBackend(userAccessToken, 'billing-service')Parámetros de la Solicitud
| Parámetro | Requerido | Descripción |
|---|---|---|
grant_type | Sí | Debe ser urn:ietf:params:oauth:grant-type:token-exchange |
subject_token | Sí | El access token existente a intercambiar |
subject_token_type | Sí | Debe ser urn:ietf:params:oauth:token-type:access_token |
requested_token_type | No | Por defecto urn:ietf:params:oauth:token-type:access_token |
requested_subject | No | ID del usuario destino para suplantación. Omitir para delegación. |
audience | No | Audiencia destino para el nuevo token. Se usa en delegación. |
scope | No | Alcance solicitado para el nuevo token. No puede superar el alcance del token original. |
client_id | Sí | El client ID de la aplicación |
client_secret | Sí | El client secret de la aplicación |
El Claim act
El intercambio de tokens siempre añade un claim act (actor) al token resultante. Este claim crea una cadena auditable que muestra quién realizó realmente el intercambio:
Suplantación simple
{
"sub": "user-456",
"act": {
"sub": "admin-123"
}
}Delegación encadenada
Si un token que ya tiene un claim act se intercambia de nuevo, la cadena crece:
{
"sub": "user-456",
"act": {
"sub": "service-b",
"act": {
"sub": "service-a",
"act": {
"sub": "admin-123"
}
}
}
}Esta cadena proporciona un rastro de auditoría completo de todos los servicios y usuarios involucrados en la secuencia de intercambio de tokens.
Validación de Tokens Intercambiados
Cuando tu API recibe un token con un claim act, puedes inspeccionarlo para entender la cadena de delegación:
import { verifyToken } from '@auris/js/jwt-verify'
async function manejarSolicitud(req) {
const payload = await verifyToken(req.headers.authorization.slice(7), {
jwksUrl: 'https://auth.tudominio.com/.well-known/jwks.json',
})
// Comprobar si es un token suplantado o delegado
if (payload.act) {
console.log(`Acción realizada por ${payload.act.sub} actuando como ${payload.sub}`)
// Es posible que quieras registrar o restringir ciertas operaciones para tokens suplantados
if (esOperacionDestructiva(req)) {
throw new Error('Las operaciones destructivas no están permitidas mediante tokens suplantados')
}
}
}Consideraciones de Seguridad
- Aplicación de permisos: La suplantación requiere
impersonate:usersy la delegación requieredelegate:tokens. Estos son permisos sensibles que deben asignarse con moderación. - Registro de auditoría: Cada intercambio de tokens se registra con el actor original, el sujeto destino, el tipo de intercambio y la marca de tiempo. Estos registros son visibles en la Consola de Auris bajo Registros.
- Restricción de alcance: Los tokens intercambiados no pueden tener un alcance más amplio que el token original. Solo se puede reducir el alcance, nunca ampliarlo.
- Cliente confidencial requerido: El intercambio de tokens requiere autenticación de cliente. Los clientes públicos no pueden realizar intercambios.
- Vida útil del token: Los tokens intercambiados tienen una vida útil predeterminada más corta (1 hora) y no pueden superar la vida útil restante del token original.
La suplantación es una capacidad muy potente. Solo asigna el permiso impersonate:users a roles de administrador de confianza. Considera añadir controles adicionales en la capa de aplicación, como bloquear la suplantación para operaciones destructivas o requerir un motivo o número de ticket.
Endpoints de la API
/api/auth/tokenEndpoint de token. Para intercambio de tokens, establece grant_type=urn:ietf:params:oauth:grant-type:token-exchange con los parámetros descritos anteriormente. Requiere autenticación de cliente.
/api/oauth/token-exchangesRequires: view:token_exchangesLista los eventos recientes de intercambio de tokens. Filtrable por usuario, tipo (suplantación/delegación) y rango de fechas.
Permisos Requeridos
| Operación | Permiso |
|---|---|
| Realizar intercambio de suplantación | impersonate:users |
| Realizar intercambio de delegación | delegate:tokens |
| Ver historial de intercambios de tokens | view:token_exchanges |
| Habilitar Intercambio de Tokens en una aplicación | manage:applications |
Guías Relacionadas
- Credenciales M2M (Client Credentials) — Autenticación servidor a servidor sin intercambio de tokens
- Claims JWT Personalizados — Añadir claims personalizados a los access tokens
- Roles y Permisos — Gestión de los permisos requeridos para el intercambio de tokens