Saltar al contenido

Diagrama de flujo de OpenID Connect: Authorization Code Flow, ID tokens y Discovery

Cómo OpenID Connect añade el inicio de sesión a OAuth 2.0: authorization code flow con PKCE, ID token y su validación, discovery, JWKS, UserInfo y cierre de sesión.

· Fundador y desarrollador

Publicado el

Diagrama de secuencia con un usuario, un navegador, una relying party y un OpenID provider. Trece mensajes numerados cubren la redirección, el inicio de sesión, el intercambio del código y la respuesta de tokens; un fragmento critical valida el ID token y un fragmento opt llama a UserInfo.

Una app móvil inicia sesión de un usuario con un proveedor de identidad y pasa el access token a tu backend, que llama al endpoint de perfil del proveedor, obtiene una dirección de correo y crea una sesión. Todas las pruebas pasan. También permite que cualquier otra app en la que el usuario haya iniciado sesión con ese proveedor entre en tu app como él con su propio access token, porque nada comprueba para qué app se emitió el token.

OpenID Connect (OIDC) cierra esa brecha. Añade un ID token a OAuth 2.0: un JWT firmado en el que el proveedor indica quién es el usuario, para qué app es el token y cuándo inició sesión el usuario.

Este artículo dibuja el authorization code flow con PKCE como diagrama de secuencia y cubre lo que añade OIDC: el scope openid, nonce, la validación del ID token, discovery, la rotación de claves, UserInfo y el cierre de sesión.

OAuth 2.0 frente a OpenID Connect

OAuth 2.0 trata del acceso: un token para llamar a una API en nombre del usuario. OpenID Connect trata de la identidad: quién inició sesión.

OAuth 2.0 OpenID Connect
Pregunta que responde ¿Puede esta app llamar a esta API? ¿Quién es el usuario y cuándo inició sesión?
Token Access token ID token
El token está destinado a La API Tu app
Formato del token No definido: opaco o JWT Un JWT firmado
Cómo se pide Scopes que define la API scope incluye openid
Define Grants y endpoints Claims, UserInfo, discovery, cierre de sesión

En la red, un inicio de sesión OIDC es una solicitud de autorización OAuth con openid en el scope, y la respuesta de tokens trae un id_token junto al access token. El diagrama del flujo OAuth 2.0 cubre en detalle la parte OAuth.

El flujo, paso a paso

OpenID Connect Core 1.0 llama a tu app la relying party (RP) y al servidor de autorización el OpenID provider (OP). Lo que pasa por el navegador, el canal delantero, puede filtrarse a URL, historial y logs; las llamadas de tu backend al proveedor, el canal trasero, no. Los números coinciden con el diagrama.

  1. Inicio (1–3). El usuario hace clic en Sign in. Tu app guarda en la sesión un state, un nonce y un code_verifier de PKCE nuevos, y redirige el navegador al proveedor.
  2. Solicitud de autenticación (4). El navegador sigue la redirección:
GET /authorize?response_type=code
    &client_id=orders-web
    &redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback
    &scope=openid%20profile%20email
    &state=7fJq2LbX9aQe
    &nonce=n-0S6_WzA2Mj
    &code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
    &code_challenge_method=S256 HTTP/1.1
Host: op.example.com
  1. Inicio de sesión y consentimiento (5). El proveedor autentica al usuario (contraseña, passkey, MFA o una sesión existente) y pide su consentimiento. Tu app nunca ve las credenciales.
  2. Vuelta del código (6–7). El proveedor redirige al redirect_uri registrado con un code de corta duración y el mismo state, que tu app compara con el de la sesión.
  3. Solicitud de tokens (8–9). Tu backend envía por POST el code, el redirect_uri y el code_verifier con sus credenciales de cliente. El proveedor comprueba el verifier contra el challenge y devuelve un id_token, un access_token y a menudo un refresh_token.
  4. Validación (10). Tu app valida el ID token y solo descarga las claves de firma cuando la que nombra no está en caché.
  5. UserInfo (11–12), opcional. Solo cuando el ID token no trae los claims que necesitas.
  6. Sesión (13). Tu app crea su propia sesión y establece una cookie.

Qué protegen state, nonce y PKCE

Valor Viaja en Lo comprueba Impide
state El paso 4 y la redirección de vuelta Tu app Una respuesta de inicio de sesión que el usuario nunca inició (CSRF)
nonce El paso 4 y luego dentro del ID token Tu app La repetición del ID token y la inyección de código en clientes confidenciales
code_verifier Su hash SHA-256 en el paso 4, él mismo en el paso 8 El proveedor Canjear un código robado

La mejor práctica actual de seguridad de OAuth, RFC 9700, permite que uno sustituya a otro en algunos casos, pero cada uno cuesta un valor aleatorio, así que envía los tres. Los clientes públicos, como las aplicaciones de una sola página y las móviles, deben usar PKCE (RFC 7636) con S256.

Dentro del ID token

El ID token del paso 9, decodificado:

{
  "iss": "https://op.example.com",
  "sub": "248289761001",
  "aud": "orders-web",
  "nonce": "n-0S6_WzA2Mj",
  "iat": 1793736400,
  "exp": 1793740000,
  "auth_time": 1793736390
}
Claim Significado Tu app
iss Emisor, una URL https Debe ser igual al issuer descubierto, exactamente
sub ID del usuario, nunca reasignado dentro del emisor, como máximo 255 caracteres ASCII Usa iss más sub como clave de la cuenta
aud Audiencia, una cadena o un array Debe encontrar su client_id en ella
exp, iat Caducidad y hora de emisión, en segundos Unix Rechaza tokens caducados o muy antiguos
nonce El valor enviado en el paso 4 Debe coincidir con la sesión
auth_time Cuándo se autenticó realmente el usuario Lo comprueba cuando envías max_age
acr, amr Nivel de garantía y métodos, como pwd o mfa Los comprueba antes de acciones sensibles

Core es explícito: solo iss más sub identifica a un usuario, porque las direcciones de correo cambian y pueden reasignarse.

Validar el ID token

La sección 3.1.3.7 de Core enumera las reglas:

  1. Fija el algoritmo (RS256 por defecto) en lugar de fiarte de la cabecera alg, y nunca aceptes none.
  2. Verifica la firma con la clave JWKS que nombra kid. Core permite que un cliente de code flow confíe en TLS en su lugar, ya que el token llegó directo del token endpoint, pero verificar cuesta poco.
  3. Comprueba iss contra el emisor descubierto, carácter por carácter.
  4. Comprueba aud para tu client_id y rechaza las audiencias en las que no confías.
  5. Comprueba exp e iat, permitiendo de unos segundos a unos minutos de desfase de reloj.
  6. Comprueba nonce contra la sesión y bórralo después.
  7. Comprueba auth_time y acr si los solicitaste.

Solo entonces crea una sesión. Con la biblioteca jose en Node.js:

import { createRemoteJWKSet, jwtVerify } from 'jose'

// issuer and jwks_uri come from the discovery document.
// The key set is cached; an unknown kid triggers a refetch
// (at most once every 30 seconds by default).
const JWKS = createRemoteJWKSet(new URL(oidc.jwks_uri))

const { payload } = await jwtVerify(tokens.id_token, JWKS, {
  issuer: oidc.issuer,     // exact match
  audience: CLIENT_ID,     // must appear in aud
  algorithms: ['RS256'],   // never trust the header alone
  clockTolerance: 60,      // seconds of clock skew
  maxTokenAge: 600,        // rejects an old iat
})
if (payload.nonce !== session.nonce) throw new Error('nonce mismatch')

Discovery y rotación de claves

OpenID Connect Discovery 1.0 pone los ajustes de un proveedor en un único documento JSON en la URL del emisor más /.well-known/openid-configuration. El de Google, reducido a los campos que usa este flujo, en el momento de escribir esto (noviembre de 2026):

{
  "issuer": "https://accounts.google.com",
  "authorization_endpoint": "https://accounts.google.com/o/oauth2/v2/auth",
  "token_endpoint": "https://oauth2.googleapis.com/token",
  "userinfo_endpoint": "https://openidconnect.googleapis.com/v1/userinfo",
  "jwks_uri": "https://www.googleapis.com/oauth2/v3/certs",
  "id_token_signing_alg_values_supported": ["RS256"],
  "code_challenge_methods_supported": ["plain", "S256"]
}

El issuer debe ser idéntico a la URL del emisor desde la que lo obtuviste y al iss de cada ID token. Configura tú mismo el emisor esperado; nunca lo tomes de un token que no hayas verificado.

Las claves rotan a través del jwks_uri: el proveedor añade una clave nueva, firma con ella y mantiene la antigua publicada durante un tiempo (Core, sección 10.1.1). Guarda el conjunto en caché, respeta Cache-Control, vuelve a descargarlo ante un kid desconocido y limita la frecuencia de esas descargas. El diagrama del flujo de autenticación JWT cubre la misma mecánica para los access tokens.

UserInfo

UserInfo devuelve claims para los scopes concedidos (profile, email, address, phone) cuando lo llamas con el access token. Su respuesta siempre contiene sub, que debe coincidir exactamente con el sub del ID token, o descartas la respuesta.

Opciones de cierre de sesión

Tres especificaciones OpenID finales cubren el cierre de sesión:

Especificación Cómo funciona Ten en cuenta
RP-Initiated Logout 1.0 Tu app redirige al end_session_endpoint del proveedor con id_token_hint Tu app también debe terminar su propia sesión
Front-Channel Logout 1.0 El proveedor carga la URL de cierre de sesión de cada app en un iframe El bloqueo de cookies de terceros puede romperlo
Back-Channel Logout 1.0 El proveedor envía por POST un logout token firmado a cada app Tu app debe encontrar y terminar la sesión en el servidor

Core también señala que el exp del ID token no guarda relación con la duración de la sesión.

Errores que aparecen en las revisiones

  • Un access token como prueba de identidad. La escena inicial. Inicia sesión de los usuarios solo con un ID token que tu backend obtuvo del token endpoint y validó.
  • Omitir aud o nonce. Todas las apps registradas en el mismo proveedor reciben ID tokens válidamente firmados con el mismo iss; solo aud dice que un token se emitió para ti, y solo nonce lo vincula a este inicio de sesión.
  • El implicit flow. response_type=id_token token pone los tokens en el fragmento de la URL; la RFC 9700 dice que los clientes no deberían usar response types que devuelvan access tokens en la respuesta de autorización. Usa code con PKCE, también en aplicaciones de una sola página.
  • ID tokens enviados a las API. Las API deberían aceptar solo access tokens emitidos para ellas; el diagrama de arquitectura de un API gateway muestra dónde suele estar esa comprobación.

El diagrama del flujo de OpenID Connect

Diagrama de secuencia con un usuario, un navegador, una relying party y un OpenID provider. Trece mensajes numerados cubren la redirección, el inicio de sesión, el intercambio del código y la respuesta de tokens; un fragmento critical valida el ID token y un fragmento opt llama a UserInfo.

16 componentes · 13 conexiones

Abrir en Archboard
Contenido del diagrama
  • User
  • Browser
  • Relying party (your app)
  • OpenID provider
  • all checks must pass
  • claims missing from the ID token
  • ID token: for your app (aud = client_id)
  • Access token: for UserInfo and APIs
  • 1. Click Sign in
  • 2. GET /login
  • 3. 302 to the provider's /authorize
  • 4. GET /authorize: scope=openid, state, nonce, code_challenge
  • 5. Log in (password, passkey, MFA) and consent
  • 6. 302 to redirect_uri with code, state
  • 7. GET /callback?code&state
  • 8. POST /token: code, code_verifier, client auth
  • 9. id_token, access_token
  • 10. GET jwks_uri (when kid is not cached)
  • 11. GET /userinfo, Bearer access_token
  • 12. Claims; sub must match the ID token
  • 13. 302 to the app, Set-Cookie: session
El authorization code flow de OpenID Connect con PKCE. Tu app envía el navegador al proveedor con scope=openid, state, nonce y un code challenge, intercambia el código por el canal trasero y valida el ID token antes de crear una sesión.

Cómo leerlo:

  • Cuatro participantes: el usuario, el navegador, tu app (la relying party) y el OpenID provider. El tiempo corre hacia abajo.
  • Los colores muestran el canal: azul a través del navegador, verde azulado de tu backend al proveedor, violeta para las acciones del usuario. Las flechas discontinuas son respuestas y redirecciones.
  • Los pasos 3 y 4 llevan scope=openid, state, nonce y el challenge de PKCE; el paso 8 lleva el verifier.
  • El fragmento critical contiene la descarga de claves y las comprobaciones que deben pasar antes de que exista una sesión. El fragmento opt es la llamada a UserInfo.
  • La columna derecha asocia los campos de discovery con los pasos, enumera los parámetros de PKCE, decodifica un ID token y muestra qué token es para quién.

Cómo dibujar con claridad diagramas de OpenID Connect

  • Dale al navegador su propia línea de vida. La separación entre canal delantero y trasero es la historia de seguridad del flujo.
  • Escribe en las flechas los parámetros comprobados: state, nonce, code_challenge, code_verifier.
  • Detalla la validación. «Validar token» no se puede revisar; «firma, iss, aud, exp, iat, nonce» sí.
  • Indica qué token va adónde, con su audiencia. Muchos errores de OIDC son un token enviado a la parte equivocada.
  • Un flujo por diagrama. Dibuja por separado el inicio de sesión, la renovación y el cierre de sesión, con ID y tokens de ejemplo.

El ejemplo de diagrama de secuencia cubre la notación; el diagrama del flujo SAML SSO muestra el protocolo basado en XML que los clientes empresariales aún piden.

Constrúyelo en Archboard

  1. Inicia sesión con Google o GitHub y crea un diagrama.
  2. Desde el pack Secuencia, añade un Actor para el usuario y tres nodos Línea de vida de la misma altura: Browser, Relying party (tu app) y OpenID provider.
  3. Dibuja los 13 mensajes como aristas rectas numeradas, de arriba abajo. Haz discontinuas las respuestas y colorea de forma distinta el canal delantero y el trasero.
  4. Añade un Fragmento combinado del pack Secuencia con el operador critical alrededor de la descarga de claves y las comprobaciones, y un segundo Fragmento combinado con opt alrededor de la llamada a UserInfo.
  5. Añade un Texto del pack Básico junto a la relying party para los valores de sesión y las comprobaciones, además de una leyenda de colores.
  6. Añade un bloque Markdown del pack Básico para discovery, PKCE y un ID token decodificado, y dos nodos Token del pack Seguridad para el ID token y el access token.

El ejemplo usa 9 nodos de diagrama, dentro del plan Free. Tu agente de IA también puede dibujarlo por MCP.

Preguntas frecuentes

¿Cuál es la diferencia entre OAuth 2.0 y OpenID Connect? OAuth 2.0 da a una app un access token para llamar a una API. OpenID Connect añade el inicio de sesión encima: el scope openid, un ID token que dice quién es el usuario y endpoints estándar de discovery y UserInfo.

¿Es un ID token lo mismo que un access token? No. El ID token es un JWT firmado para tu app que dice quién inició sesión. El access token es para las API, incluida UserInfo. Nunca envíes ID tokens a las API ni aceptes access tokens como prueba de inicio de sesión.

¿Necesito PKCE si ya envío un nonce? Usa ambos. La RFC 9700 exige PKCE para los clientes públicos. Un cliente confidencial puede apoyarse en el nonce con precauciones adicionales, pero PKCE impide canjear un código robado, mientras que el nonce solo detecta un código inyectado después de la respuesta de tokens.

¿Cómo valido un ID token? Verifica la firma con la clave JWKS que coincida con su kid y comprueba que iss sea igual al emisor, que aud contenga tu client ID, que exp no haya pasado, que iat sea reciente y que nonce coincida con la sesión.

¿Qué es /.well-known/openid-configuration? El documento de discovery de OpenID Connect. Enumera el emisor, los endpoints, los algoritmos y el jwks_uri de un proveedor, para que tu app pueda configurarse desde una sola URL.

Empieza gratis — un puesto, sin tarjeta de crédito.

Artículos relacionados

← Volver al blog

Abre un lienzo en un minuto

Inicia sesión con Google o GitHub. Gratis para un asiento. Mejora el plan cuando se una el equipo.