Planteamiento y contexto aplicable
Eres el responsable de un servidor de autorización OAuth 2.0. Los clientes móviles y web empresariales manejan scopes detallados, indicadores de recursos y contexto de pagos, pero el equipo no desea incluir la solicitud completa en la URL del navegador. Diseña un endpoint de Pushed Authorization Request (PAR). Abarca la autenticación de clientes, la generación y vinculación de request_uri, expiración, uso único, repetición (replay), validación de redirect-URI, PKCE, errores, límites de tasa (rate limits) y rollback.
Esto aplica a entrevistas de backend, plataformas de identidad y pagos. El RFC 9126 define PAR como un push directo del cliente al servidor de autorización que devuelve un request_uri para una solicitud de autorización posterior en el navegador. Una respuesta sólida también señala que PAR no elimina la necesidad de que el servidor de autorización valide la solicitud posterior.
Qué evalúa el entrevistador
- Delimitar con claridad la frontera entre el cliente, el endpoint PAR, el endpoint de autorización del navegador y el token endpoint.
- Separar la autenticación de clientes, la autenticación de usuarios, la integridad de la solicitud y la vinculación de tokens.
- Manejar la adivinación de
request_uri, el intercambio no autorizado (swapping), replay, expiración y ataques contra la redirect-URI. - Ubicar PKCE, state, nonce, JAR y PAR en las capas correctas.
- Hacer operativos los TTL, la idempotencia, los límites de tasa, la auditoría y el despliegue canary.
El RFC 9700 resume las prácticas recomendadas actuales de seguridad para OAuth 2.0. El material de preparación para SDE II de Amazon enfatiza la confiabilidad, precisión, eficiencia, escalabilidad y seguridad en el diseño de sistemas. La señal buscada en la entrevista es convertir esos estándares en límites de servicio en ejecución.
Preguntas para clarificar
- ¿El cliente es confidencial o público? ¿Puede un cliente móvil proteger un secreto de cliente, o debe usar PKCE y vinculación a la plataforma?
- ¿Qué datos confidenciales contiene la solicitud? ¿Se requiere un JAR firmado o cifrado, y qué campos deben verificarse en el momento de PAR?
- ¿Cuáles son los objetivos para el tiempo de vida de
request_uri, la tolerancia de actualización, la concurrencia por cliente y los límites de tasa globales? - ¿Las redirect URIs son fijas y prerregistradas, o un tenant empresarial requiere registro dinámico?
- ¿Todos los clientes deben enviar los parámetros de autorización a través de PAR? ¿Cómo migrarán los clientes heredados?
- ¿La actualización del navegador, la navegación hacia atrás, la cancelación y los reintentos de red deberían poder leer la misma solicitud nuevamente?
Estructura de respuesta en 30 segundos
El cliente envía un HTTPS POST a PAR, se autentica y valida los parámetros de redirect URI, scope, recurso y PKCE. El servidor crea un request_uri de alta entropía, de corta duración y vinculado al cliente, y devuelve un JSON. Luego, el navegador envía únicamente client_id y request_uri al endpoint de autorización. Dicho endpoint vuelve a validar la solicitud, state/nonce, el consentimiento del usuario y PKCE antes de consumir la referencia. Límites de tasa, auditoría, políticas de uso único, flags de compatibilidad y métricas canary controlan el despliegue.
Respuesta detallada paso a paso
1. Definir el protocolo de dos saltos
El primer salto es un HTTPS POST directo del cliente a PAR con un cuerpo application/x-www-form-urlencoded. Es el lugar para autenticar al cliente y validar client_id, tipo de respuesta, redirect URI, scope, indicadores de recursos, state, nonce y PKCE. El RFC 9126 exige HTTPS para PAR y permite extensiones del endpoint de autorización.
El segundo salto es la solicitud del agente de usuario (user agent) al endpoint de autorización, transportando normalmente solo client_id y request_uri. El servidor de autorización recupera la solicitud guardada en el primer salto en lugar de confiar en parámetros confidenciales reenviados por el navegador. Esto reduce la fuga en cadenas de consulta (query strings), los límites de tamaño de URL y la manipulación por parte del agente de usuario.
2. Diseñar el almacenamiento de request_uri
Genera request_uri con un valor aleatorio criptográficamente seguro, nunca un ID incremental o una clave de negocio predecible. Almacena la solicitud completa, el ID de cliente, la hora de creación, la expiración, el estado de consumo y los campos de auditoría con hash; vincula la referencia al cliente que la creó.
Mantén el TTL corto y devuélvelo como expires_in. Una referencia expirada devuelve invalid_request; una referencia desconocida no debe revelar si alguna vez existió. El consumo de un solo uso es lo más seguro. Si el producto debe admitir actualización de página, permite una ventana corta con conteo de lecturas, vinculación de state/nonce y un límite estricto.
3. Validar el cliente y la solicitud
Autentica al cliente en PAR usando las reglas del token-endpoint, como mTLS o private_key_jwt. La autenticación demuestra qué cliente envió la solicitud; no demuestra que un usuario haya iniciado sesión o consentido un scope. Valida en PAR las redirect URIs registradas, los scopes permitidos, los recursos y el tipo de respuesta; luego repite en el momento de la autorización las comprobaciones que requieren el contexto del usuario.
Si el cliente utiliza un Request Object firmado, valida su firma, emisor, audiencia, expiración y campos críticos bajo las reglas de JAR. PAR es el push directo y el ciclo de vida de la referencia; JAR es la firma o cifrado del Request Object. Pueden combinarse, pero ninguno reemplaza al otro.
4. Ubicar PKCE, state y nonce en la capa correcta
PAR aún transporta code_challenge y su método; el token endpoint debe verificar code_verifier al canjear el código. state vincula la sesión del cliente y mitiga CSRF. El nonce de OIDC vincula la solicitud de autenticación al token de ID. La presencia de request_uri no es motivo para eliminar estos controles ni para tratarlos como intercambiables.
5. Prevenir sustitución (swapping), replay y redirecciones abiertas
Si un atacante reemplaza una solicitud por otra que haya obtenido, el scope o el nivel de garantía podrían cambiar. Vincula la referencia al cliente y exige que coincida el contexto de cliente de la solicitud de autorización. El cliente utiliza un state y PKCE únicos; OIDC utiliza nonce. Compara las redirect URIs estrictamente para que PAR no se convierta en un punto de entrada para redirecciones abiertas.
Devuelve un error explícito pero que no permita enumeración cuando se reutilice una referencia consumida. Registra el cliente, el hash de referencia, la hora, las señales de riesgo y el resultado para detectar intentos de adivinación y replay. Mantén las solicitudes de autorización completas, las aserciones de cliente y los parámetros de recursos confidenciales fuera de los logs de acceso ordinarios.
6. Diseñar errores, límites y disponibilidad
Parámetros no válidos, una redirect URI no coincidente o una firma incorrecta utilizan errores de OAuth como invalid_request. Un método incorrecto puede ser 405, una solicitud de tamaño excesivo 413 y una violación de cuota 429. Aplica límites por cliente, tenant, IP y almacenamiento global para que un atacante no pueda agotar el almacenamiento de PAR.
Cuando PAR no esté disponible, permitir que los clientes migrados recurran a una solicitud de autorización regular es una decisión de política de seguridad. Para pagos o scopes de alto riesgo, falla explícitamente en lugar de debilitar silenciosamente el flujo. Migra a los clientes heredados mediante metadatos y luego exige gradualmente require_pushed_authorization_requests.
7. Gestionar el ciclo de vida de los datos y la observabilidad
Retén los datos de referencia únicamente durante su TTL, su consumo y el período de auditoría necesario. Utiliza almacenamiento cifrado, control de acceso y minimización; no copies el contexto de autorización confidencial en múltiples cachés. Monitorea el éxito de PAR, fallos de validación, expiraciones, consumos duplicados, tasa de errores 429, tasa de referencias faltantes en la autorización y fallos de PKCE en el intercambio de tokens.
Realiza despliegues canary comparando los flujos regulares y PAR en paralelo. Compara tasa de finalización, latencia de la primera página, fallback móvil y alertas de seguridad. Las pruebas automatizadas deben cubrir el consumo concurrente, el intercambio de referencias, variantes de redirect-URI, actualización en el navegador, solicitudes de tamaño excesivo y compatibilidad con clientes heredados.
Ejemplo de respuesta de alta calidad
Dividiría el flujo en dos saltos. El cliente llama a PAR a través de HTTPS, se autentica y valida redirect URI, scope, recurso, tipo de respuesta, PKCE, state y nonce. El servidor crea un request_uri de alta entropía, de corta duración y vinculado al cliente, y devuelve únicamente la referencia y expires_in. Luego, el navegador llama al endpoint de autorización con el ID de cliente y la referencia; el servidor recupera la solicitud original y ejecuta nuevamente las comprobaciones de autorización, sesión de usuario, state/nonce y PKCE.
La referencia almacena la solicitud, la vinculación del cliente, la expiración y el estado de consumo, siendo de un solo uso de forma predeterminada. Una funcionalidad de actualización de página utiliza una ventana corta, un límite de lecturas y auditoría. JAR se encarga de la firma o el cifrado del Request Object; PAR gestiona el push directo y el tiempo de vida de la referencia. La coincidencia estricta de redirect-URI evita sustituciones y redirecciones abiertas, mientras que los errores OAuth y los límites por cliente, IP y tenant hacen visible cualquier abuso.
Realizaría un despliegue canary basado en metadatos de clientes mientras mantengo el flujo anterior, midiendo finalización, latencia, expiración, uso duplicado, errores 429 y fallos de PKCE. Los clientes de alto riesgo no realizan un fallback silencioso. Una caída del almacenamiento o un aumento repentino de replays detiene el despliegue y revierte el flag de exigencia obligatoria. Esto reduce las fugas en URLs y la manipulación de parámetros sin alterar las fronteras de consentimiento de usuario e intercambio de códigos de OAuth.
Errores comunes
- Decir solo "poner los parámetros en POST" sin autenticación de cliente, vinculación de referencia o expiración.
- Tratar a
request_uricomo un token de acceso o convertirlo en un ID de base de datos predecible. - Asumir que PAR previene automáticamente el replay y omitir el uso único, TTL, state, nonce o PKCE.
- Mezclar PAR, JAR y PKCE sin explicar la frontera de protección de cada uno.
- Validar la redirect URI únicamente en PAR y confiar en los parámetros del navegador en el momento de la autorización.
- Ignorar los errores 413, 429, el consumo concurrente, las fugas en caché y los logs confidenciales.
- Recurrir incondicionalmente a la autorización regular cuando PAR falla, ampliando la exposición de scopes de alto riesgo.
Preguntas de seguimiento y respuestas
¿Cuánto tiempo debe vivir un request_uri?
Usa un TTL corto según el nivel de riesgo y devuelve expires_in. Elimínalo o invalídalo tras su expiración o consumo; retén únicamente campos mínimos de hash, cliente y resultado para auditoría.
¿Puede una actualización del navegador reutilizar la referencia?
Usa por defecto el consumo de un solo uso. Si se requiere soportar recarga, utiliza una ventana corta, un límite de lecturas y vinculación a state, nonce y sesión de cliente mientras se monitorean lecturas duplicadas. No permitas reutilización ilimitada.
¿Por qué se sigue necesitando PKCE tras la autenticación del cliente?
La autenticación del cliente identifica qué cliente envió la solicitud. PKCE vincula el canje del código al solicitante que posee el verificador. Sigue siendo fundamental para clientes públicos y móviles si se intercepta un código de autorización.
¿Puede PAR reemplazar a JAR?
No. PAR aborda el push directo, la ocultación de parámetros del navegador y el ciclo de vida de la referencia. JAR aborda la firma o cifrado del Request Object. Deben combinarse cuando se requiere mayor integridad o no repudio.
¿Cómo deben migrar los clientes heredados?
Habilita PAR mediante metadatos del servidor de autorización y políticas de cliente, observa la compatibilidad y luego exige require_pushed_authorization_requests para clientes seleccionados. Mantén una ruta heredada acotada y auditada en lugar de migrar todo el ecosistema a ciegas.
¿Qué pasa si el endpoint PAR recibe una inundación de tráfico?
Aplica límites por cliente, tenant, IP y recursos globales; limita el tamaño del cuerpo y el TTL de almacenamiento; devuelve 429; y monitorea la tasa de fallos y las marcas de agua de almacenamiento. Los clientes de alto riesgo no deben degradar su seguridad silenciosamente debido a la presión de tráfico.