OAuth 2.1 y OIDC bien explicados: guía para implementar identidad sin sustos
OAuth delega permisos, no autentica personas. La mayoría de los fallos de identidad nacen de esa confusión. Aquí tienen el modelo mental, los flujos y la lista de validación que de verdad aguantan en producción.
Por Innovation T Team
OAuth es un protocolo de delegación, no de autenticación. Ese único malentendido está detrás de la mitad de los fallos de identidad que encontramos en las auditorías de seguridad. Si su equipo publica botones de inicio de sesión, tokens de API o servicios máquina a máquina, los próximos diez minutos de lectura les van a ahorrar un incidente.
Desaprendan el modelo mental equivocado
OAuth 2.x responde exactamente a una pregunta: si esta aplicación tiene permiso para llamar a esta API, posiblemente en nombre de un usuario. No dice nada fiable sobre quién es ese usuario. OpenID Connect (OIDC) es la capa de identidad construida encima: añade un ID token, un endpoint de UserInfo y reglas estrictas para que un cliente sepa que un evento de autenticación ocurrió de verdad.
La distinción no es un tecnicismo de académicos. Si su backend interpreta "recibí un access token" como "este usuario está autenticado", cualquier aplicación que haya obtenido legítimamente un token para ese usuario puede reenviarlo contra su API y suplantarlo. Ese problema de reutilización de access tokens es exactamente la razón por la que existe OIDC. Delegación y autenticación son afirmaciones distintas y necesitan tokens distintos.
Peguen esta frase en la pared del equipo: OAuth habla de lo que una aplicación puede hacer, OIDC habla de quién es el usuario.
Qué cambia realmente OAuth 2.1
OAuth 2.1 sigue siendo un borrador del IETF, pero trátenlo como la línea base. Es OAuth 2.0 con una década de lecciones de seguridad incorporadas, la mayoría formalizadas antes en el RFC 9700, la guía de buenas prácticas de seguridad de OAuth. Construir hoy sobre 2.1 significa, sencillamente, hacer 2.0 bien.
Los cambios concretos:
- El flujo implícito está muerto. Los tokens entregados en fragmentos de URL se filtraban por el historial del navegador, las cabeceras referrer y los proxies con registro. No había forma de arreglarlo, así que se eliminó.
- El flujo de contraseña del propietario del recurso está muerto. Cualquier flujo que enseñe a los usuarios a escribir su contraseña en una aplicación de terceros es un curso acelerado de phishing.
- PKCE es obligatorio en todo flujo de código de autorización, clientes confidenciales incluidos. Elimina la interceptación del código de autorización y añade protección contra CSRF sin coste adicional.
- Las redirect URIs deben coincidir de forma exacta. Sin comodines, sin coincidencia por prefijo, sin "cualquier cosa bajo este subdominio".
- Los refresh tokens de clientes públicos deben ser de un solo uso (rotación) o estar vinculados criptográficamente al cliente que los presenta.
- Los bearer tokens en la query string quedan prohibidos. Acaban en los registros de acceso para siempre.
Si su proveedor de identidad o su propia implementación incumple cualquiera de estos puntos, ahí tienen su lista de remediación, ya ordenada por prioridad.
Las piezas del sistema, con precisión
Cuatro roles:
- Propietario del recurso: la persona dueña de los datos.
- Cliente: la aplicación que solicita acceso (SPA, aplicación móvil, servicio de backend).
- Servidor de autorización (AS): emite tokens tras autenticar al usuario y registrar su consentimiento. Keycloak, Auth0, Entra ID, Cognito, Zitadel.
- Servidor de recursos (RS): su API, la que acepta y valida access tokens.
Tres tokens, con trabajos muy distintos:
- Access token: una credencial para el servidor de recursos. De vida corta. El cliente debe tratarlo como una cadena opaca, incluso cuando resulta ser un JWT.
- Refresh token: una credencial de larga vida que el cliente intercambia por nuevos access tokens sin molestar al usuario. Lo más valioso que un atacante puede robar.
- ID token (solo OIDC): un JWT dirigido al cliente, no a ninguna API. Afirma "este usuario se autenticó en este momento, por este método". Su audiencia es su client_id.
Dos reglas evitan familias enteras de errores:
- Los ID tokens nunca cruzan la frontera de una API. Los consume el cliente y ahí termina su trabajo.
- Los clientes nunca toman decisiones analizando el contenido de un access token. El contenido del token es un contrato entre el AS y el RS.
Los flujos que importan en 2026
Necesitan cuatro. Todo lo demás es legado.
Código de autorización con PKCE
El flujo por defecto para cualquier cosa interactiva: aplicaciones web, SPAs, móvil. El cliente genera un secreto aleatorio (el verifier), envía su hash SHA-256 (el challenge) con la solicitud de autorización, y demuestra que posee el verifier al canjear el código. Un atacante que intercepte el código no puede canjearlo.
const verifier = base64url(crypto.getRandomValues(new Uint8Array(32)));
const digest = await crypto.subtle.digest(
"SHA-256", new TextEncoder().encode(verifier)
);
const challenge = base64url(new Uint8Array(digest));
La solicitud de autorización debe llevar siempre response_type=code, code_challenge con code_challenge_method=S256, un valor de state que se verifica al volver y, para OIDC, scope=openid más un nonce que se comprueba dentro del ID token. Saltarse state o nonce porque "PKCE ya lo cubre" es un atajo frecuente. PKCE cubre la mayor parte. La defensa en profundidad cuesta dos cadenas aleatorias.
Client credentials
Máquina a máquina, sin usuario de por medio: un servicio de facturación llamando a una API de emisión de comprobantes, un cron nocturno descargando informes. El cliente se autentica con sus propias credenciales y recibe un token con su propio alcance. Aquí importan dos disciplinas: pedir tokens para una audiencia concreta, nunca una universal, y guardar el client secret en un vault con rotación, no en un archivo de entorno subido al repositorio "de forma temporal".
Device authorization grant
Para dispositivos con entrada limitada: televisores inteligentes, CLIs, quioscos. El dispositivo muestra un código corto, el usuario aprueba desde su teléfono y el dispositivo consulta periódicamente hasta recibir el token. Si alguna vez han escrito un código en github.com/login/device, ya lo han usado.
Token exchange
RFC 8693, para cadenas de servicios. El servicio A recibe el token de un usuario y necesita llamar al servicio B en nombre de ese usuario. El antipatrón es reenviar el token original a través de cinco servicios, cada uno aceptando un token que nunca fue emitido para él. Token exchange permite que A cambie el token entrante por uno nuevo, con alcance para B y con la cadena de delegación registrada en el claim act. En nuestra experiencia, esta es la pieza que le falta a la mayoría de las arquitecturas de microservicios, y explica por qué un solo token robado abre tan a menudo la plataforma entera.
Validen tokens como si les fuera algo en ello
Los access tokens vienen en dos formatos. Los tokens opacos exigen una llamada al endpoint de introspección (RFC 7662): más latencia, revocación instantánea. Los JWT se validan localmente contra las claves publicadas por el AS (JWKS): rápido, pero la revocación solo surte efecto al expirar. El compromiso estándar son access tokens JWT con una vida de 5 a 15 minutos más rotación de refresh tokens, reservando la introspección para operaciones de alto valor.
La validación local de JWT es donde las auditorías sacan sangre. Ejecuten esta lista en cada servidor de recursos, todas las veces:
- Obtengan las claves de firma del endpoint JWKS, seleccionen por
kidy cacheen con un TTL razonable. Nunca claves escritas a mano en el código. - Fijen una lista blanca de algoritmos. Esperen
RS256oES256y rechacen todo lo demás. Esa única línea eliminaalg: noney el clásico ataque de confusión de claves de RS256 a HS256. - Comprueben
isscontra la URL exacta del emisor. Https, y ojo con las sorpresas de la barra final. - Comprueben que
audcontiene el identificador de su API. Un token válido para la API de otro no es un token válido para la suya. - Apliquen
expynbfcon una tolerancia de reloj pequeña, de 60 a 120 segundos. - Para los ID tokens, verifiquen además que el
noncecoincide con el enviado, yazpcuando hay varias audiencias. - Y después, autoricen. Que la firma sea válida significa que el AS lo emitió. No significa que este llamante pueda borrar este registro. Comprueben scopes y roles por endpoint.
En ASP.NET Core, casi todo esto se reduce a configuración:
options.TokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = "https://id.example.com",
ValidAudience = "api://orders",
ValidAlgorithms = new[] { "RS256" },
ClockSkew = TimeSpan.FromSeconds(60)
};
Existen ajustes equivalentes en jose para Node, spring-security-oauth2-resource-server para Java y authlib para Python. Usen una librería mantenida. El análisis de JWT hecho a mano es la vía directa hacia un incidente de alg: none. Para el panorama completo de endurecimiento de sus endpoints, vean nuestra guía de buenas prácticas de seguridad de APIs.
Dónde viven los tokens en el navegador
La verdad incómoda: no existe un lugar totalmente seguro para los tokens en el JavaScript del navegador. localStorage sobrevive a un XSS exactamente el tiempo que tarda en exfiltrarse. Los tokens en memoria son mejores, pero mueren al recargar la página y siguen cayendo ante una inyección de script que intercepte su cliente HTTP.
El patrón que recomendamos para cualquier proyecto serio es Backend for Frontend (BFF). El baile de OAuth ocurre en el servidor. Los tokens nunca llegan al navegador. La SPA recibe una cookie HttpOnly, Secure y SameSite vinculada a una sesión de servidor, y el BFF adjunta el access token a las llamadas hacia arriba. Un XSS todavía puede aprovechar la sesión mientras la página está abierta, pero ya no puede robar un refresh token y llevarse acceso persistente.
Vivan donde vivan los refresh tokens, rótenlos. Cada refresco emite un refresh token nuevo e invalida el anterior. Si alguna vez se presenta un token ya usado, esa es su señal de robo: revoquen toda la familia de tokens y fuercen una nueva autenticación. La mayoría de los proveedores maduros lo soportan de fábrica, pero viene desactivado por defecto más veces de las que uno esperaría. Los tokens vinculados al portador legítimo mediante DPoP van un paso más allá al atar cada token a una clave en poder del cliente, y su adopción crece de forma sostenida.
Los fallos que seguimos encontrando
- ID tokens usados como credenciales de API. El RS acepta cualquier JWT con firma válida y nunca comprueba
aud. Solución: verificación de audiencia en todas partes. - Coincidencia laxa de redirect URIs. Un comodín más un open redirect en cualquier subdominio que coincida equivale a códigos de autorización robados.
stateynonceausentes. CSRF de inicio de sesión y fijación de sesión, explotables en silencio durante años.- Un token todopoderoso para todos los servicios. Sin tokens por audiencia, sin token exchange. Un solo pod comprometido puede llamar a cualquier cosa. Este es precisamente el fallo que una arquitectura Zero Trust está diseñada para contener.
- Access tokens de 24 horas sin plan de revocación. Cuando roban un portátil, "esperar hasta mañana" no es un plan de respuesta a incidentes.
- Aplicaciones móviles con esquemas de URI personalizados para las redirecciones. Cualquier aplicación instalada puede registrar el mismo esquema e interceptar el código. Usen redirecciones https verificadas: App Links en Android, Universal Links en iOS.
- Client secrets embebidos en SPAs y binarios móviles. Los clientes públicos no pueden guardar secretos. Para eso existe PKCE.
Construir, comprar o autogestionar
Nunca construyan su propio servidor de autorización. La superficie del protocolo (endpoints de tokens, consentimiento, rotación de claves, gestión de sesiones, revocación) es enorme y hostil. La decisión real es gestionado frente a autogestionado:
- Gestionado (Auth0, Cognito, Entra External ID): lo más rápido para llegar a producción, valores por defecto sólidos, y un precio por usuario activo que suele parecer barato al principio y doloroso a escala. En nuestra experiencia, la conversación sobre precios empieza en algún punto de las decenas de miles de usuarios activos mensuales, y para una startup latinoamericana que factura en moneda local y paga la licencia en dólares, el salto duele el doble.
- Autogestionado (Keycloak, Zitadel, Ory Hydra, Authentik): control total, residencia de datos (un argumento de peso bajo el RGPD y la LOPDGDD en España, y cada vez más relevante en sectores regulados de América Latina), sin tarifas por usuario. A cambio, las actualizaciones, el endurecimiento, la disponibilidad y la gestión de claves corren de su cuenta. Presupuesten tiempo real de ingeniería, no un fin de semana.
Elijan lo que elijan, exijan: certificación OIDC, soporte de PKCE y rotación de refresh tokens, audiencias por API, vidas de token cortas y bajo su control, y soporte de WebAuthn, porque el inicio de sesión con contraseña tiene los días contados. Si las passkeys están en su hoja de ruta, y deberían estarlo, OIDC sigue siendo el mecanismo de entrega: nuestro artículo sobre passkeys y autenticación sin contraseñas explica cómo encajan las piezas.
El protocolo ya no es la parte difícil. La disciplina sí: redirecciones exactas, PKCE obligatorio, tokens restringidos por audiencia, vidas cortas, rotación con detección de reutilización y listas de validación exigidas en la revisión de código. Los equipos que interiorizan esos seis hábitos, sencillamente, dejan de tener incidentes de OAuth.
Cómo puede ayudar Innovation T
Innovation T diseña y construye infraestructura de identidad como oficio: integraciones OIDC, arquitecturas BFF para SPAs, despliegues de Keycloak y de IdP en la nube, token exchange para arquitecturas de microservicios y auditorías de implementaciones OAuth existentes contra la línea base de 2.1. Hemos visto todos los fallos de esta lista en producción y sabemos cerrarlos sin romper las sesiones de sus usuarios.
Si están eligiendo proveedor de identidad, desenredando un flujo implícito heredado o endureciendo un parque de APIs, conozcan nuestros servicios o hablen con nuestro equipo. Les diremos sin rodeos qué arreglar primero.
¿Listo para construir con Innovation T?
Ya se trate de seguridad, crecimiento o ingeniería, nuestro equipo puede ayudarte a lograrlo con calidad.