• oidc
  • oauth
  • autenticación
  • autorización
  • jwt

La guía completa para integrar un servidor OIDC en tu proyecto

Aprende las mejores prácticas para integrar un servidor OIDC (OpenID Connect) en tu proyecto y comprende cómo interactúan los componentes entre sí en el escenario.

Gao
Gao
Founder

Puedes encontrarte en una situación donde necesitas un sistema de autenticación y autorización centralizado, también conocido como gestión de acceso de identidad (IAM) o proveedor de identidad (IdP). A veces, la gente añadirá una palabra para designar el negocio, como IAM para clientes o IAM para el personal.

Dejemos de lado estos nombres elegantes por un momento. La necesidad de IAM podría surgir porque tu aplicación está creciendo, o planeas delegar el trabajo arduo a un proveedor desde el principio. No obstante, estás llegando a un punto donde necesitarás introducir un sistema de identidad en tu proyecto.

Considerando la popularidad de OAuth 2.0, OpenID Connect (OIDC) es una opción natural para muchos desarrolladores. Dado que OIDC es una capa de autenticación construida sobre OAuth 2.0, es posible que te sientas familiarizado cuando empieces a trabajar con OIDC. ¡Empecemos!

¿Qué es un servidor OIDC y por qué debería integrar un servidor OIDC?

Un servidor OIDC, o proveedor de identidad, es un sistema centralizado que gestiona la autenticación y la autorización de usuarios. Como discutimos en Por qué necesitas un sistema de identidad centralizado para un negocio de múltiples aplicaciones, un sistema de identidad centralizado tiene muchos beneficios.

Digamos que tu proyecto comienza con una aplicación web simple, y tiene autenticación incorporada:

A medida que tu proyecto crece, necesitas introducir una versión móvil:

Será una mala experiencia para los usuarios si necesitan crear una cuenta para cada aplicación. Desde que comenzaste con una aplicación web, permites que la aplicación móvil se comunique con la aplicación web para la autenticación:

Ahora, se está introduciendo un nuevo servicio API. Dado que es un servicio para usuarios de pago, necesitas asegurarte de que el usuario esté autenticado y autorizado para acceder al servicio. Para lograr esto, puedes enviar el servicio a través de la aplicación web:

O, usa alguna técnica de token para autenticar al usuario y valida el token hablando con la aplicación web en el servicio. Por lo tanto, la aplicación móvil puede usar el servicio directamente:

Las cosas se están complicando. Así que decides dividir la lógica de autenticación y autorización en un servicio separado:

El proceso de refactorización puede ser doloroso. Puedes notar que la complejidad aumentará exponencialmente a medida que agregues más aplicaciones y servicios al proyecto. Aún peor, es posible que necesites mantener múltiples métodos de autenticación como inicio de sesión sin contraseña, inicio de sesión social, SAML, etc.

Por eso es mejor introducir un proveedor de identidad desde el principio cuando tienes un plan para escalar tu proyecto.

Mejores prácticas para integrar un servidor OIDC

Encuentra un proveedor OIDC

Hay muchos proveedores OIDC disponibles en el mercado. Puedes elegir uno basado en tus requisitos y preferencias. Mientras el proveedor cumpla con OIDC, desempeñará el mismo rol en tu proyecto.

¿Qué significan “sujeto”, “cliente” y “audiencia” en OIDC?

Para simplificar el concepto, podemos pensar que el sujeto es la entidad que está solicitando acceso a una audiencia a través de un cliente.

Veamos algunos escenarios típicos:

1. Un usuario hace clic en el botón de inicio de sesión en una aplicación web

En una aplicación web tradicional y de renderizado del lado del servidor, el frontend y el backend están acoplados. Digamos que la aplicación web sirve tanto frontend como backend:

  • Sujeto: El usuario
  • Audiencia: El servidor OIDC
  • Cliente: La aplicación web

Puede parecer contradictorio que la audiencia sea el servidor OIDC. De hecho, es la clave para realizar la experiencia SSO (Inicio de Sesión Único) para los usuarios finales. Veamos un diagrama de secuencia simplificado para el flujo de código de autorización:

code es un código de un solo uso que se puede intercambiar por varios tokens, como el token de acceso, el token de ID y el token de actualización. Está bien si no comprendes todos estos tokens en este momento. A medida que avancemos, obtendrás una mejor comprensión de ellos.

En el caso anterior, el usuario no necesita iniciar sesión nuevamente cuando cambia a otra aplicación porque el usuario (sujeto) ya ha sido autenticado con el servidor OIDC (audiencia).

2. Un usuario usa una aplicación de una sola página

En una aplicación de una sola página (o una aplicación móvil), el frontend y el backend están separados. Digamos que el backend es un servicio API:

  • Sujeto: El usuario
  • Audiencia: El servicio API
  • Cliente: La aplicación de una sola página (SPA)

Un diagrama de secuencia simplificado con el flujo de código de autorización:

Dado que el servicio API es no interactivo, la SPA necesita usar el token de acceso con el servicio API como audiencia (el aud en el token).

¿Por qué el servidor OIDC sigue siendo una audiencia?

Técnicamente, puedes eliminar el servidor OIDC de la lista de audiencias. Dado que en la mayoría de los casos, necesitarás la información del usuario del servidor OIDC (lo que requiere que el servidor OIDC sea la audiencia), es mejor incluir siempre el servidor OIDC en la lista de audiencias cuando involucra la interacción del usuario.

Espera, ¿estás diciendo que podemos tener múltiples audiencias en una solicitud de autorización?

¡Exactamente! Recuerda que OIDC está construido sobre OAuth 2.0, es posible aprovechar RFC 8707: Indicadores de recursos para OAuth 2.0 en la solicitud de autorización para especificar múltiples audiencias. Requiere el soporte tanto de la concesión como del servidor OIDC. Logto admite esta característica de forma nativa.

3. Una comunicación de máquina a máquina

Digamos que tienes un servicio A que necesita llamar al servicio B:

  • Sujeto: Servicio A
  • Audiencia: Servicio B
  • Cliente: Servicio A

Un diagrama de secuencia simplificado con concesión de credenciales de cliente:

Cuando el servicio B necesita llamar al servicio A, los roles simplemente se intercambian.

Resumen

  • Sujeto: Puede ser un usuario, un servicio o cualquier entidad que necesite acceder a la audiencia.
  • Cliente: Puede ser una aplicación web, una aplicación móvil o cualquier entidad que inicie la solicitud o actúe en nombre del sujeto.
  • Audiencia: Puede ser un servicio, una API o cualquier entidad que proporcione acceso al sujeto.

¿Qué son los tokens de acceso, los tokens de ID y los tokens de actualización?

Hay tres tipos de tokens que puedes encontrar cuando trabajas con OIDC:

  • Token de acceso: Se usa para acceder a la audiencia. Puede ser un JWT (Token Web JSON) o un token opaco (generalmente una cadena aleatoria).
  • Token de ID: Un token específico de OIDC que contiene información del usuario. Siempre es un JWT. El cliente puede decodificar el token para obtener información del usuario.
  • Token de actualización: Se utiliza para obtener un nuevo conjunto de tokens cuando el token de acceso o el token de ID expiran.

Para una explicación detallada de estos tokens, puedes consultar Comprender los tokens de actualización, tokens de acceso y tokens de ID en el protocolo OIDC.

En el escenario 1 y 2 anteriores, el término solicitud de autorización se refiere a una solicitud para obtener un conjunto de tokens a través de una concesión específica.

Cuando todo va bien, un conjunto de tokens se devolverá en el paso de "Intercambiar tokens usando code". Los tokens disponibles en el conjunto dependen de múltiples factores, especialmente del parámetro scope en la solicitud de autorización. Para mayor simplicidad, asumiremos que todos los tokens se devuelven en el conjunto. Una vez que el token de acceso expira, el cliente puede usar el token de actualización para obtener un nuevo conjunto de tokens sin interacción del usuario.

Para el escenario 3, es más simple porque la concesión de credenciales del cliente solo devuelve un token de acceso.

¿Cómo manejar múltiples audiencias en OIDC?

Puedes notar que solo se devuelve un token de acceso a la vez. ¿Cómo podríamos manejar el caso donde el cliente necesita acceder a múltiples audiencias?

Hay dos soluciones comunes:

Especificar resource en la solicitud de intercambio de código

Cuando el cliente intercambia el código por tokens, puede especificar un parámetro resource en la solicitud. El servidor OIDC devolverá un token de acceso para la audiencia especificada, si es aplicable.

Aquí tienes un ejemplo no normativo:

Luego el servidor OIDC devolverá un token de acceso para la audiencia API_SERVICE, si es aplicable.

Usar un token de actualización para obtener un nuevo token de acceso

Con RFC 8707, el cliente incluso puede especificar múltiples audiencias usando el parámetro resource varias veces. Ahora, si los tokens de actualización están disponibles en el cliente, el cliente puede especificar la audiencia en el parámetro resource al actualizar el token.

Aquí tienes un ejemplo no normativo:

Tiene el mismo efecto que la solución anterior. Mientras tanto, otras audiencias concedidas aún están disponibles en futuras solicitudes de token.

Concesión de credenciales del cliente

También puedes usar el parámetro resource en la concesión de credenciales del cliente para especificar la audiencia. No hay problema con múltiples audiencias en esta concesión porque siempre puedes solicitar un nuevo token de acceso para una audiencia diferente simplemente enviando otra solicitud de token.

Protege tu servicio API

El "servicio API" en el escenario 2 y el "Servicio B" en el escenario 3 tienen una cosa en común: necesitan validar el token de acceso para determinar si la solicitud está autorizada. Dependiendo del formato del token de acceso, el proceso de validación puede variar.

  • Token opaco: El servicio API necesita llamar al servidor OIDC para validar el token. Un punto de introspección suele ser proporcionado por el servidor OIDC para este propósito.
  • JWT: El servicio API puede validar el token localmente verificando la firma y las afirmaciones en el token. El servidor OIDC usualmente proporciona un conjunto de claves web JSON (JWKS) (jwks_uri) para que el servicio API obtenga la clave pública para verificar la firma.

Si eres nuevo en JWT, puedes consultar ¿Qué es un JSON Web Token (JWT)?. De hecho, generalmente no es necesario validar la firma y verificar las afirmaciones manualmente porque hay muchas bibliotecas que pueden hacerlo por ti, como jose para Node.js y navegadores web.

Verificar afirmaciones

Además de validar la firma del JWT, el servicio API siempre debe verificar las afirmaciones en el token:

  • iss: El emisor del token. Debe coincidir con la URL del emisor del servidor OIDC.
  • aud: La audiencia del token. Debe coincidir con el valor de la audiencia del servicio API (generalmente un URI válido).
  • exp: El tiempo de expiración del token. El servicio API debe rechazar el token si ha expirado.
  • scope: Los alcances (permisos) del token. El servicio API debe comprobar si el alcance requerido está presente en el token.

Otras afirmaciones, como sub (sujeto) e iat (emitido en), también son importantes en algunos casos. Si tienes medidas de seguridad adicionales, comprueba las afirmaciones en consecuencia.

Autorización

Una pregunta sin respuesta aún queda en el aire: ¿Cómo determinamos si un alcance (es decir, permiso) puede ser concedido a un sujeto?

La única pregunta lleva a todo un nuevo mundo de la autorización, lo cual está fuera del ámbito de este artículo. En resumen, hay algunos enfoques comunes como RBAC (Control de Acceso Basado en Roles) y ABAC (Control de Acceso Basado en Atributos). Aquí tienes algunos recursos para empezar:

Notas finales

Introducir un servidor OIDC en tu proyecto es un gran paso. Puede mejorar significativamente la seguridad y escalabilidad de tu proyecto. Mientras tanto, puede llevar algo de tiempo entender los conceptos y las interacciones entre los componentes.

Elegir un buen proveedor OIDC que se ajuste a tus requisitos y preferencias puede reducir notablemente la complejidad del proceso de integración, ya que el proveedor generalmente ofrece todo el paquete, incluyendo el servidor OIDC, mecanismos de autorización, SDKs, y las características empresariales que puedas necesitar en el futuro.

Espero que esta guía te ayude a entender los conceptos básicos de la integración de un servidor OIDC. Si estás buscando uno para empezar, recomendaría egoístamente Logto, nuestra infraestructura de identidad para desarrolladores.