Cuando una aplicación ofrece “Iniciar sesión con Google”, Microsoft u otro proveedor de identidad, normalmente hay varios protocolos trabajando por debajo. OAuth 2.0 permite delegar acceso a recursos y OpenID Connect (OIDC) añade una capa de identidad que permite a una aplicación saber quién se ha autenticado.
El resultado parece sencillo para el usuario: pulsar un botón, autenticarse y volver a la aplicación. Por debajo, sin embargo, intervienen redirecciones, códigos temporales, tokens, identificadores de cliente, estados de sesión, claves criptográficas y varias fronteras de confianza.
Un error en cualquiera de esas relaciones puede convertir un flujo legítimo de autenticación en robo de códigos, inyección de sesiones, reutilización de tokens o incluso acceso a la cuenta de otra persona. Y muchas veces el problema no está en OAuth como protocolo, sino en cómo la aplicación lo ha integrado.
En esta guía vamos a revisar los fallos que merece la pena buscar en una auditoría OAuth/OIDC, qué protege realmente PKCE, por qué state y nonce no son exactamente lo mismo, cómo se valida un ID Token y qué está cambiando con OAuth 2.1.
En esta guía
- OAuth y OIDC en 60 segundos
- Fallo 1: validación insuficiente del redirect_uri
- Fallo 2: CSRF, state y sesiones que no quedan vinculadas
- Fallo 3: PKCE mal implementado y ataques de degradación
- Fallo 4: inyección y reutilización de authorization codes
- Fallo 5: validar mal el ID Token
- Fallo 6: OAuth mix-up cuando existen varios proveedores
- Fallo 7: account linking basado únicamente en email
- Fallo 8: fuga y reutilización de tokens
- Refresh tokens: el objetivo de larga duración
- Qué cambia realmente con OAuth 2.1
- Cómo auditar un flujo OAuth/OIDC
- Qué significa para seguridad ofensiva
- Preguntas frecuentes
OAuth y OIDC en 60 segundos
OAuth 2.0 es un framework de autorización. Permite que una aplicación obtenga acceso limitado a determinados recursos sin necesitar las credenciales del usuario.
OpenID Connect añade una capa de autenticación sobre OAuth 2.0. Es la parte que permite responder a la pregunta “¿quién es este usuario?” y proporciona, entre otras cosas, el ID Token.
En un Authorization Code Flow moderno, simplificando bastante, ocurre esto:
1. Usuario → aplicación "Quiero iniciar sesión" 2. Aplicación → Authorization Server client_id + redirect_uri + state/nonce + code_challenge... 3. Authorization Server → usuario autenticación + consentimiento 4. Authorization Server → redirect_uri authorization code 5. Aplicación → Token Endpoint authorization code + code_verifier 6. Token Endpoint → aplicación access token + ID token + opcionalmente refresh token
El navegador ve el código de autorización durante la redirección, pero el intercambio por tokens se realiza posteriormente contra el token endpoint. PKCE añade además una prueba que vincula ese código con la instancia del cliente que inició la operación.
| Elemento | Para qué sirve | Error habitual |
|---|---|---|
authorization code |
Credencial temporal que se intercambia por tokens. | Permitir que sea interceptado, inyectado o canjeado fuera de su transacción. |
access token |
Autoriza acceso a un Resource Server. | Tratarlo como si fuera una prueba universal de identidad o aceptarlo para una audiencia incorrecta. |
ID Token |
En OIDC contiene información verificable sobre la autenticación y el usuario. | No validar firma, issuer, audience, expiración o nonce. |
refresh token |
Permite obtener nuevos access tokens. | Permitir replay indefinido si es robado. |
Fallo 1: validación insuficiente del redirect_uri
El parámetro redirect_uri determina dónde enviará el Authorization Server al navegador después de completar la autorización. En el Authorization Code Flow, esa redirección transporta normalmente el código de autorización.
Esto convierte su validación en una frontera de seguridad crítica.
El problema aparece cuando el servidor utiliza reglas flexibles en lugar de comparar la URI completa registrada: comodines, comprobaciones parciales del hostname, prefijos de cadena o expresiones mal construidas.
# URI registrada https://app.example.com/oauth/callback # Una validación incorrecta podría aceptar algo parecido a: https://app.example.com.attacker.example/oauth/callback ↑ el dominio real ya no es example.com
También aparecen problemas cuando se registran patrones demasiado amplios para permitir múltiples subdominios o rutas. Cuanta más lógica tenga que interpretar el Authorization Server para decidir si una redirección es válida, más posibilidades existen de introducir diferencias entre lo que pretendía el desarrollador y lo que realmente acepta el parser.
La práctica actual de seguridad recogida por RFC 9700 es clara: las redirecciones registradas deben compararse mediante coincidencia exacta de cadena, salvo la excepción específica de puertos dinámicos en determinados redirects loopback de aplicaciones nativas.
¿Y los open redirects?
Una segunda pieza interesante es encontrar una redirección abierta dentro de un dominio que participa en el flujo.
# Endpoint legítimo vulnerable a open redirect
https://app.example.com/redirect?next=https://destination.example
Dependiendo de cómo se haya configurado el cliente OAuth, del tipo de respuesta y de cómo se propaguen los parámetros o fragmentos, un open redirect puede ayudar a sacar credenciales OAuth de la ubicación donde deberían permanecer.
Por eso RFC 9700 no solo exige validar estrictamente los redirect URI: también indica que clientes y Authorization Servers no deberían exponer open redirectors que permitan enviar el navegador a destinos arbitrarios.
Fallo 2: CSRF, state y sesiones que no quedan vinculadas
Durante un flujo OAuth existen dos operaciones diferentes que deben quedar relacionadas: la petición que inicia la aplicación y la respuesta que vuelve posteriormente al callback.
Tradicionalmente, state se utiliza para unir ambas operaciones y proteger el callback frente a CSRF.
# La aplicación inicia el flujo state = random_value_bound_to_browser_session # Después, en el callback received_state == expected_state ↑ la respuesta pertenece a esta transacción
Un state constante, predecible, reutilizable o no asociado correctamente a la sesión pierde buena parte de su utilidad.
Sin esta vinculación, un atacante puede intentar introducir en el navegador de otra persona una respuesta OAuth perteneciente a una transacción distinta. Dependiendo de la funcionalidad, el resultado puede ser login CSRF, vinculación incorrecta de cuentas u otras formas de confusión de sesión.
¿Entonces state es siempre obligatorio?
Aquí existe un matiz importante. Las recomendaciones actuales no dicen simplemente “siempre debe existir state”.
RFC 9700 permite que un cliente se apoye en la protección CSRF proporcionada por PKCE cuando haya comprobado que el Authorization Server realmente lo soporta y lo hace cumplir. En flujos OpenID Connect, nonce también puede proporcionar protección frente a determinadas formas de CSRF e inyección.
Si no existen esas garantías, debe utilizarse un token CSRF de un solo uso transportado mediante state y vinculado de forma segura al navegador.
Además, si state se utiliza para transportar información de aplicación —por ejemplo, la página a la que volver después del login— esa información también debe protegerse frente a manipulación.
state, nonce y PKCE están relacionados con la integridad de la transacción, pero no son simplemente tres nombres para el mismo control. Cada mecanismo protege propiedades diferentes del flujo.Fallo 3: PKCE mal implementado y ataques de degradación
PKCE, definido originalmente en RFC 7636, nació para proteger clientes públicos frente a la interceptación del authorization code, pero las buenas prácticas actuales recomiendan utilizarlo mucho más ampliamente.
El cliente crea un code_verifier aleatorio y envía en la petición inicial una transformación de ese valor denominada code_challenge.
# Inicio del flujo code_verifier = random_high_entropy_value code_challenge = BASE64URL(SHA256(code_verifier)) # Authorization request code_challenge=... code_challenge_method=S256 # Token request posterior code=... code_verifier=...
El Authorization Server conserva la relación entre el código y el challenge. Cuando posteriormente recibe el code_verifier, comprueba que corresponde con el challenge original.
El resultado es importante: robar únicamente el authorization code deja de ser suficiente para canjearlo.
El downgrade de PKCE
Un Authorization Server puede anunciar soporte para PKCE pero implementarlo de manera opcional. Eso introduce una situación delicada si la presencia de code_challenge es lo único que decide si PKCE se aplica o no.
RFC 9700 describe específicamente ataques de degradación relacionados con PKCE. Una de las inconsistencias que el servidor debe detectar es recibir posteriormente un code_verifier para una autorización que nunca tuvo asociado un code_challenge.
# Estado coherente authorization request: code_challenge = ABC token request: code_verifier = valor_que_produce_ABC → validar # Estado inconsistente authorization request: sin code_challenge token request: code_verifier = XYZ → rechazar
No basta, por tanto, con que una plataforma diga que “soporta PKCE”. Hay que comprobar que lo aplica correctamente durante toda la transacción.
Las recomendaciones actuales también utilizan S256 como método seguro para derivar el challenge. El método plain no ofrece las mismas propiedades cuando un atacante puede observar la petición de autorización.
Fallo 4: inyección y reutilización de authorization codes
PKCE también ayuda frente a otro problema: la inyección de authorization codes.
En lugar de intentar simplemente robar un código, el atacante intenta introducir un código obtenido en otra transacción dentro de la sesión legítima de la aplicación.
Sesión A code_A ↔ challenge_A Sesión B code_B ↔ challenge_B Intento de mezclar las transacciones sesión B recibe code_A code_verifier_B no corresponde con challenge_A → rechazo
Para que esto funcione correctamente, el code_verifier debe ser específico de cada operación y quedar vinculado a la sesión que inició el flujo.
Los authorization codes también deberían ser de vida corta, estar asociados al cliente correspondiente y ser de un solo uso. El token endpoint es una segunda frontera de seguridad: no basta con proteger correctamente el endpoint de autorización.
Durante una auditoría merece la pena observar qué ocurre cuando se intenta reutilizar un código ya canjeado, modificar el client_id, cambiar el redirect_uri durante el canje o mezclar artefactos obtenidos en sesiones diferentes.
Fallo 5: validar mal el ID Token
Cuando OpenID Connect entra en juego aparece otro artefacto: el ID Token. Normalmente es un JWT firmado que contiene información sobre el emisor, el usuario, la audiencia y el evento de autenticación.
Recibir un JWT con una estructura correcta no significa que sea válido para nuestra aplicación.
Entre las comprobaciones importantes están:
- Firma: debe validarse criptográficamente utilizando las claves correspondientes al proveedor esperado.
iss: el issuer debe coincidir exactamente con el proveedor en el que confía la aplicación.aud: la aplicación debe encontrarse entre las audiencias para las que fue emitido el token.exp: el token no puede haber expirado.nonce: cuando se ha enviado uno en la petición, debe aparecer y corresponder con la transacción iniciada.azp: en determinados casos con múltiples audiencias también debe comprobarse el Authorized Party.
# Validación conceptual
verify_signature(id_token, expected_provider_keys)
assert id_token.iss == expected_issuer
assert client_id in id_token.aud
assert current_time < id_token.exp
assert id_token.nonce == expected_nonce
Uno de los errores más interesantes aparece cuando una aplicación verifica que un token tiene una firma válida pero no comprueba correctamente su audience.
Un token puede haber sido emitido correctamente por Google, Microsoft u otro proveedor y seguir sin estar destinado a nuestra aplicación. La autenticidad del emisor no sustituye a la validación del destinatario.
UserInfo también debe relacionarse con la identidad autenticada
Si la aplicación utiliza el endpoint UserInfo de OpenID Connect, existe otra validación importante: el claim sub recibido en la respuesta de UserInfo debe coincidir exactamente con el sub del ID Token utilizado para esa sesión.
De lo contrario, la aplicación podría terminar asociando información de un usuario con la autenticación de otro.
Fallo 6: OAuth mix-up cuando existen varios proveedores
Las aplicaciones que permiten autenticarse contra varios Authorization Servers tienen una frontera adicional que a veces pasa desapercibida: recordar con qué proveedor comenzó cada transacción.
Imagina una aplicación que admite varios proveedores:
Proveedor A → accounts.identity-a.example Proveedor B → login.identity-b.example
En un mix-up attack, el objetivo es hacer que el cliente confunda el proveedor que inició el proceso y termine enviando un código o credencial al endpoint equivocado.
RFC 9207 introdujo el parámetro iss en la respuesta OAuth precisamente para permitir que el cliente identifique explícitamente qué Authorization Server produjo la respuesta.
Cuando una aplicación interactúa con múltiples Authorization Servers debe comprobar esa identidad.
# El flujo se inició con: expected_issuer = https://identity-a.example # La respuesta declara: iss = https://identity-b.example → abortar la transacción
Utilizar redirect URIs diferentes por proveedor puede servir como defensa alternativa en determinadas arquitecturas, pero identificar explícitamente el issuer evita depender únicamente de la estructura de las URLs.
Fallo 7: account linking basado únicamente en email
Uno de los fallos más interesantes no ocurre necesariamente dentro del protocolo, sino en la lógica que la aplicación construye encima.
Supongamos que la aplicación recibe este perfil:
{
"iss": "https://identity.example",
"sub": "248289761001",
"email": "[email protected]",
"email_verified": true
}
Una implementación rápida podría buscar una cuenta local mediante el email y, si existe, iniciar sesión automáticamente en ella o vincular la nueva identidad.
El problema es que OpenID Connect no define el email como un identificador estable ni único del usuario. Puede cambiar, puede reutilizarse y distintos issuers pueden aplicar políticas diferentes.
OIDC define como identificador estable la combinación:
(iss, sub)
https://identity.example + 248289761001
El sub identifica al sujeto dentro del contexto del issuer y está diseñado precisamente para que el Relying Party pueda diferenciar identidades de forma estable.
Si se quiere vincular una nueva identidad OAuth/OIDC a una cuenta existente, el proceso de account linking debería disponer de controles adicionales: sesión autenticada, reautenticación cuando proceda, confirmación explícita y comprobaciones de propiedad adecuadas.
email_verified=true indica que el proveedor verificó ese email según sus procedimientos. No convierte el email en un identificador universal, inmutable o exclusivo.Fallo 8: fuga y reutilización de tokens
Incluso con un flujo OAuth correctamente construido, los tokens siguen siendo credenciales. Un access token bearer tradicional puede utilizarlo quien consiga obtenerlo mientras siga siendo válido y el Resource Server lo acepte.
Fuga mediante URLs y Referer
RFC 9700 documenta que información sensible relacionada con una respuesta OAuth puede filtrarse a través de la cabecera Referer, especialmente cuando una página que participa en el flujo carga recursos externos o dirige posteriormente al usuario hacia otra ubicación.
La página de callback debería ser especialmente austera:
- procesar inmediatamente el authorization code;
- evitar scripts, analítica, imágenes u otros recursos de terceros innecesarios;
- evitar que credenciales permanezcan innecesariamente en la URL;
- aplicar una política de referrer restrictiva cuando corresponda;
- redirigir posteriormente a una URL limpia.
Tokens dentro del navegador
Otro error habitual es considerar localStorage una frontera de seguridad.
No lo es frente a JavaScript ejecutándose en el mismo origen. Si existe un XSS o se compromete un script que forma parte de la aplicación, ese código puede acceder a los mecanismos de almacenamiento disponibles para la propia aplicación.
RFC 10017, publicado en agosto de 2026 como Best Current Practice para aplicaciones OAuth ejecutadas en navegador, analiza específicamente estas amenazas y diferentes arquitecturas para reducir la exposición de tokens.
Una de ellas es el patrón Backend for Frontend (BFF): el backend actúa como cliente OAuth confidencial, conserva los access y refresh tokens y expone al navegador una sesión basada en cookie. De esta forma los tokens OAuth no tienen que quedar disponibles directamente para el JavaScript de la aplicación.
# Aplicación de navegador manejando tokens directamente Browser JavaScript → access token → API # Patrón BFF Browser → cookie de sesión → BFF → access token → API ↑ token permanece en backend
Las cookies de una arquitectura BFF deben configurarse correctamente —por ejemplo, con Secure y HttpOnly— y el backend sigue necesitando protección frente a CSRF. Cambiar tokens por cookies sin revisar el modelo de amenazas no resuelve automáticamente el problema.
Limitar el daño si el token se roba
Las buenas prácticas actuales combinan varias defensas:
- audience restriction: el token solo debería poder utilizarse contra el Resource Server para el que fue emitido;
- scopes mínimos: conceder únicamente los privilegios necesarios;
- vida limitada: reducir la ventana útil de un token filtrado;
- sender-constrained tokens: vincular el token al cliente que puede demostrar posesión de una clave.
Entre los mecanismos de sender-constraining se encuentran DPoP y los access tokens vinculados mediante mutual TLS.
Un bearer token tradicional funciona porque quien lo posee puede presentarlo. Con DPoP, además del token, el cliente debe demostrar posesión de la clave privada asociada.
Bearer token tradicional token robado → potencialmente reutilizable Token ligado mediante proof-of-possession token robado + sin clave privada → replay bloqueado
Esto reduce considerablemente determinados escenarios de replay, aunque no convierte en inocuo un XSS capaz de ejecutar acciones dentro del contexto legítimo de la propia aplicación.
Refresh tokens: el objetivo de larga duración
Un access token suele tener una vida relativamente corta. Un refresh token puede permitir obtener nuevos access tokens durante mucho más tiempo, por lo que su compromiso tiene un impacto diferente.
Para clientes públicos, RFC 9700 exige mecanismos capaces de detectar o impedir el replay de refresh tokens mediante estrategias como:
- sender-constrained refresh tokens, ligados criptográficamente a una instancia del cliente; o
- refresh token rotation, entregando un refresh token nuevo cada vez que se utiliza el anterior.
Con rotación, el servidor mantiene suficiente información para detectar que un refresh token antiguo vuelve a aparecer.
Uso legítimo RT1 → access token + RT2 RT1 queda invalidado RT2 → access token + RT3 RT1 reaparece después RT1 → token reutilizado: posible compromiso
El servidor no tiene por qué saber inicialmente si quien reutilizó el token fue el atacante o el cliente legítimo, pero puede detectar que existen dos partes intentando utilizar la misma cadena de credenciales e invalidar la autorización asociada.
La gestión de refresh tokens debe considerar además expiración, revocación, inactividad y eventos relevantes como logout o cambios importantes en la relación de autorización.
Qué cambia realmente con OAuth 2.1
Hay que hacer aquí una precisión importante: a septiembre de 2026 OAuth 2.1 todavía es un Internet-Draft del IETF y no un RFC definitivo.
La versión activa en septiembre de 2026 es draft-ietf-oauth-v2-1-16. El objetivo de OAuth 2.1 no es inventar un protocolo completamente diferente, sino consolidar en una especificación moderna muchas de las prácticas de seguridad que la comunidad ha aprendido durante años de despliegues de OAuth 2.0.
| Área | OAuth 2.0 original | Dirección de OAuth 2.1 |
|---|---|---|
| Authorization Code | PKCE fue definido posteriormente como una extensión. | PKCE forma parte del funcionamiento normal del Authorization Code Flow. |
redirect_uri |
Las implementaciones históricas han permitido distintos comportamientos. | Comparación exacta contra las URIs registradas, con excepciones específicamente definidas. |
| Implicit Grant | Definido en OAuth 2.0. | Ya no forma parte del framework. |
| Resource Owner Password Credentials | Incluido en OAuth 2.0. | Ya no forma parte del framework. |
| Refresh tokens en clientes públicos | Menos prescriptivo. | Se incorporan las protecciones modernas contra replay. |
Lo importante desde pentesting es que no hace falta esperar a que OAuth 2.1 se convierta en RFC para exigir muchas de estas propiedades. RFC 9700 ya representa la Best Current Practice de seguridad para despliegues OAuth 2.0.
Cómo auditar un flujo OAuth/OIDC
Una auditoría útil no debería limitarse a modificar un parámetro aislado. Primero hay que reconstruir la transacción completa y entender qué componente confía en qué otro componente.
| Área | Qué revisar |
|---|---|
| Redirect URI | Coincidencia exacta, wildcards, subdominios, normalización, rutas y open redirects. |
| PKCE | Uso de S256, obligatoriedad, vinculación por transacción y comportamiento ante parámetros inconsistentes. |
| CSRF | state, nonce, PKCE y su vinculación real a la sesión que inició el flujo. |
| Authorization code | Vida útil, un solo uso, cliente correcto e imposibilidad de inyectarlo en otra sesión. |
| ID Token | Firma, iss, aud, exp, nonce y, cuando corresponda, azp. |
| UserInfo | Correspondencia del sub con la identidad autenticada mediante el ID Token. |
| Varios proveedores | Identificación del issuer y resistencia frente a mix-up. |
| Account linking | Uso de (iss, sub), confianza en email y proceso de vinculación de nuevas identidades. |
| Access tokens | Audience, scopes, duración, almacenamiento, logs y posibilidad de replay. |
| Refresh tokens | Rotación, sender-constraining, expiración, revocación y detección de reutilización. |
| Callback | Scripts externos, analítica, Referer, historial y eliminación rápida de credenciales de la URL. |
También conviene analizar las peticiones sin depender de la interfaz. El navegador muestra el camino feliz, pero las propiedades realmente interesantes suelen encontrarse en las relaciones entre Authorization Server, token endpoint, callback, Resource Server y lógica interna de la aplicación.
Una pregunta especialmente útil durante toda la auditoría es:
¿Qué demuestra realmente este valor?
client_id → identifica al cliente, pero normalmente no es un secreto
access token → concede acceso a determinados recursos
ID Token → contiene afirmaciones de identidad para una audiencia concreta
state → puede vincular la respuesta con la transacción del navegador
nonce → vincula el ID Token con una autenticación iniciada previamente
PKCE → vincula el authorization code con quien conoce el verifier
iss → identifica al emisor que produjo la respuesta o token
sub → identifica al sujeto dentro del contexto de un issuer
Entender esas propiedades ayuda mucho más que memorizar una lista de parámetros.
Qué significa para seguridad ofensiva
OAuth y OpenID Connect aparecen en aplicaciones web, APIs, entornos empresariales, aplicaciones móviles y arquitecturas cloud. Por eso una vulnerabilidad en estos flujos puede atravesar varias capas de una aplicación al mismo tiempo: autenticación, autorización, lógica de negocio y gestión de sesión.
Además, muchas vulnerabilidades no dependen de una carga especialmente compleja. El trabajo está en comprender qué artefacto pertenece a cada transacción, qué servidor debería aceptarlo y qué propiedades tendría que validar antes de confiar en él.
Ese razonamiento empieza con fundamentos como HTTP, sesiones, autenticación y autorización, que trabajamos en el curso Web eXploitation Junior (WXJ), y se profundiza en el curso Web eXploitation Expert (WXE), donde OAuth, OIDC, JWT, APIs, autenticación y lógica de negocio forman parte del análisis avanzado de aplicaciones web.
La diferencia entre encontrar un endpoint OAuth y encontrar una vulnerabilidad real suele estar precisamente ahí: dejar de mirar parámetros aislados y reconstruir la frontera de confianza completa.
¿Quieres aprender a auditar autenticación, APIs y lógica de negocio más allá de los fallos básicos?
En SixHack Academy puedes empezar construyendo una base sólida con Web eXploitation Junior (WXJ) y continuar con Web eXploitation Expert (WXE), donde profundizamos en autenticación moderna, JWT, OAuth/OIDC, APIs y escenarios de explotación web avanzada.
Preguntas frecuentes
¿Qué diferencia hay entre OAuth 2.0 y OpenID Connect?
OAuth 2.0 es principalmente un framework de autorización: permite que una aplicación obtenga acceso limitado a determinados recursos. OpenID Connect añade una capa de identidad sobre OAuth 2.0 y permite autenticar al usuario mediante elementos como el ID Token.
¿PKCE sustituye siempre al parámetro state?
No de forma universal. RFC 9700 permite apoyarse en PKCE como protección frente a CSRF cuando el cliente ha verificado que el Authorization Server soporta PKCE correctamente. state sigue siendo necesario en otras situaciones y continúa siendo útil para mantener estado de aplicación. En OIDC, nonce también tiene un papel importante en la vinculación de la transacción.
¿Para qué sirve PKCE?
Vincula un authorization code con un secreto efímero generado por el cliente. Aunque otra parte obtenga el código, no debería poder canjearlo sin conocer el code_verifier correspondiente. También ayuda a prevenir ataques de inyección de códigos.
¿Es inseguro guardar un access token en localStorage?
localStorage no protege un token frente a JavaScript malicioso ejecutándose en el mismo origen, por ejemplo a través de XSS o de un script comprometido. En aplicaciones sensibles pueden utilizarse arquitecturas como BFF para mantener los tokens fuera del contexto JavaScript del navegador.
¿Una cookie HttpOnly soluciona el problema?
No por sí sola. HttpOnly evita que JavaScript lea directamente la cookie, pero una aplicación que utiliza cookies necesita seguir contemplando CSRF y otros ataques donde código malicioso actúa desde el navegador de la víctima.
¿Qué campos de un ID Token debo validar?
Entre otros controles, deben verificarse su firma, el issuer (iss), la audience (aud), la expiración (exp) y, cuando corresponda, el nonce. En determinados casos también debe validarse azp. La validación exacta depende del flujo y de las características del cliente.
¿Puedo identificar un usuario OIDC únicamente por su email?
No debería utilizarse el email como identificador estable. OpenID Connect establece los Subject Identifiers mediante sub, interpretados dentro del contexto del issuer correspondiente. En la práctica, la combinación iss + sub es la referencia apropiada para identificar una identidad federada. El email puede cambiar o reutilizarse.
¿OAuth 2.1 ya ha sustituido oficialmente a OAuth 2.0?
No. A septiembre de 2026 OAuth 2.1 continúa desarrollándose como Internet-Draft del IETF. Muchas de las medidas que incorpora, sin embargo, ya representan las prácticas modernas de seguridad de OAuth y aparecen en documentos como RFC 9700.
¿Qué son los sender-constrained tokens?
Son tokens cuyo uso está ligado criptográficamente a un determinado cliente o clave. Tecnologías como DPoP y mutual TLS permiten reducir el riesgo de que un access token robado pueda reutilizarse simplemente desde otro sistema.
¿Qué es un OAuth mix-up attack?
Es una clase de ataque que afecta especialmente a clientes que trabajan con varios Authorization Servers. El objetivo es hacer que el cliente confunda qué servidor produjo una respuesta y termine utilizando códigos o credenciales contra el endpoint incorrecto. RFC 9207 define el parámetro iss como una de las principales contramedidas.
¿OAuth es solo relevante para aplicaciones web?
No. OAuth y OIDC aparecen también en aplicaciones móviles, APIs, aplicaciones de escritorio, dispositivos y entornos empresariales. El modelo de amenazas cambia según el tipo de cliente, por lo que existen recomendaciones específicas para aplicaciones nativas y aplicaciones ejecutadas en navegador.
Referencias
- RFC 9700 — Best Current Practice for OAuth 2.0 Security : recomendaciones actuales sobre redirect URIs, PKCE, CSRF, mix-up attacks, fugas de credenciales, token replay, refresh tokens y sender-constrained tokens.
- RFC 10017 — OAuth 2.0 for Browser-Based Applications : amenazas y arquitecturas recomendadas para aplicaciones OAuth ejecutadas en navegador, incluyendo Backend for Frontend (BFF), almacenamiento de tokens y riesgos derivados de JavaScript malicioso.
- RFC 6749 — The OAuth 2.0 Authorization Framework : especificación original del framework OAuth 2.0.
- RFC 7636 — Proof Key for Code Exchange by OAuth Public Clients : especificación original de PKCE y protección frente a la interceptación de authorization codes.
- OpenID Connect Core 1.0 incorporating errata set 2 : especificación principal de OIDC, incluyendo ID Tokens, nonce, claims, Subject Identifiers, UserInfo y validación de tokens.
-
RFC 9207 — OAuth 2.0 Authorization Server Issuer Identification
:
define el parámetro
issen las respuestas OAuth y su uso para prevenir la confusión entre Authorization Servers. - RFC 9449 — OAuth 2.0 Demonstrating Proof of Possession (DPoP) : define DPoP para vincular tokens a una clave y reducir determinados ataques de replay de access tokens robados.
- RFC 8705 — OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens : autenticación OAuth mediante mutual TLS y access tokens vinculados a certificados.
- RFC 8252 — OAuth 2.0 for Native Apps : Best Current Practice para implementar OAuth de forma segura en aplicaciones nativas.
- OAuth 2.1 Authorization Framework — IETF Internet-Draft : borrador activo que consolida el funcionamiento moderno de OAuth, incluyendo PKCE, validación estricta de redirect URIs y la eliminación de grants considerados obsoletos.