Implementar un SDK OIDC sencillo del lado del cliente
Logto ofrece una variedad de SDKs para diferentes plataformas. Aparte de nuestros SDKs oficiales, alentamos a los desarrolladores de la comunidad a crear sus propios SDKs amigables para el usuario. Este artículo te guiará en la construcción de un SDK básico del lado del cliente para OIDC.
Introducción
Logto proporciona a nuestros desarrolladores y grupos empresariales una solución integral de Identidad de Cliente y Gestión de Acceso (CIAM). Ofrecemos una amplia gama de SDKs listos para usar para diferentes plataformas y marcos de aplicación. Combinado con nuestro servicio en la nube de Logto, puedes establecer sin esfuerzo un flujo de autorización de usuario altamente seguro para tu aplicación en cuestión de minutos. Como una empresa que nació de la comunidad de desarrolladores, Logto acoge y valora nuestro compromiso con la comunidad. Además de los SDKs de Logto oficialmente desarrollados, continuamente alentamos y damos una cálida bienvenida a los desarrolladores de la comunidad a contribuir con su experiencia creando SDKs más diversos y fáciles de usar, satisfaciendo las necesidades únicas de diversas plataformas y marcos. En este artículo, demostraremos brevemente cómo implementar un SDK de autenticación estándar OIDC paso a paso.
Contexto
El flujo de Conexión Abierta (OIDC) es un protocolo de autenticación que se basa en el marco de trabajo OAuth 2.0 para proporcionar verificación de identidad y capacidades de inicio de sesión único. Permite a los usuarios autenticarse con una aplicación y obtener autorización para acceder de forma segura a cualquier recurso privado. Por favor, consulta las especificaciones de OIDC para más detalles.
Flujo de trabajo
Un flujo de código de autorización estándar incluye los siguientes pasos:
Flujo de autenticación
- El usuario inicia la petición de inicio de sesión: Un usuario anónimo llega a su aplicación a través de una entrada pública. Intenta autenticarse y tal vez solicitar el acceso a un recurso protegido en una aplicación o servicio de terceros.
- Autenticación del usuario: La aplicación cliente genera una URI de autenticación y envía una petición al servidor de autorización, que redirige al usuario a su página de inicio de sesión. El usuario interactúa con la página de inicio de sesión utilizando una amplia gama de métodos de inicio de sesión y se autentica en el servidor de autorización.
- Manejar el retorno de inicio de sesión: Tras una autenticación exitosa, el usuario será redirigido de vuelta a tu aplicación con un
authorization_code
concedido. Esteauthorization_code
contiene todos los permisos relevantes vinculados al estado de la autenticación y los datos de autorización solicitados. - Intercambio de tokens: Solicitar el intercambio de tokens usando el
authorization_code
extraído de la dirección de redirección anterior. A cambio:
id_token
: Un JWT firmado digitalmente que contiene información de identidad sobre el usuario autenticado.access_token
: Unaccess_token
opaco que puede ser utilizado para acceder al punto final de información básica del usuario.refresh_token
: Token de credenciales que permite al usuario mantener un intercambio continuo para unaccess_token
Flujo de autorización
- Acceder a la información del usuario: Para acceder a más información del usuario, la aplicación puede hacer solicitudes adicionales al punto final de UserInfo, utilizando el
access_token
opaco obtenido del flujo inicial de intercambio de tokens. Esto permite la recuperación de detalles adicionales sobre el usuario, como su dirección de correo electrónico o foto de perfil. - Conceder acceso al recurso protegido: Si es necesario, la aplicación puede hacer solicitudes adicionales al punto final de intercambio de tokens, utilizando el
refresh_token
combinado con los parámetrosresource
yscope
, para obtener unaccess_token
dedicado para que el usuario acceda al recurso objetivo. Este proceso resulta en la emisión de unaccess_token
en formato JWT que contiene toda la información de autorización necesaria para acceder al recurso protegido.
Implementación
Seguiremos algunas estrategias de diseño dentro de nuestro SDK JavaScript @logto/client para demostrar el proceso de implementación de un SDK sencillo para tu propia aplicación cliente. Por favor, ten en cuenta que la estructura de código detallada puede variar dependiendo del marco de trabajo cliente con el que estás trabajando. Siéntete libre de elegir cualquiera de los SDKs oficiales de Logto como ejemplo para tu propio proyecto de SDK.
Vista previa
Constructor
El constructor debe tomar un logtoConfig como su entrada. Esto proporciona todas las configuraciones necesarias que necesitarás para establecer una conexión de autenticación a través de este SDK.
Dependiendo de la plataforma o marco de trabajo que estés utilizando para el SDK, puedes pasar una instancia de almacenamiento local persistente al constructor. Esta instancia de almacenamiento se utilizará para almacenar todos los tokens y secretos relacionados con la autorización.
Iniciar la autenticación del usuario
Antes de generar una URL de petición de autenticación, es esencial completar varios pasos de preparación para asegurar un proceso seguro.
Obtener las configuraciones OIDC del servidor de autorización
Define un método privado getOidcConfigs
para obtener las configuraciones OIDC del punto final de descubrimiento del servidor de autorización. La respuesta de las configuraciones OIDC contiene toda la información de metadatos que el cliente puede usar para interactuar con el servidor de autorización, incluyendo sus ubicaciones de punto final y las capacidades del servidor. (Por favor, consulta las especificaciones de metadatos del servidor de autorización OAuth OAuth para más detalles.)
Generador PKCE
Un flujo de validación PKCE(Proof Key for Code Exchange) es esencial para todos los flujos de intercambio de código de autorización del cliente público. Mitiga el riesgo del ataque de intercepción del código de autorización. Por lo tanto, un code_challenge
y un code_verifier
es requerido para todas las peticiones de autorización de las aplicaciones cliente públicas (por ejemplo, aplicación nativa y SPA).
Los métodos de implementación pueden variar dependiendo de los lenguajes y marcos de trabajo que estés utilizando. Por favor, consulta la especificación de code_challenge y code_verifier para las definiciones detalladas.
Generar parámetro de estado
En el flujo de autorización, el parámetro de estado es un valor generado aleatoriamente que se incluye en la petición de autorización enviada por el cliente. Actúa como una medida de seguridad para prevenir ataques de falsificación de peticiones en sitios cruzados (CSRF).
Almacenar información de sesión intermedia
Hay varios parámetros que necesitan ser preservados en el almacenamiento para la validación después de que el usuario se autentique y sea redirigido de vuelta al lado del cliente. Vamos a implementar un método para establecer esos parámetros intermedios en el almacenamiento.
Iniciar sesión
Vamos a juntar todo lo que implementamos anteriormente, definamos un método que genere una URL de inicio de sesión para el usuario y redirija al usuario al servidor de autorización para autenticarse.
Manejar el retorno de inicio de sesión del usuario
En la sección anterior, creamos un método de inicio de sesión que genera una URL para la autenticación del usuario. Esta URL contiene todos los parámetros requeridos necesarios para iniciar un flujo de autenticación desde una aplicación cliente. El método redirige al usuario a la página de inicio de sesión del servidor de autorización para autenticarse. Después de un inicio de sesión exitoso, el usuario final será redirigido de vuelta a la ubicación de redirect_uri proporcionada anteriormente. Todos los parámetros necesarios serán llevados en la redirect_uri para completar los siguientes flujos de intercambio de tokens.
Extraer y verificar la URL de devolución de llamada
Este paso de validación es extremadamente importante para prevenir cualquier forma de ataques de devolución de llamada de autorización falsificados. La URL de devolución de llamada DEBE ser cuidadosamente verificada antes de enviar una petición de intercambio de código adicional al servidor de autorización. Primero que todo, necesitamos recuperar los datos de signInSession que almacenamos del almacenamiento de la aplicación.
Luego verifica el parámetro de la URL de devolución de llamada antes de enviar la petición de intercambio de código al servidor de autorización.
- Usa el
redirectUri
previamente almacenado para verificar si elcallbackUri
es el mismo que el que enviamos al servidor de autorización. - Usa el
state
previamente almacenado para verificar si el estado devuelto es el mismo que el que enviamos al servidor de autorización. - Comprueba si el servidor de autorización devuelve algún error
- Comprueba la existencia del
authorization_code
devuelto
Enviar la petición de intercambio de código
Como último paso del flujo de autenticación del usuario, utilizaremos el authorization_code
devuelto para enviar una petición de intercambio de tokens y obtener los tokens de autorización requeridos. Para obtener más detalles sobre las definiciones de los parámetros de la solicitud, por favor consulta la especificación de intercambio de tokens.
- code: el
authorization_code
que recibimos de la URI de devolución de llamada - clientId: la ID de la aplicación
- redirectUri: El mismo valor se utiliza al generar la URL de inicio de sesión para el usuario.
- codeVerifier: verificador de código PKCE. Igual que el redirectUri, el servidor de autorización comparará este valor con el que enviamos previamente, asegurando la validación de la petición de intercambio de tokens que entra.
Manejar la devolución de llamada de inicio de sesión
Recopilando todo lo que tenemos. Construyamos el método de manejo de devolución de llamada de inicio de sesión:
Como resultado, la petición de intercambio de tokens devolverá los siguientes tokens:
id_token
: ID de OIDC idToken, un JSON Web Token (JWT) que contiene información de identidad sobre el usuario autenticado. El id_token también puede ser utilizado como la Única Fuente de Verdad (SSOT) del estado de autenticación de un usuario.access_token
: El código de autorización predeterminado devuelto por el servidor de autorización. Puede ser utilizado para llamar al punto final de información del usuario y recuperar información autenticada del usuario.refresh_token
: (si el scope offline_access está presente en la petición de autorización): Este token de actualización permite a la aplicación cliente obtener un nuevo token de acceso sin requerir que el usuario vuelva a autenticarse, concediendo un acceso a largo plazo a los recursos.expires_in
: La duración del tiempo, en segundos, para la que el token de acceso es válido antes de que expire.
Verificación del token ID
Verificar y extraer reclamos del id_token
es un paso crucial en el proceso de autenticación para asegurar la autenticidad e integridad del token. Aquí están los pasos clave involucrados en la verificación de un idToken
.
- Verificación de la firma: El
id_token
está firmado digitalmente por el servidor de autorización utilizando su clave privada. La aplicación cliente necesita validar la firma utilizando la clave pública del servidor de autorización. Esto asegura que el token no ha sido manipulado y fue emitido por el servidor de autorización legítimo. - Verificación del emisor: Comprobar que la reclamación "iss" (emisor) en el
id_token
coincide con el valor esperado, indicando que el token fue emitido por el servidor de autorización correcto. - Verificación de la audiencia: Asegurarse de que la reclamación "aud" (audiencia) en el
id_token
coincide con la ID del cliente de la aplicación cliente, asegurando que el token está destinado al cliente. - Comprobar la expiración: Verificar que la reclamación "iat" (emitida en) en el
id_token
no haya pasado la hora actual, asegurando que el token aún es válido. Dado que hay costos de transacción de red necesitamos establecer una tolerancia de tiempo emitida al validar la reclamación iat del token recibido.
El id_token devuelto es un token web JSON (JWT) estándar. Dependiendo del marco de trabajo que estés utilizando, puedes encontrar varios plugins de validación de tokens JWT convenientes para ayudar en la decodificación y validación del token. Para este ejemplo, utilizaremos jose en nuestro SDK de JavaScript para facilitar la validación y decodificación del token.
Obtener la información del usuario
Después de una autenticación de usuario exitosa, la información básica del usuario puede ser recuperada del id_token
OIDC emitido por el servidor de autorización. Sin embargo, debido a consideraciones de rendimiento, el contenido del token JWT es limitado. Para obtener más información detallada del perfil del usuario, los servidores de autorización compatibles con OIDC ofrecen un punto final de información de usuario fuera de la caja. Este punto final te permite recuperar datos adicionales del perfil del usuario solicitando scopes específicos del perfil del usuario.
Al llamar a un punto final de intercambio de tokens sin indicar un recurso API específico, el servidor de autorización emitirá por defecto un access_token
de tipo opaco. Este access_token
sólo puede ser utilizado para acceder al punto final de información del usuario, permitiendo la recuperación de datos básicos del perfil del usuario.
Obtener token de acceso para autorización de recurso protegido
En la mayoría de los casos, una aplicación cliente no sólo requiere autenticación de usuario, sino también necesita autorización de usuario para acceder a ciertos recursos protegidos o puntos finales de la API. Aquí, utilizaremos el refresh_token
obtenido durante el inicio de sesión para adquirir access_token(s)
específicamente concedidos para administrar recursos particulares. Esto nos permite obtener acceso a esas APIs protegidas.
Resumen
Hemos proporcionado las implementaciones de métodos esenciales para el proceso de autenticación y autorización del usuario de la aplicación del lado cliente. Dependiendo de tu escenario específico, puedes organizar y optimizar la lógica del SDK en consecuencia. Ten en cuenta que pueden existir variaciones debido a diferentes plataformas y marcos de trabajo.
Para obtener detalles adicionales, explora los paquetes de SDK ofrecidos por Logto. Alentamos a más usuarios a unirse al desarrollo y participar en discusiones con nosotros. Sus comentarios y contribuciones son altamente valorados ya que continuamos mejorando y ampliando las capacidades del SDK.
Apéndice
Scopes reservados
Scopes de Logto reservados que necesitarás pasar durante la petición de autenticación inicial. Esos scopes son ya sea OIDC-reservados o Logto-reservados scopes fundamentales para completar un flujo de autorización exitoso.
Nombre del Scope | Descripción |
---|---|
openid | Requerido para conceder id_token después de una autenticación exitosa. |
offline-access | Requerido para conceder un refresh_token que permite a tu aplicación cliente intercambiar y renovar un access_token fuera de la pantalla. |
profile | Requerido para obtener acceso a la información básica del usuario. |
Configuración de Logto
Nombre de la Propiedad | Tipo | Obligatorio | Descripción | Valor Predeterminado |
---|---|---|---|---|
appId | string | true | El identificador de aplicación único. Generado por el servidor de autorización para identificar la aplicación cliente. | |
appSecret | string | El secreto de la aplicación se utiliza, junto con el ID de la aplicación, para verificar la identidad del solicitante. Se requiere para clientes confidenciales como aplicaciones web de Go o Next.js, y es opcional para clientes públicos como aplicaciones nativas o de página única (SPAs) | ||
endpoint | string | true | El punto final raíz de tu servidor de autorización. Esta propiedad será utilizada ampliamente para generar peticiones de autorización. | |
scopes | lista de strings | Indica todos los scopes de recurso necesarios que el usuario puede necesitar ser concedido para acceder a cualquier recurso protegido dado. | [reservedScopes] | |
resources | lista de strings | Todos los indicadores de recurso protegido que el usuario puede solicitar para acceder. |