Adicionar autenticação ao seu aplicativo Webflow
Este guia mostrará como integrar o Logto em seus sites Webflow.
- O projeto de exemplo está disponível em Webflow project preview.
- Uma demonstração ao vivo está implantada em https://charless-trendy-site-f191c0.webflow.io/.
Pré-requisitos
- Integrar o Logto com o Webflow requer o recurso "Código personalizado" do Webflow, que exige pelo menos o plano "Básico".
- Um site Webflow, use um site existente ou crie um novo.
Integração
Inicializar o provedor Logto
Nos passos seguintes, assumimos que seu site Webflow está rodando em https://your-awesome-site.webflow.io
.
Neste passo, adicionaremos código personalizado em nível global ao seu site Webflow. Como o NPM não é suportado no Webflow, usaremos o serviço CDN jsdelivr.com para importar o Logto SDK.
Abra a página "Configurações do site" e navegue até a seção "Código personalizado". Adicione o seguinte código à seção "Código do cabeçalho".
<script type="module">
// Importar SDK \`@logto/browser\` do CDN jsdelivr
import LogtoClient from 'https://esm.run/@logto/browser';
// Atribuir a instância \`logtoClient\` ao objeto window,
// permitindo uso global em outras páginas
window.logtoClient = new LogtoClient({
endpoint: '<your-logto-endpoint>', // Ex.: http://localhost:3001
appId: '<your-application-id>',
});
</script>
Implementar login
Antes de mergulharmos nos detalhes, aqui está uma visão geral rápida da experiência do usuário final. O processo de login pode ser simplificado da seguinte forma:
- Seu aplicativo invoca o método de login.
- O usuário é redirecionado para a página de login do Logto. Para aplicativos nativos, o navegador do sistema é aberto.
- O usuário faz login e é redirecionado de volta para o seu aplicativo (configurado como o URI de redirecionamento).
Sobre o login baseado em redirecionamento
- Este processo de autenticação segue o protocolo OpenID Connect (OIDC), e o Logto aplica medidas de segurança rigorosas para proteger o login do usuário.
- Se você tiver vários aplicativos, pode usar o mesmo provedor de identidade (Logto). Uma vez que o usuário faz login em um aplicativo, o Logto completará automaticamente o processo de login quando o usuário acessar outro aplicativo.
Para saber mais sobre a lógica e os benefícios do login baseado em redirecionamento, veja Experiência de login do Logto explicada.
Configurar URI de redirecionamento de login
Vamos mudar para a página de detalhes do Aplicativo no Logto Console. Adicione um URI de redirecionamento https://your-awesome-site.webflow.io/callback
e clique em "Salvar alterações".
Implementar um botão de login
Retorne ao seu designer do Webflow, arraste e solte um botão "Sign in" na página inicial e atribua a ele um ID "sign-in" para referência 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>
Lidar com redirecionamento
Estamos quase lá! No último passo, usamos https://your-awesome-site.webflow.io/callback
como o URI de Redirecionamento, e agora precisamos tratá-lo adequadamente.
Primeiro, vamos criar uma página "Callback" no Webflow e simplesmente colocar algum texto estático "Redirecionando..." nela. Em seguida, adicione o seguinte código personalizado de nível de página à página "Callback".
<script type="module">
(async () => {
// Lidar com a lógica de retorno de chamada de login chamando o método do SDK
await logtoClient.handleSignInCallback(window.location.href);
// Redirecionar de volta para a página inicial quando o tratamento estiver concluído
window.location.assign('https://your-awesome-site.webflow.io');
})();
</script>
Implementar logout
Chamar .signOut()
limpará todos os dados do Logto na memória e no localStorage, se existirem.
Após sair, será ótimo redirecionar seu usuário de volta para o seu site. Vamos adicionar https://your-awesome-site.webflow.io
como um dos URIs de Pós Logout no Admin Console (mostrado em URIs de Redirecionamento), e usar a URL como parâmetro ao chamar .signOut()
.
Implementar um botão de logout
Retorne ao designer do Webflow e adicione um botão "Sair" na sua página inicial. Da mesma forma, atribua um ID "sign-out" ao botão e adicione o seguinte código ao código personalizado em nível de página.
const signOutButton = document.getElementById('sign-out');
const onClickSignOut = () => logtoClient.signOut('https://your-awesome-site.webflow.io');
signOutButton.addEventListener('click', onClickSignOut);
Lidar com o status de autenticação
No Logto SDK, geralmente podemos usar o método logtoClient.isAuthenticated()
para verificar o status de autenticação. Se o usuário estiver autenticado, o valor será true
; caso contrário, será false
.
No seu site Webflow, você também pode usá-lo para mostrar e ocultar programaticamente os botões de login e logout. Aplique o seguinte código personalizado para ajustar o CSS dos botões de acordo.
const isAuthenticated = await logtoClient.isAuthenticated();
signInButton.style.display = isAuthenticated ? 'none' : 'block';
signOutButton.style.display = isAuthenticated ? 'block' : 'none';
Ponto de verificação: Teste seu site Webflow
Agora, teste seu site:
- Implemente e visite o URL do seu site, o botão de login deve estar visível.
- Clique no botão de login, o SDK iniciará o processo de login, redirecionando você para a página de login do Logto.
- Após fazer login, você será redirecionado de volta para o seu site, vendo o nome de usuário e o botão de logout.
- Clique no botão de logout para sair.
Obter informações do usuário
Você pode usar esses métodos do Logto para recuperar informações do usuário programaticamente:
getIdTokenClaims
: Obtenha informações do usuário decodificando o Token de ID (ID token) local. Algumas reivindicações (Claims) podem não estar disponíveis.fetchUserInfo
: Obtenha informações do usuário enviando uma solicitação para o endpoint userinfo.
É importante notar que as reivindicações de informações do usuário que podem ser recuperadas dependem dos escopos (Scopes) usados pelo usuário durante o login, e considerando o desempenho e o tamanho dos dados, o Token de ID (ID token) pode não conter todas as reivindicações do usuário, algumas reivindicações do usuário estão disponíveis apenas no endpoint userinfo (veja a lista relacionada abaixo).
Logto usa as convenções de escopos e reivindicações do OIDC para definir os escopos e reivindicações para recuperar informações do usuário do Token de ID e do endpoint userinfo do OIDC. Tanto "escopo" quanto "reivindicação" são termos das especificações OAuth 2.0 e OpenID Connect (OIDC).
Em resumo, quando você solicita um escopo, você obterá as reivindicações correspondentes nas informações do usuário. Por exemplo, se você solicitar o escopo `email`, você obterá os dados `email` e `email_verified` do usuário.
Por padrão, o Logto SDK sempre solicitará três escopos: `openid`, `profile` e `offline_access`, e não há como remover esses escopos padrão. Mas você pode adicionar mais escopos ao configurar o Logto:
<script type="module">
// Importar SDK \`@logto/browser\` do CDN jsdelivr
import LogtoClient from 'https://esm.run/@logto/browser';
// Atribuir a instância \`logtoClient\` ao objeto window,
// permitindo uso global em outras páginas
window.logtoClient = new LogtoClient({
endpoint: '<your-logto-endpoint>', // Ex.: http://localhost:3001
appId: '<your-application-id>',
scopes: [
UserScope.Email,
UserScope.Phone,
UserScope.CustomData,
UserScope.Identities,
UserScope.Organizations,
],
});
</script>
Aqui está a lista de Escopos (Scopes) suportados e as Reivindicações (Claims) correspondentes:
openid
Nome da Reivindicação | Tipo | Descrição | Precisa de userinfo? |
---|---|---|---|
sub | string | O identificador único do usuário | Não |
profile
Nome da Reivindicação | Tipo | Descrição | Precisa de userinfo? |
---|---|---|---|
name | string | O nome completo do usuário | Não |
username | string | O nome de usuário do usuário | Não |
picture | string | URL da foto de perfil do Usuário Final. Este URL DEVE referir-se a um arquivo de imagem (por exemplo, um arquivo de imagem PNG, JPEG ou GIF), em vez de uma página da Web contendo uma imagem. Note que este URL DEVE referenciar especificamente uma foto de perfil do Usuário Final adequada para exibição ao descrever o Usuário Final, em vez de uma foto arbitrária tirada pelo Usuário Final. | Não |
created_at | number | Hora em que o Usuário Final foi criado. O tempo é representado como o número de milissegundos desde a época Unix (1970-01-01T00:00:00Z). | Não |
updated_at | number | Hora em que as informações do Usuário Final foram atualizadas pela última vez. O tempo é representado como o número de milissegundos desde a época Unix (1970-01-01T00:00:00Z). | Não |
Outras reivindicações padrão incluem family_name
, given_name
, middle_name
, nickname
, preferred_username
, profile
, website
, gender
, birthdate
, zoneinfo
e locale
também serão incluídas no escopo profile
sem a necessidade de solicitar o endpoint userinfo. Uma diferença em relação às reivindicações acima é que essas reivindicações só serão retornadas quando seus valores não estiverem vazios, enquanto as reivindicações acima retornarão null
se os valores estiverem vazios.
Ao contrário das reivindicações padrão, as reivindicações created_at
e updated_at
estão usando milissegundos em vez de segundos.
email
Nome da Reivindicação | Tipo | Descrição | Precisa de userinfo? |
---|---|---|---|
string | O endereço de email do usuário | Não | |
email_verified | boolean | Se o endereço de email foi verificado | Não |
phone
Nome da Reivindicação | Tipo | Descrição | Precisa de userinfo? |
---|---|---|---|
phone_number | string | O número de telefone do usuário | Não |
phone_number_verified | boolean | Se o número de telefone foi verificado | Não |
address
Por favor, consulte o OpenID Connect Core 1.0 para os detalhes da reivindicação de endereço.
custom_data
Nome da Reivindicação | Tipo | Descrição | Precisa de userinfo? |
---|---|---|---|
custom_data | object | Os dados personalizados do usuário | Sim |
identities
Nome da Reivindicação | Tipo | Descrição | Precisa de userinfo? |
---|---|---|---|
identities | object | As identidades vinculadas do usuário | Sim |
sso_identities | array | As identidades SSO vinculadas do usuário | Sim |
urn:logto:scope:organizations
Nome da Reivindicação | Tipo | Descrição | Precisa de userinfo? |
---|---|---|---|
organizations | string[] | Os IDs das organizações às quais o usuário pertence | Não |
organization_data | object[] | Os dados das organizações às quais o usuário pertence | Sim |
urn:logto:scope:organization_roles
Nome da Reivindicação | Tipo | Descrição | Precisa de userinfo? |
---|---|---|---|
organization_roles | string[] | Os papéis da organização aos quais o usuário pertence com o formato <organization_id>:<role_name> | Não |
Considerando o desempenho e o tamanho dos dados, se "Precisa de userinfo?" for "Sim", isso significa que a reivindicação não aparecerá no Token de ID, mas será retornada na resposta do endpoint userinfo.
Recursos de API
Recomendamos ler 🔐 Controle de Acesso Baseado em Papel (RBAC) primeiro para entender os conceitos básicos do RBAC do Logto e como configurar corretamente os recursos de API.
Configurar cliente Logto
Depois de configurar os recursos de API, você pode adicioná-los ao configurar o Logto em seu aplicativo:
<script type="module">
// Importar SDK \`@logto/browser\` do CDN jsdelivr
import LogtoClient from 'https://esm.run/@logto/browser';
// Atribuir a instância \`logtoClient\` ao objeto window,
// permitindo uso global em outras páginas
window.logtoClient = new LogtoClient({
endpoint: '<your-logto-endpoint>', // Ex.: http://localhost:3001
appId: '<your-application-id>',
resources: ['https://shopping.your-app.com/api', 'https://store.your-app.com/api'], // Adicionar recursos de API
});
</script>
Cada recurso de API tem suas próprias permissões (escopos).
Por exemplo, o recurso https://shopping.your-app.com/api
tem as permissões shopping:read
e shopping:write
, e o recurso https://store.your-app.com/api
tem as permissões store:read
e store:write
.
Para solicitar essas permissões, você pode adicioná-las ao configurar o Logto em seu aplicativo:
<script type="module">
// Importar SDK \`@logto/browser\` do jsdelivr CDN
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>
Você pode notar que os escopos são definidos separadamente dos recursos de API. Isso ocorre porque Resource Indicators for OAuth 2.0 especifica que os escopos finais para a solicitação serão o produto cartesiano de todos os escopos em todos os serviços de destino.
Assim, no caso acima, os escopos podem ser simplificados a partir da definição no Logto, ambos os recursos de API podem ter escopos read
e write
sem o prefixo. Então, na configuração do Logto:
<script type="module">
// Importar SDK \`@logto/browser\` do jsdelivr CDN
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, ele solicitará os escopos read
e write
.
Não há problema em solicitar escopos que não estão definidos nos recursos de API. Por exemplo, você pode solicitar o escopo email
mesmo que os recursos de API não tenham o escopo email
disponível. Escopos indisponíveis serão ignorados com segurança.
Após o login bem-sucedido, o Logto emitirá os escopos apropriados para os recursos de API de acordo com os papéis do usuário.
Buscar token de acesso para o recurso de API
Para buscar o token de acesso para um recurso de API específico, você pode usar o método getAccessToken
:
const isAuthenticated = await logtoClient.isAuthenticated();
if (isAuthenticated) {
(async () => {
const token = await logtoClient.getAccessToken();
console.log(token);
})();
}
Este método retornará um token de acesso JWT que pode ser usado para acessar o recurso de API quando o usuário tiver as permissões relacionadas. Se o token de acesso em cache atual tiver expirado, este método tentará automaticamente usar um token de atualização para obter um novo token de acesso.
Buscar tokens de organização
Se organização é um conceito novo para você, por favor, leia 🏢 Organizações (Multi-tenancy) para começar.
Você precisa adicionar o escopo UserScope.Organizations
ao configurar o cliente Logto:
import LogtoClient, { UserScope } from 'https://esm.run/@logto/browser';
window.logtoClient = new LogtoClient({
// ...other configs
scopes: [UserScope.Organizations],
});
Uma vez que o usuário esteja autenticado, você pode buscar o token de organização para o usuário:
import { UserScope } from 'https://esm.run/@logto/browser';
const isAuthenticated = await logtoClient.isAuthenticated();
(async () => {
if (!isAuthenticated) {
return;
}
const claims = await logtoClient.getIdTokenClaims();
console.log('Reivindicações do token de ID:', claims);
console.log('IDs das organizações:', claims.organizations);
// Supondo que haja pelo menos uma organização, vamos pegar a primeira
const organizationId = claims.organizations[0];
const token = await logtoClient.getOrganizationToken(organizationId);
console.log('Token de acesso da organização:', token);
})();