Saltar al contenido principal

Añade autenticación a tu aplicación Webflow

Esta guía te mostrará cómo integrar Logto en tus sitios de Webflow.

tip

Requisitos previos

  1. Integrar Logto con Webflow requiere la función de "Código personalizado" de Webflow, que requiere al menos el plan "Básico".
  2. Un sitio de Webflow, ya sea utilizando un sitio existente o creando uno nuevo.

Integración

Inicializar el proveedor de Logto

nota

En los siguientes pasos, asumimos que tu sitio Webflow está funcionando en https://your-awesome-site.webflow.io.

En este paso, añadiremos código personalizado a nivel global a tu sitio Webflow. Dado que NPM no es compatible con Webflow, utilizaremos el servicio CDN de jsdelivr.com para importar el SDK de Logto.

Abre la página de "Configuración del sitio" y navega a la sección de "Código personalizado". Añade el siguiente código a la sección de "Código en el encabezado".

<script type="module">
// Importar el SDK \`@logto/browser\` desde el CDN de jsdelivr
import LogtoClient from 'https://esm.run/@logto/browser';

// Asignar la instancia \`logtoClient\` al objeto window,
// permitiendo su uso global en otras páginas
window.logtoClient = new LogtoClient({
endpoint: '<your-logto-endpoint>', // Ej. http://localhost:3001
appId: '<your-application-id>',
});
</script>

Implementar inicio de sesión

Antes de profundizar en los detalles, aquí tienes una visión general rápida de la experiencia del usuario final. El proceso de inicio de sesión se puede simplificar de la siguiente manera:

  1. Tu aplicación invoca el método de inicio de sesión.
  2. El usuario es redirigido a la página de inicio de sesión de Logto. Para aplicaciones nativas, se abre el navegador del sistema.
  3. El usuario inicia sesión y es redirigido de vuelta a tu aplicación (configurada como el URI de redirección).
Sobre el inicio de sesión basado en redirección
  1. Este proceso de autenticación sigue el protocolo OpenID Connect (OIDC), y Logto aplica medidas de seguridad estrictas para proteger el inicio de sesión del usuario.
  2. Si tienes múltiples aplicaciones, puedes usar el mismo proveedor de identidad (Logto). Una vez que el usuario inicia sesión en una aplicación, Logto completará automáticamente el proceso de inicio de sesión cuando el usuario acceda a otra aplicación.

Para aprender más sobre la lógica y los beneficios del inicio de sesión basado en redirección, consulta Experiencia de inicio de sesión de Logto explicada.


Configurar el URI de redirección de inicio de sesión

Vamos a cambiar a la página de detalles de la aplicación en Logto Console. Añade un URI de redirección https://your-awesome-site.webflow.io/callback y haz clic en "Guardar cambios".

URI de redirección en Logto Console

Implementar un botón de inicio de sesión

Regresa a tu diseñador de Webflow, arrastra y suelta un botón de "Iniciar sesión" en la página de inicio y asígnale un ID "sign-in" para referencia posterior usando getElementById().

<script type="module">
const signInButton = document.getElementById('sign-in');
const onClickSignIn = () => logtoClient.signIn('https://your-awesome-site.webflow.io/callback');
signInButton.addEventListener('click', onClickSignIn);
</script>

Manejar la redirección

¡Ya casi terminamos! En el último paso, usamos https://your-awesome-site.webflow.io/callback como el URI de redirección, y ahora necesitamos manejarlo adecuadamente.

Primero, vamos a crear una página de "Callback" en Webflow, y simplemente poner algún texto estático "Redirigiendo..." en ella. Luego añade el siguiente código personalizado a nivel de página en la página de "Callback".

<script type="module">
(async () => {
// Manejar la lógica de callback de inicio de sesión llamando al método del SDK
await logtoClient.handleSignInCallback(window.location.href);

// Redirigir de nuevo a la página de inicio cuando se complete el manejo
window.location.assign('https://your-awesome-site.webflow.io');
})();
</script>

Implementar cierre de sesión

Llamar a .signOut() borrará todos los datos de Logto en la memoria y en localStorage si existen.

Después de cerrar sesión, será genial redirigir a tu usuario de vuelta a tu sitio web. Vamos a añadir https://your-awesome-site.webflow.io como uno de los URIs de Post Sign-out en la Admin Console (se muestra bajo Redirect URIs), y usar la URL como parámetro al llamar a .signOut().

Implementar un botón de cierre de sesión

Regresa al diseñador de Webflow y añade un botón de "Cerrar sesión" en tu página de inicio. De manera similar, asigna un ID "sign-out" al botón y añade el siguiente código al código personalizado a nivel de página.

const signOutButton = document.getElementById('sign-out');
const onClickSignOut = () => logtoClient.signOut('https://your-awesome-site.webflow.io');
signOutButton.addEventListener('click', onClickSignOut);

Manejar el estado de autenticación

En Logto SDK, generalmente podemos usar el método logtoClient.isAuthenticated() para verificar el estado de autenticación. Si el usuario ha iniciado sesión, el valor será true; de lo contrario, será false.

En tu sitio de Webflow, también puedes usarlo para mostrar y ocultar programáticamente los botones de inicio y cierre de sesión. Aplica el siguiente código personalizado para ajustar el CSS de los botones en consecuencia.

const isAuthenticated = await logtoClient.isAuthenticated();

signInButton.style.display = isAuthenticated ? 'none' : 'block';
signOutButton.style.display = isAuthenticated ? 'block' : 'none';

Punto de control: Prueba tu sitio de Webflow

Ahora, prueba tu sitio:

  1. Despliega y visita la URL de tu sitio, el botón de inicio de sesión debería ser visible.
  2. Haz clic en el botón de inicio de sesión, el SDK iniciará el proceso de inicio de sesión, redirigiéndote a la página de inicio de sesión de Logto.
  3. Después de iniciar sesión, serás redirigido de vuelta a tu sitio, viendo el nombre de usuario y el botón de cierre de sesión.
  4. Haz clic en el botón de cierre de sesión para cerrar sesión.

Obtener información del usuario

Puedes utilizar estos métodos de Logto para recuperar información del usuario de manera programática:

  • getIdTokenClaims: Obtén información del usuario decodificando el Token de ID (ID token) local. Algunos reclamos (claims) pueden no estar disponibles.
  • fetchUserInfo: Obtén información del usuario enviando una solicitud al endpoint de userinfo.

Es importante tener en cuenta que los reclamos de información del usuario que se pueden recuperar dependen de los alcances (scopes) utilizados por el usuario durante el inicio de sesión, y considerando el rendimiento y el tamaño de los datos, el Token de ID (ID token) puede no contener todos los reclamos del usuario, algunos reclamos del usuario solo están disponibles en el endpoint de userinfo (consulta la lista relacionada a continuación).

Logto utiliza las convenciones de alcances y reclamos (scopes and claims) de OIDC para definir los alcances y reclamos para obtener información del usuario del Token de ID y del endpoint userinfo de OIDC. Tanto "alcance" como "reclamo" son términos de las especificaciones de OAuth 2.0 y OpenID Connect (OIDC).

En resumen, cuando solicitas un alcance, obtendrás los reclamos correspondientes en la información del usuario. Por ejemplo, si solicitas el alcance `email`, obtendrás los datos `email` y `email_verified` del usuario.

Por defecto, Logto SDK siempre solicitará tres alcances: `openid`, `profile` y `offline_access`, y no hay forma de eliminar estos alcances predeterminados. Pero puedes añadir más alcances al configurar Logto:

<script type="module">
// Import \`@logto/browser\` SDK desde el CDN de jsdelivr
import LogtoClient from 'https://esm.run/@logto/browser';

// Asigna la instancia \`logtoClient\` al objeto window,
// permitiendo su uso global en otras páginas
window.logtoClient = new LogtoClient({
endpoint: '<your-logto-endpoint>', // Ej. http://localhost:3001
appId: '<your-application-id>',
scopes: [
UserScope.Email,
UserScope.Phone,
UserScope.CustomData,
UserScope.Identities,
UserScope.Organizations,
],
});
</script>

Aquí está la lista de alcances (Scopes) soportados y los reclamos (Claims) correspondientes:

openid

Nombre del reclamoTipoDescripción¿Necesita userinfo?
substringEl identificador único del usuarioNo

profile

Nombre del reclamoTipoDescripción¿Necesita userinfo?
namestringEl nombre completo del usuarioNo
usernamestringEl nombre de usuario del usuarioNo
picturestringURL de la foto de perfil del usuario final. Esta URL DEBE referirse a un archivo de imagen (por ejemplo, un archivo de imagen PNG, JPEG o GIF), en lugar de a una página web que contenga una imagen. Ten en cuenta que esta URL DEBERÍA referirse específicamente a una foto de perfil del usuario final adecuada para mostrar al describir al usuario final, en lugar de una foto arbitraria tomada por el usuario final.No
created_atnumberMomento en que se creó el usuario final. El tiempo se representa como el número de milisegundos desde la época Unix (1970-01-01T00:00:00Z).No
updated_atnumberMomento en que se actualizó por última vez la información del usuario final. El tiempo se representa como el número de milisegundos desde la época Unix (1970-01-01T00:00:00Z).No

Otros reclamos estándar incluyen family_name, given_name, middle_name, nickname, preferred_username, profile, website, gender, birthdate, zoneinfo y locale también se incluirán en el alcance profile sin necesidad de solicitar el endpoint de userinfo. Una diferencia en comparación con los reclamos anteriores es que estos reclamos solo se devolverán cuando sus valores no estén vacíos, mientras que los reclamos anteriores devolverán null si los valores están vacíos.

nota

A diferencia de los reclamos estándar, los reclamos created_at y updated_at utilizan milisegundos en lugar de segundos.

email

Nombre del reclamoTipoDescripción¿Necesita userinfo?
emailstringLa dirección de correo electrónico del usuarioNo
email_verifiedbooleanSi la dirección de correo electrónico ha sido verificadaNo

phone

Nombre del reclamoTipoDescripción¿Necesita userinfo?
phone_numberstringEl número de teléfono del usuarioNo
phone_number_verifiedbooleanSi el número de teléfono ha sido verificadoNo

address

Por favor, consulta el OpenID Connect Core 1.0 para los detalles del reclamo de dirección.

custom_data

Nombre del reclamoTipoDescripción¿Necesita userinfo?
custom_dataobjectLos datos personalizados del usuario

identities

Nombre del reclamoTipoDescripción¿Necesita userinfo?
identitiesobjectLas identidades vinculadas del usuario
sso_identitiesarrayLas identidades SSO vinculadas del usuario

urn:logto:scope:organizations

Nombre del reclamoTipoDescripción¿Necesita userinfo?
organizationsstring[]Los IDs de las organizaciones a las que pertenece el usuarioNo
organization_dataobject[]Los datos de las organizaciones a las que pertenece el usuario

urn:logto:scope:organization_roles

Nombre del reclamoTipoDescripción¿Necesita userinfo?
organization_rolesstring[]Los roles de organización a los que pertenece el usuario con el formato <organization_id>:<role_name>No

Considerando el rendimiento y el tamaño de los datos, si "¿Necesita userinfo?" es "Sí", significa que el reclamo no aparecerá en el Token de ID, pero se devolverá en la respuesta del endpoint de userinfo.

Recursos de API

Recomendamos leer primero 🔐 Control de acceso basado en roles (RBAC) para entender los conceptos básicos de Logto RBAC y cómo configurar correctamente los recursos de API.

Configurar el cliente de Logto

Una vez que hayas configurado los recursos de API, puedes agregarlos al configurar Logto en tu aplicación:

<script type="module">
// Importar el SDK \`@logto/browser\` desde el CDN de jsdelivr
import LogtoClient from 'https://esm.run/@logto/browser';

// Asignar la instancia \`logtoClient\` al objeto window,
// permitiendo su uso global en otras páginas
window.logtoClient = new LogtoClient({
endpoint: '<your-logto-endpoint>', // Ejemplo: http://localhost:3001
appId: '<your-application-id>',
resources: ['https://shopping.your-app.com/api', 'https://store.your-app.com/api'], // Añadir recursos de API
});
</script>

Cada recurso de API tiene sus propios permisos (alcances).

Por ejemplo, el recurso https://shopping.your-app.com/api tiene los permisos shopping:read y shopping:write, y el recurso https://store.your-app.com/api tiene los permisos store:read y store:write.

Para solicitar estos permisos, puedes agregarlos al configurar Logto en tu aplicación:

<script type="module">
// Importar el SDK de \`@logto/browser\` desde el CDN de jsdelivr
import LogtoClient from 'https://esm.run/@logto/browser';

window.logtoClient = new LogtoClient({
endpoint: '<your-logto-endpoint>',
appId: '<your-application-id>',
scopes: ['shopping:read', 'shopping:write', 'store:read', 'store:write'],
resources: ['https://shopping.your-app.com/api', 'https://store.your-app.com/api'],
});
</script>

Puedes notar que los alcances se definen por separado de los recursos de API. Esto se debe a que Resource Indicators for OAuth 2.0 especifica que los alcances finales para la solicitud serán el producto cartesiano de todos los alcances en todos los servicios objetivo.

Así, en el caso anterior, los alcances se pueden simplificar desde la definición en Logto, ambos recursos de API pueden tener alcances read y write sin el prefijo. Luego, en la configuración de Logto:

<script type="module">
// Importar el SDK de \`@logto/browser\` desde el CDN de jsdelivr
import LogtoClient from 'https://esm.run/@logto/browser';

window.logtoClient = new LogtoClient({
endpoint: '<your-logto-endpoint>',
appId: '<your-application-id>',
scopes: ['read', 'write'],
resources: ['https://shopping.your-app.com/api', 'https://store.your-app.com/api'],
});
</script>

Para cada recurso de API, se solicitarán tanto los alcances read como write.

nota

Está bien solicitar alcances que no están definidos en los recursos de API. Por ejemplo, puedes solicitar el alcance email incluso si los recursos de API no tienen el alcance email disponible. Los alcances no disponibles serán ignorados de manera segura.

Después de un inicio de sesión exitoso, Logto emitirá los alcances apropiados a los recursos de API de acuerdo con los roles del usuario.

Obtener token de acceso para el recurso de API

Para obtener el token de acceso para un recurso de API específico, puedes usar el método getAccessToken:

const isAuthenticated = await logtoClient.isAuthenticated();

if (isAuthenticated) {
(async () => {
const token = await logtoClient.getAccessToken();
console.log(token);
})();
}

Este método devolverá un token de acceso JWT que se puede usar para acceder al recurso de API cuando el usuario tiene permisos relacionados. Si el token de acceso en caché actual ha expirado, este método intentará automáticamente usar un token de actualización para obtener un nuevo token de acceso.

Obtener tokens de organización

Si la organización es nueva para ti, por favor lee 🏢 Organizaciones (Multi-tenancy) para comenzar.

Necesitas añadir el alcance UserScope.Organizations al configurar el cliente Logto:

import LogtoClient, { UserScope } from 'https://esm.run/@logto/browser';

window.logtoClient = new LogtoClient({
// ...other configs
scopes: [UserScope.Organizations],
});

Una vez que el usuario ha iniciado sesión, puedes obtener el token de organización para el usuario:

import { UserScope } from 'https://esm.run/@logto/browser';

const isAuthenticated = await logtoClient.isAuthenticated();

(async () => {
if (!isAuthenticated) {
return;
}
const claims = await logtoClient.getIdTokenClaims();

console.log('Reclamos del token de ID:', claims);
console.log('IDs de organizaciones:', claims.organizations);

// Asumiendo que hay al menos una organización, tomemos la primera
const organizationId = claims.organizations[0];
const token = await logtoClient.getOrganizationToken(organizationId);

console.log('Token de acceso de la organización:', token);
})();

Lecturas adicionales

Flujos de usuario final: flujos de autenticación, flujos de cuenta y flujos de organización Configurar conectores Protege tu API