Adicionar autenticação ao seu aplicativo Next Auth
Este guia mostrará como integrar o Logto em seu aplicativo Next.js com Next Auth.
- Neste guia, assumimos que você configurou o Next Auth em seu projeto Next.js. Se você ainda não fez isso, confira a documentação do Next Auth para começar.
Pré-requisitos
- Uma conta Logto Cloud ou um Logto auto-hospedado.
- Um aplicativo tradicional Logto criado.
- Um projeto Next.js com Next Auth, confira a documentação do Next Auth.
Integração
Configurar o provedor Next Auth
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.
Nos trechos de código a seguir, assumimos que seu aplicativo está sendo executado em http://localhost:3000/
.
Configurar URI de redirecionamento de login
Vamos mudar para a página de detalhes do Aplicativo no Logto Console. Adicione um URI de redirecionamento http://localhost:3000/api/auth/callback/logto
e clique em "Salvar alterações".
Configurar provedor Next Auth
Você pode encontrar e copiar o "App Secret" na página de detalhes do aplicativo no Admin Console:
Modifique a configuração da rota da API do Next Auth. Se você estiver usando o Pages Router, o arquivo está em pages/api/auth/[...nextauth].js
, se estiver usando o App Router, o arquivo está em app/api/auth/[...nextauth]/route.ts
.
A seguir está um exemplo de App Router:
- Next Auth v5
- Next Auth v4
import NextAuth from 'next-auth';
export const {
handlers: { GET, POST },
signIn,
signOut,
auth,
} = NextAuth({
providers: [
{
id: 'logto',
name: 'Logto',
type: 'oidc',
// Você pode obter o valor do emissor na página de Detalhes do Aplicativo Logto,
// no campo "Endpoint do emissor"
issuer: 'https://xxxx.logto.app/oidc',
clientId: '<logto-app-id>',
clientSecret: '<logto-app-secret>',
authorization: {
params: { scope: 'openid offline_access profile email' },
},
profile(profile) {
// Você pode personalizar o mapeamento do perfil do usuário aqui
return {
id: profile.sub,
name: profile.name ?? profile.username,
email: profile.email,
image: profile.picture,
};
},
},
],
});
- Substitua a URL do
issuer
pelo "Endpoint do emissor" do seu aplicativo Logto. - Substitua o
clientId
e oclientSecret
pelo ID e segredo do seu aplicativo Logto. - Personalize a função
profile
para mapear o perfil do usuário para o objeto de usuário do Next Auth, o mapeamento padrão é mostrado no exemplo.
import NextAuth from 'next-auth';
const handler = NextAuth({
providers: [
{
id: 'logto',
name: 'Logto',
type: 'oauth',
// Você pode obter a URL bem conhecida na página de Detalhes do Aplicativo Logto,
// no campo "Endpoint de configuração do provedor OpenID"
wellKnown: 'https://xxxx.logto.app/oidc/.well-known/openid-configuration',
authorization: { params: { scope: 'openid offline_access profile email' } },
clientId: '<logto-app-id>',
clientSecret: '<logto-app-secret>',
client: {
id_token_signed_response_alg: 'ES384',
},
profile(profile) {
// Você pode personalizar o mapeamento do perfil do usuário aqui
return {
id: profile.sub,
name: profile.name ?? profile.username,
email: profile.email,
image: profile.picture,
};
},
},
],
});
export { handler as GET, handler as POST };
- Substitua a URL do
wellKnown
pelo "Endpoint de configuração do provedor OpenID" do seu aplicativo Logto. - Substitua o
clientId
e oclientSecret
pelo ID e segredo do seu aplicativo Logto. - Personalize a função
profile
para mapear o perfil do usuário para o objeto de usuário do Next Auth, o mapeamento padrão é mostrado no exemplo. - Lembre-se de definir o
id_token_signed_response_alg
comoES384
.
Ponto de verificação
Agora, você pode testar seu aplicativo para ver se a autenticação funciona como esperado.
Escopos e reivindicações
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:
const handler = NextAuth({
providers: [
{
id: 'logto',
name: 'Logto',
// ... outras opções
authorization: { params: { scope: 'openid offline_access profile email' } },
// ... outras opções
},
],
});
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.