Resumen
- DPoP cambia la propiedad esencial del bearer token: conocer su valor ya no completa la credencial. Quien lo presenta debe firmar una prueba nueva con la clave privada vinculada al token.
- La prueba describe un conjunto acotado: método, URI objetivo sin query ni fragmento, tiempo, identificador único, hash del token y, cuando se exige, nonce del servidor. No firma toda la operación.
- Tras validar DPoP, el resource server aún comprueba emisor, audiencia, vigencia, estado y privilegios del token, coordina el replay y decide si el sujeto puede ejecutar esa acción sobre ese recurso ahora.
El token robado que dejó de ser suficiente
Un access token aparece en los registros de una pasarela. Alguien lo copia y lo presenta desde otro proceso. Si fuera Bearer, la cadena podría bastar mientras el token siguiera vigente y el servidor la aceptara. Pero el token está restringido mediante DPoP.
El atacante necesita una segunda pieza: un JWT de prueba recién firmado. La clave pública de esa prueba debe producir la misma huella que el authorization server asoció al token. Firmar con una clave nueva no sirve. Reutilizar una prueba observada tampoco debería servir si cambian el método o la URI, si la ventana temporal terminó, si falta el nonce reciente o si el jti ya fue consumido.
El rechazo demuestra exactamente lo que DPoP promete: una fuga del valor del token no entrega por sí sola la capacidad de usarlo.
Después llega el cliente legítimo. La firma valida. htm y htu coinciden. ath corresponde al token. iat entra en la ventana y jti es nuevo. El token y la clave están correctamente ligados. Aun así, el servidor responde que no: la audiencia es otra API, el scope solo permite consulta, el usuario perdió el rol o la orden ya se cerró.
Ambas respuestas son correctas. La primera protege la restricción del emisor. La segunda protege la autoridad sobre el recurso. Mezclarlas en un único indicador “PoP valid” borra el límite que permite saber quién decidió qué.
Qué cambia respecto de Bearer
La RFC 6750 parte de una regla simple: cualquiera que posee un bearer token puede usarlo como cualquier otro poseedor. El sistema confía en que el valor no se filtre, que TLS lo proteja en tránsito y que su audiencia, duración y alcance reduzcan el daño.
La RFC 9449 añade una comprobación de posesión al nivel de aplicación. El cliente crea un par asimétrico y firma una prueba al solicitar el token. El authorization server puede guardar en el token la huella JWK de la clave pública. Más tarde, el resource server recibe el token y otra prueba y confirma que la clave usada ahora coincide con aquella huella.
La RFC 9700 recomienda restringir los tokens al emisor para reducir el replay de valores robados. Pero también recomienda limitar audiencia y privilegios. Son controles complementarios. Un token muy amplio sigue siendo muy amplio aunque solo una clave pueda presentarlo.
La huella no autentica automáticamente a una persona o empresa. El JWK público puede haber sido creado por un cliente público sin registro previo de esa clave. Demostrar que alguien puede usar la parte privada no prueba por qué recibió la autorización ni qué persona controla hoy el entorno de ejecución.
La prueba tiene un perfil, no solo una firma
En el protected header, typ debe ser dpop+jwt; alg debe designar un algoritmo asimétrico admitido; jwk debe contener solo la clave pública. La aplicación, no el JWT recibido, decide qué algoritmos acepta. La RFC 8725 insiste en validar tipo, issuer, audience y reglas mutuamente excluyentes para evitar que un JWT válido en un contexto se cuele en otro.
La carga incluye htm, htu, iat y jti. El servidor compara el método con la petición real y la URI objetivo con su vista autorizada de la petición. Decide la antigüedad admisible. Usa el identificador impredecible para detectar una segunda presentación.
Con un access token, aparece ath: la codificación del hash SHA-256 del valor exacto. Recalcularlo impide adjuntar una prueba capturada al token de otro usuario o a un token rotado.
Con un desafío del servidor aparece nonce. No todos los nonces son iguales: el que emite el authorization server se devuelve allí; el que emite el resource server pertenece a ese servidor. Un valor reciente e impredecible obliga a la capacidad de firma a reaccionar ahora, en vez de permitir una reserva de pruebas generadas con antelación.
Una prueba no pasa porque esos nombres estén presentes. El servidor rechaza campos duplicados, formato incorrecto, claims ausentes, tipo equivocado, algoritmo fuera de política, firma falsa, JWK privado, método o URI diferentes, tiempo inaceptable, nonce ajeno, ath incorrecto y clave distinta de la ligada al token.
jkt, ath y dpop_jkt resuelven sustituciones diferentes
La huella guardada como cnf.jkt vincula el token a una clave. La prueba corriente debe verificarse con una clave cuya huella sea idéntica.
ath vincula esa prueba al valor concreto del token presentado. Sin él, una prueba válida podría acompañar a otro token ligado a la misma clave. Con él, el resource server sabe que la firma se calculó para esta cadena, no que la cadena tenga permisos correctos.
dpop_jkt puede ligar antes el código de autorización a la clave que el cliente pretendía usar. Así se impide que quien intercepte el código lo canjee con una clave propia y obtenga un token perfectamente DPoP, pero ligado al atacante. Esta protección se suma a PKCE y a la autenticación del cliente; no las reemplaza.
Un despliegue que solo comprueba una de las tres uniones no puede declararse completo con una casilla “DPoP enabled”. El registro de evidencias debe indicar la etapa y la comparación.
El query y el cuerpo quedan fuera de la base
htm evita convertir una prueba de lectura en una de borrado. htu evita moverla a otro URI. El alcance tiene un borde preciso: htu no incluye query ni fragmento. DPoP tampoco firma de base el body ni cualquier header de aplicación.
Dos peticiones con la misma ruta y distinto ?cuenta= pueden producir el mismo htu. Dos cuerpos JSON con beneficiarios diferentes pueden compartir toda la prueba DPoP. Eso no significa que DPoP esté roto; significa que su objeto es la restricción del emisor, no la aprobación de los términos del negocio.
La RFC 9110 aporta la semántica HTTP. La aplicación decide cómo query, body, headers y estado del objeto cambian el efecto. Para una operación irreversible pueden hacer falta un mandato transaccional, idempotency key, firma de mensaje o confirmación adicional.
Las pasarelas complican incluso la URI. El cliente ve un scheme, authority y path públicos; el backend puede ver host interno y ruta reescrita. La política debe señalar quién reconstruye la vista externa y qué cabeceras de forwarding son confiables. Ampliar la normalización hasta “hacer que pase” puede destruir el vínculo; usar la vista interna sin contexto puede bloquear todos los clientes correctos.
jti necesita memoria compartida
El claim jti es una etiqueta única, no un cerrojo. Para rechazar un replay, el receptor guarda los identificadores aceptados durante la ventana pertinente y realiza de forma atómica la comprobación y el alta.
En varias regiones, dos copias simultáneas pueden llegar antes de replicar el estado. Cada región considera nuevo el mismo jti. Reducir la ventana limita el riesgo, pero no elimina la carrera. Un nonce puede endurecer la interacción, siempre que exista una política clara de emisión, alcance, rotación y consumo.
Además, prueba única no significa efecto único. Un cliente puede firmar dos JWT distintos al reintentar una petición cuyo resultado desconoce. Ambos jti son nuevos. La capa de negocio debe reconocer la transacción y decidir si devuelve el resultado anterior o ejecuta otra vez.
Cuando el navegador conserva la clave y el atacante conserva el contexto
Una clave no extraíble puede impedir que un XSS copie el material privado y use el token fuera del dispositivo. La RFC 10017 mantiene una advertencia más incómoda: código malicioso dentro del origen tiene los privilegios del contexto de la aplicación. Puede pedir firmas, invocar la API o iniciar un nuevo flow aunque nunca lea la clave.
Por eso hay dos modelos de amenaza. DPoP protege contra exfiltración y uso desligado del entorno. No sanea un entorno ya controlado. Si el adversario roba token y clave, o domina la interfaz que firma, la restricción deja de separar al atacante del cliente.
La custodia mejora con hardware, non-exportable keys y procesos aislados. La identidad y la autorización no nacen de esa custodia. Siguen necesitando una política que contemple usuario, client, recurso, acción, riesgo y estado actual.
Evidencia que llega hasta el commit
IANA registra DPoP, DPoP-Nonce y los parámetros asociados. El registro da interoperabilidad nominal; no prueba adopción ni correcta aplicación.
Una traza útil conserva hashes seguros del token y la prueba, huella pública, algoritmo seleccionado, htm, URI externa e interna normalizadas, edad, jti, emisor del nonce, resultado atómico del replay store, comparación de ath y jkt, issuer, audience, scopes, versión de política y resultado de commit. No conserva raw tokens ni private keys.
La prueba de running code incluye casos negativos cruzados entre cliente, authorization server, gateway y réplicas: token sin clave, clave incorrecta, token intercambiado, método cambiado, URI reescrita, prueba vieja, replay simultáneo, nonce de otro emisor, audiencia errónea, scope corto, cuenta suspendida y operación ya realizada. La autoridad se demuestra cuando cada capa rechaza su propio error y deja evidencia de ello.
Informe para miembros
Contexto ampliado del perfil
Inicia sesión con el nivel de membresía adecuado para desbloquear el informe completo y las notas de las fuentes.
Solo para Strategic Circle
Strategic Circle
Abierto a todos los lectores. Desbloquea informes de perfil después de unirte e iniciar sesión.
Únete a Strategic CircleSolo para Leadership Alliance
Leadership Alliance
Para propietarios y directivos cualificados de activos de propiedad intelectual; inicia sesión para desbloquear los informes de la alianza.
Unirse a Leadership Alliance
