Enunciado y alcance
Un cliente de banca móvil llama a una API de pagos. El usuario puede aprobar una única transferencia de 500 USD a un beneficiario. El servidor de autorización debe mostrar los detalles de la transacción durante el consentimiento, y un token de acceso copiado no debe ser reutilizable desde otra instancia de cliente. Explica un diseño de OAuth 2.0 Rich Authorization Request (RAR) con Demonstrating Proof of Possession (DPoP), que incluya la emisión de tokens, las comprobaciones del servidor de recursos, el manejo de repeticiones (replay), la pérdida de claves y la verificación.
Esta es una pregunta de seguridad de backend y contratos de API. La moneda exacta, el monto y el beneficiario son suposiciones para la entrevista, no hechos del mercado.
Qué está evaluando el entrevistador
- Si distingues entre aquello a lo que el usuario dio su consentimiento y lo que un token de acceso puede invocar.
- Si sabes que RAR transporta detalles de autorización estructurados, mientras que DPoP vincula un token a una clave y demuestra la posesión por solicitud.
- Si se nombra cada punto de control: servidor de autorización, endpoint de token, servidor de recursos y libro mayor de pagos (payment ledger).
- Si puedes contener repeticiones (replay), envíos duplicados, pérdida de claves y respuestas ambiguas del proveedor.
- Si el despliegue y las pruebas demuestran el invariante de negocio en lugar de solo verificar la sintaxis del JWT.
Una respuesta débil dice "pon el monto en un scope y firma el JWT". Una respuesta sólida mantiene estructurados los detalles de la transacción, vincula el token emitido a la clave del cliente y hace que la máquina de estados final del pago sea la autoridad definitiva.
Aclaraciones que conviene hacer primero
- ¿El servidor de autorización es también el propietario del libro mayor de pagos? Si no es así, el libro mayor debe volver a verificar la decisión de autorización al momento de confirmar (commit).
- ¿Una autorización es válida para exactamente una transferencia o puede autorizar un conjunto acotado de transferencias? Los detalles de RAR y la vida útil del token dependen de este límite.
- ¿Puede el cliente móvil mantener una clave respaldada por hardware tras una reinstalación y cómo se revoca un dispositivo perdido?
- ¿Recibe el servidor de recursos un requisito de nonce de DPoP y qué ventana de desviación de reloj (clock-skew) es aceptable?
- ¿Qué sucede después de un tiempo de espera (timeout) en el proveedor de pagos: puede el sistema consultar el estado o debe registrar un estado desconocido?
Estructura para una respuesta de 30 segundos
"Pondría la transferencia exacta en un objeto authorization_details en lugar de inventar un scope amplio. El cliente crea un par de claves y envía una prueba DPoP al solicitar un token; el servidor de autorización vincula el token a esa clave pública. El servidor de recursos valida el token de acceso, la prueba DPoP, el método, el URI, la marca de tiempo, el nonce y la vinculación token-clave, y luego pasa el identificador de transacción autorizada al libro mayor de pagos. El libro mayor lo acepta una sola vez con una clave de idempotencia y registra un estado terminal. La protección contra repeticiones, la revocación de dispositivos, los timeouts del proveedor y la evidencia de auditoría son controles independientes, cada uno probado en su propio componente".
Solución paso a paso
1. Modelar la acción solicitada
RAR define una solicitud authorization_details estructurada. El objeto debe contener un type registrado, la acción exacta, el monto, la moneda, el identificador de destino y una referencia de transacción. El servidor de autorización valida el esquema, la titularidad de la cuenta, los límites y las políticas antes de presentar el consentimiento. Debe mostrar los mismos valores canónicos que utilizará el libro mayor; una etiqueta suministrada por el cliente no es suficiente.
{
"type": "payment",
"actions": ["transfer"],
"amount": "500.00",
"currency": "USD",
"beneficiary_id": "b_123",
"request_id": "rq_7f2"
}El resultado de la autorización debe hacer referencia a un registro de autorización propiedad del servidor. No permitas que un servidor de recursos reconstruya el dinero, la moneda o el beneficiario a partir de una cadena de texto no confiable destinada a visualización.
2. Vincular el token a la clave del cliente
El cliente crea una clave privada en un almacenamiento protegido y envía un JWT de prueba DPoP al endpoint de token. La prueba incluye el método HTTP, el URI de destino, la hora de emisión, un identificador de prueba único y la clave pública. El servidor de autorización verifica la prueba y emite un token cuyo reclamo (claim) de confirmación hace referencia a esa clave. Por lo tanto, un token de portador copiado sin la clave privada resulta insuficiente para una solicitud protegida.
DPoP es una restricción de emisor a nivel de aplicación; no reemplaza a TLS, el almacenamiento seguro de claves, las políticas de autorización ni la revocación de dispositivos. La clave es un autenticador para la instancia del cliente, no una prueba de que el ser humano aprobó un pago en particular.
3. Verificar cada solicitud al recurso
El cliente envía tanto el token de acceso como una prueba DPoP reciente. El servidor de recursos verifica la firma, la expiración del token, el emisor, la audiencia, la huella digital (thumbprint) de confirmación, el método, el URI, la ventana de reloj, el nonce cuando sea necesario y la caché de repetición del identificador de prueba. Rechaza una prueba reutilizada para otro URI o fuera de su ventana de repetición. La vinculación del token de acceso y la búsqueda de los detalles de autorización deben verificarse juntas; una prueba válida para un token diferente no es suficiente.
4. Convertir al libro mayor en la autoridad final
El servidor de recursos crea un comando de pago que contiene el ID del registro de autorización, el resumen (digest) canónico del monto y beneficiario, el ID de instancia del cliente y una clave de idempotencia. El libro mayor compara el comando con el registro aprobado en una sola transacción. Solo acepta una autorización no utilizada, escribe PENDING o COMMITTED, y rechaza montos modificados, destinos cambiados, aprobaciones expiradas o una segunda transición terminal. Si un proveedor externo agota el tiempo de espera (timeout), registra UNKNOWN y consulta o concilia antes de reintentar; un timeout no demuestra que no haya ocurrido un cargo.
5. Gestionar la recuperación y la revocación
Almacena los identificadores de prueba durante una ventana de repetición acotada y limita la caché por cliente y emisor. Un dispositivo perdido revoca la clave o su registro de autorización, no solo la sesión del navegador. Mantén entradas de auditoría para el hash de la carga útil de consentimiento, los valores mostrados, la huella digital de la clave del token, la decisión del recurso, la transición del libro mayor y la acción del operador. Censura (redact) las claves privadas y los tokens sin procesar. Si un despliegue falla, se puede deshabilitar el nuevo tipo de detalles de autorización mientras se mantienen los flujos antiguos gobernados por separado.
6. Comparar alternativas
Los scopes amplios como payments.write son más simples pero no pueden expresar un monto único y un beneficiario único; el libro mayor necesitaría de todos modos otra autorización de transacción confiable. Mutual TLS puede vincular tokens a un certificado y resulta atractivo para clientes de servidor controlados, pero el ciclo de vida de los certificados en dispositivos móviles y la terminación de red son más difíciles. DPoP se adapta a claves administradas por la aplicación y clientes HTTP, pero el manejo de nonce, reloj, caché de repeticiones y pérdida de claves se convierte en un trabajo de implementación explícito.
Respuesta de muestra de alta calidad
"Separaría cuatro decisiones. Primero, RAR transporta una autorización de pago tipificada con el monto exacto, la moneda, el beneficiario y el ID de solicitud del servidor; la pantalla de consentimiento renderiza los valores canónicos y el servidor de autorización valida los límites. Segundo, el cliente móvil utiliza una clave protegida y pruebas DPoP, y el token emitido se vincula a esa clave. Tercero, el servidor de recursos valida el token, la prueba, el URI, la hora, el nonce y la repetición de pruebas antes de cargar el registro de autorización propiedad del servidor. Finalmente, el libro mayor de pagos compara atómicamente ese registro con el comando y permite una única transición terminal idempotente. Se rechaza un token copiado sin la clave, un beneficiario modificado, una prueba duplicada o un segundo envío. Un timeout del proveedor se convierte en UNKNOWN y se concilia, nunca se reintenta a ciegas. Mediría las repeticiones rechazadas, los fallos de nonce, las discrepancias de autorización, los comandos duplicados, los resultados desconocidos y la propagación de revocaciones, para luego implementar un canary del nuevo tipo RAR con un interruptor de reversión (rollback switch)".
Errores comunes
- Poner el monto y el beneficiario en un scope → los scopes se convierten en cadenas de texto sin límites y pierden la validación tipificada → usa un esquema de authorization-details registrado y un registro propiedad del servidor.
- Tratar DPoP como consentimiento humano → la posesión de una clave no prueba lo que el usuario aprobó → mantén separados el consentimiento, la vinculación del token y la autorización del libro mayor.
- Validar DPoP solo en el gateway → los invocadores internos o rutas alternativas podrían eludir la verificación → haz cumplir la vinculación en cada límite de recursos y pasa un ID de decisión firmado.
- Reintentar un timeout del proveedor como un nuevo pago → la primera solicitud podría haberse confirmado → consulta el estado, utiliza una clave de idempotencia y mantén un estado
UNKNOWNexplícito. - Almacenar en caché los ID de prueba para siempre → la memoria crece y razonar sobre un cambio de política se vuelve difícil → utiliza una ventana de repetición acotada vinculada a la vida útil de la prueba y a la política de reloj.
Preguntas de seguimiento y respuestas
¿Qué pasa si el atacante roba tanto el token de acceso como una prueba DPoP?
Rechaza la reutilización del identificador de prueba y haz cumplir las restricciones de método, URI, hora y nonce. Mantén una vida útil corta para las pruebas y exige una prueba nueva por cada solicitud. Si la clave privada también está comprometida, revoca la vinculación de la clave y los registros de autorización; DPoP no puede recuperar por sí solo una clave comprometida.
¿Por qué no codificar el pago en un scope de JWT?
Un scope es útil para permisos de granularidad gruesa, pero una transferencia de dinero necesita campos tipificados, validación, visualización y un registro de servidor estable. Una cadena de scope puede permanecer como una capacidad amplia mientras que RAR y el libro mayor hacen cumplir la transacción exacta.
¿Qué sucede si el servidor de recursos y el servidor de autorización discrepan?
Utiliza un ID de autorización propiedad del servidor y un registro versionado. El servidor de recursos debe fallar de forma cerrada (fail closed) cuando el registro no esté disponible o su versión esté desactualizada para una acción de alto riesgo. El libro mayor vuelve a verificar la versión en su transacción, de modo que una decisión antigua en caché no pueda confirmar un pago modificado.
¿DPoP evita todas las repeticiones (replays)?
No. Reduce la repetición de un token copiado cuando el atacante carece de la clave privada y permite que el servidor detecte pruebas reutilizadas. No evita que un poseedor malintencionado de la clave repita un comando permitido, por lo que la idempotencia del libro mayor, la autorización de un solo uso, los límites de tasa (rate limits) y la revocación de dispositivos siguen siendo necesarios.