OpenID Connect · OAuth 2.0

Funciones avanzadas, explicadas con sencillez

Estos mecanismos refuerzan la seguridad del flujo base. Cada uno responde a una debilidad concreta: partimos del problema y luego la solución.

El hilo conductor

El flujo base envía información a través del navegador, donde cualquiera puede manipularla. Las funciones avanzadas lo corrigen en cada paso: PAR y JAR protegen la solicitud, private_key_jwt protege la identidad de la aplicación, JARM protege la respuesta, DPoP protege el token una vez emitido y CIBA gestiona el caso en que no hay navegador. A ello se suman resource (qué API), RAR (qué operación precisa), acr (qué nivel de autenticación) y el registro dinámico de clientes.

private_key_jwt · PAR · JAR · JARM · DPoP · CIBA · Resource indicators · RAR · acr y step-up · Registro dinámico de clientes · Pairwise y userinfo firmado

private_key_jwt

RFC 7523 / OIDC Core 9

Pruebe quién es con una firma en lugar de una contraseña compartida.

El problema

Un cliente confidencial se autentica normalmente con un «client_secret», una contraseña que conocen el cliente y el servidor. Si se filtra en un lado, el otro no tiene forma de saberlo, y el secreto viaja por archivos de configuración.

Cómo funciona

El cliente conserva una clave privada que nunca sale de sus instalaciones. En cada llamada construye una pequeña «atestación» firmada (un JWT) que dice «soy este cliente, me dirijo a este servidor y esto solo es válido unos minutos». El servidor solo tiene la clave pública: verifica la firma, y nada más.

Como imagen

En lugar de una contraseña que conoce el guardia, firma cada entrada con su pluma personal; el guardia solo tiene un espécimen de su firma.

Cuándo usarlo

Bancos, administraciones públicas, cualquier entorno que prohíba los secretos compartidos. Obligatorio en varios perfiles de seguridad (FAPI).

Trampas

Aserción reutilizada (de ahí el identificador «jti» de un solo uso), audiencia incorrecta, duración demasiado larga, clave errónea.

En ID-Kit

Cree un cliente «Confidencial con clave (private_key_jwt)» en su proveedor de pruebas, pegue su certificado o JWKS público y luego llame a /token con client_assertion. ID-Kit le dice con precisión por qué se rechaza una aserción.

PAR: pushed authorization request

RFC 9126

Enviar su solicitud de inicio de sesión directamente al servidor, sin pasar por el navegador.

El problema

Normalmente, la solicitud (quién soy, qué quiero, adónde volver) se escribe en la dirección de la página y viaja por el navegador: el usuario o un software malicioso pueden leerla o cambiarla, y las direcciones muy largas son un problema.

Cómo funciona

La aplicación envía primero toda su solicitud al servidor, de servidor a servidor, autenticándose. El servidor responde con un simple «ticket» (request_uri) válido un minuto. La aplicación envía entonces el navegador al servidor solo con ese ticket. El ticket solo puede usarse una vez.

Como imagen

En lugar de gritar su pedido por el comedor, se lo entrega a la cocina y solo muestra a la sala un número de ticket.

Cuándo usarlo

Siempre que quiera impedir que se manipule un parámetro (importe, scopes, redirect_uri): banca, sanidad, pagos. Exigido por FAPI.

Trampas

Ticket caducado (60 s), ya utilizado o presentado por un cliente distinto del que lo envió.

En ID-Kit

Proveedor de pruebas: llame a /par. En la aplicación de pruebas, elija el flujo «code_par». El ajuste «Require PAR» del proveedor rechaza las solicitudes clásicas.

JAR: solicitud de autorización firmada

RFC 9101

Firmar la solicitud de inicio de sesión para que nadie pueda modificarla por el camino.

El problema

Aun con los parámetros en la dirección, nada prueba que procedan realmente de la aplicación y no se hayan cambiado.

Cómo funciona

Los parámetros se reúnen en un JWT firmado con la clave del cliente (parámetro «request»). El servidor verifica la firma, el emisor, la audiencia y la fecha. Los parámetros del JWT sustituyen a los de la dirección.

Como imagen

Una carta en un sobre sellado con lacre: si el sello está roto, el servidor lo ve.

Cuándo usarlo

Con PAR en perfiles de alta seguridad; solo, cuando no hay canal de servidor a servidor.

Trampas

Clave pública del cliente no registrada, «aud» que no es el emisor del servidor, JWT caducado, client_id distinto.

En ID-Kit

Registre la clave pública del cliente y envíe su JWT en «request» o a /par. Se explican las firmas y audiencias incorrectas.

JARM: respuesta de autorización firmada

FAPI JARM

El servidor también firma su respuesta: la aplicación sabe que procede realmente de él y que no se ha modificado.

El problema

Cuando el servidor devuelve al usuario a la aplicación con «code=…» en la dirección, cualquiera en el navegador puede tocarlo. Esto abre la puerta a ataques en los que otro servidor suplanta al correcto («mix-up»).

Cómo funciona

En lugar de varios parámetros simples, el servidor devuelve un único parámetro «response»: un JWT firmado que contiene code, state, el emisor (iss) y la audiencia (aud). La aplicación verifica la firma y luego lee el código que contiene. Cuatro variantes: jwt, query.jwt, fragment.jwt, form_post.jwt (según dónde se coloque el JWT).

Como imagen

La respuesta llega en un sobre sellado en lugar de en una postal.

Cuándo usarlo

Perfil FAPI 2.0 y sectores regulados. También útil para detectar ataques mix-up entre servidores.

Trampas

Olvidar verificar la firma, o leer parámetros simples junto al JWT. query.jwt está prohibido cuando los tokens vuelven por el navegador.

En ID-Kit

Añada response_mode=jwt (o una variante) a su solicitud de autorización en el proveedor de pruebas: incluso una denegación o un error van firmados.

DPoP: token vinculado a una clave

RFC 9449

Un token robado es inútil sin la clave de la aplicación que lo solicitó.

El problema

Un token «Bearer» funciona como el dinero en efectivo: quien lo tiene puede usarlo, aunque lo haya robado de un registro, una extensión del navegador o una API comprometida.

Cómo funciona

La aplicación crea un par de claves. En cada llamada adjunta una breve «prueba» firmada con su clave privada que dice «este es el método y la dirección a la que llamo, en este instante». El servidor vincula el token a la huella de la clave (cnf.jkt). La API comprueba que la prueba fue firmada por la misma clave y que lleva el hash del token (ath). Un ladrón que tenga el token pero no la clave privada queda bloqueado.

Como imagen

Una tarjeta bancaria con PIN, en lugar de billetes: la tarjeta sola no basta.

Cuándo usarlo

Aplicaciones móviles y páginas web (SPA) donde los tokens quedan expuestos, API sensibles, perfiles FAPI 2.0.

Trampas

Prueba reutilizada (jti de un solo uso), método o dirección incorrectos (htm, htu), reloj desfasado (iat ±2 min), token presentado con «Bearer» en lugar de «DPoP», ath ausente en la API.

En ID-Kit

Envíe una cabecera DPoP al /token del proveedor de pruebas: el token pasa a ser token_type DPoP con cnf.jkt. En /userinfo, se necesita «Authorization: DPoP» más una prueba con ath; si no, un mensaje explica lo que falta.

CIBA: autenticación en otro dispositivo

OpenID CIBA Core

Una aplicación pide al servidor que autentique a alguien en su teléfono, sin navegador ni redirección.

El problema

En una ventanilla, un centro de llamadas, un terminal de pago o un asistente de voz, la persona no está frente a un navegador que pueda redirigir.

Cómo funciona

La aplicación dice al servidor «autentica a Alice» (login_hint), opcionalmente con un mensaje que mostrar («¿Autoriza el pago de 25 €?») y recibe un auth_req_id. El servidor contacta con Alice en su teléfono. Mientras tanto, la aplicación consulta /token: «authorization_pending» mientras Alice no haya respondido; después los tokens si acepta, o «access_denied» si rechaza.

Como imagen

El vendedor llama a su banco para decir «mi cliente está aquí», y es su banco quien le envía una notificación para confirmar.

Cuándo usarlo

Validación de pagos u operaciones sensibles, centros de llamadas, quioscos, telefonía. El mensaje de vinculación (binding_message) aparece en ambas pantallas para comprobar que se valida la operación correcta.

Trampas

Consultar demasiado rápido (slow_down), dejar caducar la solicitud, olvidar que login_hint debe designar a un usuario conocido por el servidor.

En ID-Kit

Active el flujo CIBA en un cliente del proveedor de pruebas y llame a /bc-authorize. La respuesta contiene un enlace «idkit_approval_url»: es la página del «teléfono», donde aprueba o deniega; después obtiene los tokens con /token. ID-Kit solo admite el modo poll.

Resource indicators: a qué API está destinado el token

RFC 8707

Diga con qué API quiere hablar, para que el token solo funcione allí.

El problema

Un access token válido para «cualquier API» es peligroso: si la API de facturación se ve comprometida, puede reutilizar el token contra la API de nóminas.

Cómo funciona

La aplicación añade «resource=https://api.example.com/invoices» a su solicitud (de autorización o de token). El proveedor pone esta dirección en la audiencia (aud) del token. La API comprueba que aud es ella misma y, si no, rechaza.

Como imagen

Un billete de tren nominativo para una línea concreta, en lugar de un billete válido en todas partes.

Cuándo usarlo

En cuanto haya varias API detrás del mismo proveedor, y para los tokens sensibles.

Trampas

API que no comprueba aud; recurso con fragmento (#) o que no es una dirección absoluta (invalid_target).

En ID-Kit

Añada resource a /authorize o /token del proveedor de pruebas: cambia la audiencia del token JWT y de la introspección. El recurso se recuerda en el código y se conserva en el refresh.

RAR: autorizaciones detalladas

RFC 9396

Pida un derecho preciso («pagar 25 € a X») en lugar de un scope amplio («pagar»).

El problema

Un scope como «payments» es demasiado vago: el usuario no sabe lo que aprueba y el token permite mucho más que la operación prevista.

Cómo funciona

La aplicación envía authorization_details: una lista JSON de objetos con un «type» (por ejemplo payment_initiation) y los detalles de la operación (importe, beneficiario). El proveedor los muestra, los copia en el token y en la respuesta, y la API los lee.

Como imagen

Un cheque rellenado (importe, beneficiario) en lugar de un cheque en blanco.

Cuándo usarlo

Pagos, sanidad, delegación fina. Obligatorio en algunos perfiles bancarios.

Trampas

JSON no válido o falta «type» (invalid_authorization_details); API que ignora el contenido del token.

En ID-Kit

Envíe authorization_details a /authorize o /token: ID-Kit lo valida y lo vuelve a encontrar en el token, en la respuesta de /token y en la introspección.

acr y step-up: nivel de autenticación

OIDC Core, RFC 9470

Saber con qué fuerza se autenticó la persona y exigir más si hace falta.

El problema

Iniciar sesión con una contraseña no basta para transferir 10 000 €. La aplicación debe poder decir «quiero autenticación fuerte».

Cómo funciona

La aplicación pide acr_values (por ejemplo el nivel «mfa»). El proveedor devuelve en el ID token el valor acr obtenido y la lista amr de métodos usados (contraseña, código de un solo uso…). Una API puede rechazar un token de nivel demasiado bajo y pedir un «step-up»: la persona vuelve a autenticarse con más fuerza.

Como imagen

En el banco, puede consultar su cuenta con la tarjeta, pero para una transferencia grande le piden además un documento de identidad.

Cuándo usarlo

Operaciones sensibles, cumplimiento normativo (autenticación fuerte).

Trampas

Tratar acr_values como una exigencia cuando es una petición («voluntaria»); no comprobar el acr recibido.

En ID-Kit

Añada acr_values=urn:idkit:acr:mfa: el ID token contiene acr y amr [pwd, otp], y la introspección devuelve acr y auth_time. Sin solicitud, el nivel es «pwd».

Registro dinámico de clientes

RFC 7591

Una aplicación se registra por sí misma en el proveedor, sin pasar por un administrador.

El problema

Crear clientes a mano no escala: herramientas, extensiones, servidores MCP, aplicaciones móviles instaladas por miles de personas.

Cómo funciona

La aplicación envía un POST JSON a /register (nombre, direcciones de retorno, flujos deseados, método de autenticación). El proveedor crea el cliente y devuelve client_id y, si procede, client_secret.

Como imagen

Un quiosco de inscripción de autoservicio en lugar de una cita en recepción.

Cuándo usarlo

Ecosistemas abiertos, herramientas que se conectan a proveedores desconocidos.

Trampas

Redirecciones inseguras (http fuera de localhost), grants incoherentes con el método de autenticación, sin límite.

En ID-Kit

Active «Allow dynamic registration» en los ajustes del proveedor de pruebas y luego haga POST a /register. El límite es de 25 clientes.

Pairwise y userinfo firmado

OIDC Core 8.1 y 5.3.2

Un identificador distinto por aplicación e información de perfil firmada.

El problema

Si todas las aplicaciones ven el mismo identificador (sub) de una persona, pueden cruzar sus bases de datos y seguirla de un servicio a otro.

Cómo funciona

En modo pairwise, el proveedor calcula un sub distinto para cada dominio de aplicación: el mismo usuario aparece con dos identificadores diferentes en dos aplicaciones. Por separado, /userinfo puede responder con un JWT firmado en lugar de JSON simple, para que la aplicación pueda probar de dónde proceden los datos.

Como imagen

Un seudónimo distinto por sitio en lugar de un número de la seguridad social en todas partes.

Cuándo usarlo

Privacidad (administraciones públicas, sanidad, educación); entornos donde la información de perfil debe ir firmada.

Trampas

Vincular cuentas entre aplicaciones con sub (imposible con pairwise); olvidar que el sub de userinfo debe ser idéntico al del ID token.

En ID-Kit

Dos ajustes en el proveedor de pruebas: «Identificador por aplicación (pairwise)» y «userinfo como JWT firmado».

Vea también: diagramas de secuencia · ¿qué flujo elegir? · la línea de tiempo