Procure o emoji 🛠️ se quiser passar pelo conteúdo enquanto se concentra nas etapas de criação.
Esse tutorial demonstra como proteger uma aplicação Node.js construída com o framework Express implementando autenticação de usuário. Você vai melhorar uma aplicação Node.js inicial para praticar os seguintes conceitos de segurança:
- Adicionar login e logout de usuário.
- Recuperar informações de usuário.
- Proteger as rotas da aplicação.
- Chamar endpoints protegidos de uma API.
Este tutorial usa a biblioteca de OpenID Connect da Auth0 para Express para proteger as aplicações Express. Essa biblioteca dá às pessoas desenvolvedoras de Node.js uma alternativa ao Passport.js. O OpenID Connect para Express permite adicionar autenticação de usuário a aplicações Express usando as melhores práticas de segurança enquanto escreve menos código.
⚠️ Se você ainda precisar usar o Passport.js para proteger sua aplicação Express, consulte o tutorial Node.js e Autenticação Express usando o Passport (em inglês).
Como a Auth0 funciona?
Com a ajuda da Auth0, você não precisa ser um especialista em protocolos de identidade, como OAuth 2.0 ou OpenID Connect, para entender como proteger suas aplicações. Primeiro, você integra sua aplicação com a Auth0. Sua aplicação redirecionará os usuários para uma página de login personalizável da Auth0. Após seus usuários fazerem login com sucesso, Auth0 os redireciona de volta para a sua aplicação, retornando JSON Web Tokens (JWTs) com autenticação e informações de usuário.
⏰⚡️ Se você tiver pouco tempo, consulte o Guia de Início Rápido Express da Auth0 (em inglês) para começar a usar a autenticação de usuário em Express em apenas alguns minutos.
Obtenha a Aplicação Inicial
Criamos um projeto inicial para te ajudar a aprender os conceitos de segurança do Node.js por meio da prática. O projeto inicial usa Bootstrap com um tema personalizado para cuidar do estilo e do layout da sua aplicação. Você pode se concentrar em construir componentes Express para proteger sua aplicação.
🛠 Dessa forma, clone o repositório
auth0-express-pug-sample
em seu branch starter
para começar:git clone -b starter git@github.com:auth0-blog/auth0-express-pug-sample.git
🛠 Depois de clonar o repositório, torne
auth0-express-pug-sample
seu diretório atual:cd auth0-express-pug-sample
🛠 Instale as dependências do projeto Node.js:
npm install
🛠 Crie um arquivo
.env
dentro do diretório do projeto:touch .env
🛠 Preencha o arquivo
.env
assim:DEV_PORT=4041 PROD_PORT=4040
Para simplificar seu fluxo de desenvolvimento em Node.js, este projeto usa o
para reiniciar o servidor e nodemon
para recarregar o navegador sempre que os arquivos de código fonte relevantes forem alterados.browser-sync
🛠 Execute o seguinte comando para iniciar o servidor Node.js:
npm run dev
Você pode simular o comportamento de frameworks front-end quando são recarregados em execução, como React e Angular em templates Express usando o Browsersync. O navegador será atualizado automaticamente sempre que o código-fonte for alterado: por exemplo, quando você modifica uma regra CSS ou altera o valor de retorno de uma função.
🛠 Abra uma janela de terminal separada e execute o seguinte comando para servir a interface do usuário da sua aplicação Express:
npm run ui
O Browsersync abre automaticamente uma nova janela apresentando a interface de usuário da sua aplicação. Se não, abra
.http://localhost:4040/
Conecte O Express Com a Auth0
A melhor parte da plataforma Auth0 é a simplicidade para começar a usá-la, seguindo estas etapas:
Se inscreva e crie uma Aplicação Auth0
Se ainda não o fez,
cadastre-se para obter uma conta Auth0 gratuita →Uma conta gratuita oferece:
- 7.000 usuários ativos gratuitos e logins ilimitados.
- Login Universal Auth0 para Web, iOS e Android.
- Até 2 provedores de identidade social, como Google, GitHub e Twitter.
- Serverless ilimitados para personalizar e estender os recursos da Auth0.
Durante o cadastro, você cria um Auth0 Tenant, que representa o produto ou serviço ao qual você está adicionando autenticação.
🛠 Depois de se inscrever, Auth0 leva você para o Dashboard. No menu da barra lateral esquerda, clique em "Applications".
🛠 Em seguida, clique no botão "Create Application". Irá abrir um formulário para que você escreva o nome e escolha o tipo da aplicação.
- Name: (Nome)
Auth0 Express
- Application Type (Tipo da aplicação): Regular Web Applications
🛠 Clique no botão "Create" para concluir o processo. A página da sua aplicação Auth0 é carregada.
Na próxima etapa, você aprenderá como ajudar o Express e a Auth0 a se comunicarem.
Qual é a relação entre Auth0 Tenants e aplicações Auth0?
Digamos que você tenha uma aplicação Express de compartilhamento de fotos chamado “Noddit”. Você então criaria um Auth0 tenant chamado
noddit
.Agora, digamos que o Noddit esteja disponível em três plataformas: na web como uma aplicação de página única (Single Page Application ou SPA em inglês) e como um aplicativo móvel nativo para Android e iOS. Se cada plataforma precisar de autenticação, você precisará criar três aplicações Auth0 para fornecer ao produto tudo o que a pessoa precisa para autenticar os usuários por meio dessa plataforma.
Crie uma ponte de comunicação entre Express e Auth0
Ao usar a Auth0, você não precisa criar formulários de login. A Auth0 oferece uma página de login universal para reduzir a sobrecarga de adição e gerenciamento de autenticação.
Como funciona o Login Universal?
Sua aplicação Express redirecionará os usuários para a Auth0 sempre que eles dispararem uma requisição de autenticação. A Auth0 irá apresentar uma página de login. Assim que eles fizerem login, a Auth0 os redirecionará de volta para a sua aplicação. Para que o redirecionamento ocorra com segurança, você deve especificar nas suas configurações de aplicações Auth0 as URLs para os quais a Auth0 pode redirecionar usuários, uma vez que estejam autenticados.
🛠 Clique na guia "Settings" da página da aplicação Auth0 e preencha os seguintes valores:
🛠 URLs de callback permitidas (Allowed Callback URLs em inglês)
http://localhost:4040/callback
O valor acima é a URL que Auth0 pode usar para redirecionar seus usuários depois que eles fizerem login.
🛠URLs de logout permitidas (Allowed Logout URLs em inglês)
http://localhost:4040
O valor acima é a URL que Auth0 pode usar para redirecionar seus usuários depois que eles fizerem logout.
🛠 Role para baixo e clique no botão "Save changes".
🛠 Não feche esta página ainda. Você precisará de algumas informações na próxima seção.
Adicione as variáveis de configuração da Auth0 ao Express
Na aba "Settings" da página da aplicação Auth0, você precisa dos valores de Domínio Auth0 (Auth0 Domain em inglês) e ID do Cliente (Client ID em inglês) para permitir que sua aplicação Express use a ponte de comunicação que você criou.
O que exatamente é um domínio Auth0 e um ID de cliente Auth0?
Domain
Quando você criou uma nova conta Auth0, a Auth0 pediu para escolher um nome para seu Tenant. Este nome, anexado com
auth0.com
, é o seu domínio Auth0 (Auth0 Domain em inglês). É a URL base que você usará para acessar as APIs Auth0 e a URL para onde você redirecionará os usuários para fazer login.Auth0 também oferece suporte a domínios personalizados para para permitir que o Auth0 faça o trabalho pesado de autenticação para você sem comprometer sua experiência de branding.
ID de Cliente
A Auth0 atribui um ID de cliente (Client ID) a cada aplicação, que é uma string alfanumérica, e é o identificador exclusivo da sua aplicação (como
q8fij2iug0CmgPLfTfG1tZGdTQyGaTUA
). Você não pode modificar o ID do cliente. Você usará o ID do cliente para identificar a aplicação Auth0 que o SDK da Auth0 para Express precisa se conectar.Atenção: Outra informação crítica presente nas "Settings" é o Segredo do Cliente (Client Secret em inglês). Esse segredo protege seus recursos concedendo tokens apenas para solicitantes se tiverem autorização. Pense nisso como a senha da sua aplicação, que deve ser mantida em sigilo o tempo todo. Se alguém obtiver acesso ao seu segredo, pode se passar pela sua aplicação e acessar recursos protegidos.
🛠 Abra o arquivo
.env
do diretório do projeto auth0-express-pug-sample
e atualize-o da seguinte forma:DEV_PORT=4041 PROD_PORT=4040 AUTH0_ISSUER_BASE_URL=https://<AUTH0_DOMAIN>/ AUTH0_CLIENT_ID=
🛠 Para o valor
AUTH0_ISSUER_BASE_URL
, <AUTH0_DOMAIN>
é o valor do seu Domain nas "Settings". Certifique-se de manter a barra no final para esse valor.🛠
AUTH0_CLIENT_ID
é o seu Client ID em "Settings".Essas variáveis permitem que sua aplicação Express se identifique como uma parte autorizada para interagir com o servidor de autenticação Auth0.
Conexão Auth0 e Express
Você concluiu a configuração de um serviço de autenticação que sua aplicação Express pode consumir. Agora só falta continuar construindo o projeto ao longo deste guia, adicionando componentes para acionar e gerenciar o fluxo de autenticação.
Fique à vontade para se aprofundar na documentação da Auth0 para saber mais sobre como a Auth0 ajuda a economizar tempo na implementação e gerenciamento de identidade.
Configure O OpenID Connect Para Express
🛠 Você precisa seguir estas etapas para integrar a biblioteca OpenID Connect com sua aplicação Express.
Instale o OpenID Connect para Express
🛠 Execute o seguinte comando:
npm install express-openid-connect
Configure o OpenID Connect para Express
🛠 Abra o arquivo
.env
novamente e adicione valores em BASE_URL
e SESSION_SECRET
nele:DEV_PORT=4041 PROD_PORT=4040 AUTH0_ISSUER_BASE_URL=<...> AUTH0_CLIENT_ID=<...> BASE_URL=http://localhost:4040 SESSION_SECRET=
O valor
BASE_URL
é a URL onde sua aplicação é servida.O valor
SESSION_SECRET
é o segredo usado para assinar o cookie de ID de sessão, que pode ser uma string para um único segredo ou um vetor com vários segredos.🛠️ Execute o seguinte comando para gerar uma string adequada para o segredo da sessão:
node -e "console.log(crypto.randomBytes(32).toString('hex'))"
🛠️ Copie e cole a saída do comando acima como o valor de
SESSION_SECRET
em .env
.🛠️ Para que sua aplicação reconheça essas novas variáveis de ambiente, você precisa reiniciar o servidor Node.js. Localize a janela do terminal onde você executou
npm run dev
anteriormente, pare-o e execute-o novamente.Autenticação de usuário é um mecanismo para monitorar quem está acessando sua aplicação e controlar o que essas pessoas podem fazer. Por exemplo, você pode impedir que usuários que não tenham efetuado login acessem partes da sua aplicação. Nesse cenário, a Auth0 pode atuar como bouncer da aplicação.
Um bouncer é uma pessoa empregada por uma boate ou estabelecimento similar para impedir que encrenqueiros entrem ou os expulsem do local. A segurança do Express não é muito diferente da segurança de uma boate.
Se os usuários quiserem acessar uma rota protegida da sua aplicação, a Auth0 irá interrompê-los e solicitar que apresentem suas credenciais. Se a Auth0 puder verificar quem são e se devem entrar lá, a Auth0 os deixará entrar. Caso contrário, a Auth0 os levará de volta para uma rota pública da aplicação.
Agora, é importante reiterar que o processo de autenticação não acontecerá na sua aplicação. Sua aplicação Express redirecionará seus usuários para a página de login universal da Auth0, onde a Auth0 solicita as credenciais e redireciona o usuário de volta à sua aplicação com o resultado do processo de autenticação.
A biblioteca OpenID Connect para Express fornece a rota
auth
para anexar rotas de autenticação à sua aplicação. Você não precisará implementar controladores /login
ou /logout
, o OpenID Connect para Express faz isso para você.Agora você precisa inicializar, configurar e integrar
express-openid-connect
com sua aplicação Express.🛠 Abra o arquivo
src/index.js
e atualize a seção Required External Modules
para importar auth
:// src/index.js /** * Required External Modules */ const express = require('express'); const path = require('path'); const { auth } = require('express-openid-connect');
🛠 Em seguida, atualize a seção
App Configuration
para inicializar e usar auth
como uma função de middleware do Express:// src/index.js /** * App Configuration */ app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'pug'); app.use(express.static(path.join(__dirname, '..', 'public'))); app.use( auth({ issuerBaseURL: process.env.AUTH0_ISSUER_BASE_URL, baseURL: process.env.BASE_URL, clientID: process.env.AUTH0_CLIENT_ID, secret: process.env.SESSION_SECRET, authRequired: false, auth0Logout: true, }), );
Você está adicionando duas propriedades adicionais,
authRequired
e auth0Logout
. O que essas propriedades estão fazendo?authRequired
é uma propriedade booleana que configura o OpenID Connect para Express para exigir autenticação para todas as rotas quando você o define como true
. Para este projeto, você terá uma mistura de rotas públicas e protegidas. Dessa forma, você define essa propriedade como false
.auth0Logout
é outro valor booleano que habilita o recurso de logout Auth0, que permite um usuário fazer logout da sessão Auth0. Ao implementar a funcionalidade de logout em uma aplicação, normalmente há três camadas de sessão que você precisa considerar:- Camada de sessão da aplicação
- Camada de sessão Auth0
- Camada de sessão do provedor de identidade
Por exemplo, se um de seus usuários fez login usando o Google, você pode configurar seu serviço de autenticação Auth0 para que ele faça logout da aplicação, da sessão Auth0 ou do próprio Google. Confira o documento “Logout" (em inglês) para saber mais detalhes sobre a arquitetura do logout do usuário.
Para esta aplicação, você fará logout dos usuários da camada de sessão Auth0.
A biblioteca OpenID Connect para Express está configurada. Tudo pronto para implementar a autenticação do usuário na próxima seção.
Adicione Autenticação De Usuários
Ao longo deste guia, você usará mixins Pug para implementar a interface do usuário (UI) da aplicação seguindo uma arquitetura baseada em componentes. Cada mixin atuará como um componente de UI, tornando-se uma peça reutilizável que você pode criar e manter isoladamente.
Você precisa criar componentes de UI para que seus usuários acionem eventos de autenticação: login, logout e inscrição.
O OpenID Connect para Express cria um namespace oidc no objeto
req
da sua aplicação. Nesse namespace, a biblioteca armazena métodos e dados de autenticação, como um objeto user
para armazenar informações de perfil do usuário e um método login
para personalizar a experiência de login do usuário. Você explorará o objeto oidc
nas próximas seções.Crie um botão de login
🛠 Crie um arquivo
login-button.pug
dentro do diretório src/components/
:touch src/components/login-button.pug
🛠 Crie um
mixin
para representar um componente de botão de login em src/components/login-button.pug
assim:mixin login-button() button( class="btn btn-primary btn-block", onclick="window.location='/login'" ) Log In
Por baixo dos panos, o OpenID Connect para Express cria uma rota
/login
para a sua aplicação Express. Quando o usuário clica neste botão, sua aplicação Express solicita do usuário que faça autenticação e dê consentimento para que sua aplicação Express acesse determinados dados em nome deste usuário. Em sua arquitetura atual, isso significa que sua aplicação Express redireciona o usuário para a página de login universal da Auth0 para realizar o processo de autenticação. Você verá isso em ação nas próximas seções.Você pode personalizar a experiência de login usando o método
no controlador Express. Por exemplo, você pode passar opções para este método redirecionar usuários a uma página de login universal Auth0 otimizada para se inscrever na sua aplicação Express.req.oidc.login()
Crie um botão de inscrição
Você pode fazer os usuários acessarem diretamente uma página de inscrição em vez de uma página de login criando um controlador de rota
/sign-up
.🛠 Para começar, abra o arquivo
src/index.js
. Localize a seção Routes Definitions
. Nesta seção, existem diferentes subseções que definem rotas para cada recurso da sua aplicação Web Express. Localize a subseção > Authentication
e atualize-a da seguinte forma:// src/index.js /** * Routes Definitions */ // > Other route subsections... // > Authentication app.get('/sign-up', (req, res) => { res.oidc.login({ authorizationParams: { screen_hint: 'signup', }, }); });
Você cria um controlador de rota
/sign-up
, onde você acessa o método res.oidc.login()
. Esse método usa algumas LoginOptions
para personalizar o comportamento da experiência de login do usuário.Aqui, você sobrescrever o
padrão, que são parâmetros de URL que o OpenID Connect para Express usa ao redirecionar usuários para Auth0 para fazer login.authorizationParams
Você pode passar novos valores para alterar o que o servidor de autorização Auth0 retorna dependendo do seu caso de uso. Em seu controlador
/sign-up
, você especifica a propriedade screen_hint=signup
como um parâmetro de autorização para levar os usuários a um formulário de inscrição.{ authorizationParams: { screen_hint: "signup", }, }
Agora, crie um botão de inscrição para acionar esse evento solicitando a rota
/sign-up
.🛠 Crie um arquivo
signup-button.pug
no diretório src/components/
:touch src/components/signup-button.pug
🛠 Preencha
src/components/signup-button.pug
assim para definir um mixin signup-button
:mixin signup-button() button( class="btn btn-primary btn-block", onclick="window.location='/sign-up'" ) Sign Up
O uso do recurso de inscrição exige que você habilite a nova experiência de login universal Auth0 em seu tenant.
🛠 Abra a seção Login Universal do Auth0 Dashboard e escolha a opção "New" na subseção "Experience".
🛠 Role para baixo e clique no botão "Save changes".
A diferença entre a experiência de usuário em fazer login ou se inscrever ficará mais evidente quando você integrar esses componentes à aplicação Express e vê-los em ação. Você fará isso nas próximas seções
Crie um botão de logout
🛠 Crie um
logout-button.pug
no diretório src/components/
:touch src/components/logout-button.pug
🛠 Preencha o arquivo
src/components/logout-button.pug
assim:mixin logout-button() button( class="btn btn-danger btn-block", onclick="window.location='/logout'" ) Log Out
A rota
/logout
criada pelo OpenID Connect para Express chama o método req.oidc.logout()
por baixo dos panos. Este método limpa a sessão da aplicação e redireciona para o endpoint Auth0 /v2/logout
para limpar a sessão Auth0. Assim como no método de login, você pode passar LogoutOptions
para req.oidc.logout()
para personalizar seu comportamento.Aqui, você passa a opção
returnTo
para especificar a URL onde Auth0 deve redirecionar seus usuários após o logout. No momento, você está trabalhando localmente e as "Allowed Logout URLs" da sua aplicação Auth0 apontam para http://localhost:4040
.No entanto, se você fizer o deploy da sua aplicação Express para produção, será necessário adicionar a URL de logout de produção à lista "Allowed Logout URLs" e garantir que a Auth0 redirecione seus usuários para essa URL de produção e não para o
localhost
. Leia mais sobre como funciona o Logout na Auth0 (em inglês).
Integre os botões de login e logout
Vamos envolver os mixins
login-button
e logout-button
em um chamado authentication-button
.🛠 Crie um arquivo
authentication-button.pug
no diretório src/components/
:touch src/components/authentication-button.pug
🛠 Preencha
src/components/authentication-button.pug
com o seguinte código:include ./login-button include ./logout-button mixin authentication-button(isAuthenticated) if isAuthenticated +logout-button else +login-button
isAuthenticated
é um valor booleano exposto pelo objeto req.oidc
. Seu valor é true
quando a Auth0 autenticou o usuário e false
quando não o fez.Existem algumas vantagens em usar este wrapper de mixin
authentication-button
:Você pode construir interfaces flexíveis.
authentication-button
serve como uma opção de "login/logout" que você pode colocar em qualquer lugar que precisar dessa funcionalidade de troca. No entanto, você ainda tem os mixins login-button
e logout-button
separados para os casos em que você precise de sua funcionalidade de forma isolada. Por exemplo, você pode ter um botão de logout em uma página que somente usuários autenticados podem ver.Você pode construir interfaces extensíveis. Você pode facilmente trocar o mixin
login-button
por signup-button
em authentication-button
para criar uma opção de "inscrever-se/fazer logout". Você também pode envolver a opção "inscrever-se/fazer logout" em um mixin new-authentication-button
.Você pode construir interfaces declarativas. Usando
authentication-button
, você pode adicionar a funcionalidade de login e logout ao seu componente de barra de navegação, por exemplo, sem pensar nos detalhes de implementação de como a troca de autenticação funciona.🛠 Com isso em mente, crie um arquivo
auth-nav.pug
no diretório src/components/
:touch src/components/auth-nav.pug
🛠 Preencha
src/components/auth-nav.pug
assim:include ./authentication-button mixin auth-nav(isAuthenticated) div(class="navbar-nav ml-auto") +authentication-button(isAuthenticated)
isAuthenticated
aparece de novo. De onde vem esse valor? Você vai descobrir em breve!🛠 Finalmente, abra o arquivo
nav-bar.pug
no diretório src/components/
e atualize-o assim:include ./main-nav include ./auth-nav mixin nav-bar(activeRoute) div(class="nav-container mb-3") nav(class="navbar navbar-expand-md navbar-light bg-light") div(class="container") div(class="navbar-brand logo") +main-nav(activeRoute) +auth-nav(isAuthenticated)
Por ter diferentes tipos de subcomponentes da barra de navegação, você pode estender cada um conforme necessário, sem reabrir e modificar o componente
nav-bar
.Mais uma vez,
isAuthenticated
aparece. A biblioteca OpenID Connect para Express define esse valor no método req.oidc.isAuthenticated()
. Seu valor de retorno é essencial para que a autenticação funcione corretamente em sua aplicação Express.Como você passa dados de um controlador para um modelo no Express?
Em aplicações web Express, você tem acesso a um fluxo de dados unidirecional do controlador de rota para o modelo. Como tal, cada controlador de rota que renderiza um modelo que depende de
isAuthenticated
deve passar esse valor.No entanto, passar um valor manualmente para um modelo em cada controlador de rota não é apenas tedioso, mas propenso a erros. O que você pode fazer é disponibilizar o valor como um valor local para todos os modelos Pug.
🛠 Atualize a seção
App Configuration
no arquivo src/index.js
dessa forma:// src/index.js /** * App Configuration */ app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'pug'); app.use(express.static(path.join(__dirname, '..', 'public'))); app.use( auth({ issuerBaseURL: process.env.AUTH0_ISSUER_BASE_URL, baseURL: process.env.BASE_URL, clientID: process.env.AUTH0_CLIENT_ID, secret: process.env.SESSION_SECRET, authRequired: false, auth0Logout: true, }), ); app.use((req, res, next) => { res.locals.isAuthenticated = req.oidc.isAuthenticated(); next(); });
Você define
res.locals
em um manipulador de função de middleware. Este objeto permite que você passe dados pela sua Aplicação Express. Todos os seus modelos de Pug podem acessar suas propriedades (como isAuthenticated
) diretamente. Como req.oidc.isAuthenticated()
é um método, você deve executá-lo para obter seu valor.Há uma ressalva sobre o uso de
res.locals
: esses valores vivem apenas em uma requisição individual. Assim que o ciclo de requisição-resposta é concluído, os valores desaparecem. Isso não é um problema para sua aplicação, pois cada vez que um usuário solicita uma rota do navegador, o ciclo de requisição-resposta começa novamente.🛠 Vá em frente e tente fazer o login. Sua aplicação Express redireciona você para a página de login universal da Auth0. Você pode usar um formulário para fazer login com um nome de usuário e senha ou um provedor de identidade social como o Google. Observe que esta página de login também oferece a opção de se inscrever.
Experimento: Use o mixin signup-button
signup-button
Troque o mixin
login-button
pelo mixin signup-button
na condição definida no mixin authentication-button
:include ./signup-button include ./logout-button mixin authentication-button(isAuthenticated) if isAuthenticated +logout-button else +signup-button
Ao clicar no botão "Sign Up" (Inscreva-se), você será direcionado para uma página com linguagem otimizada para incentivar a se inscrever em sua aplicação Express.
Experimente isso!
Depois de concluir esse teste, troque
signup-button
por login-button
para continuar com o restante deste guia.include ./login-button include ./logout-button mixin authentication-button(isAuthenticated) if isAuthenticated +logout-button else +login-button
Você pode personalizar a aparência das novas páginas de Login Universal. Você também pode substituir qualquer texto na "New Experience" usando a API de Personalização de Texto.
🛠 Clique na aba Profile e depois clique no botão "Log Out".
Observe que o Express desconectou você, mas em vez de levá-lo de volta à rota
/profile
, ele o levou de volta à rota /
, a página inicial.🛠 Clique na aba Profile e agora clique no botão "Log In".
Desta vez, o Express te leva novamente de volta à página inicial
/
depois de fazer login. Como usuário, você espera acessar a página /profile
depois de fazer login, certo? Afinal, seu sistema de autenticação está agindo como um bouncer. O bouncer não leva as pessoas de volta à entrada da boate depois de apresentarem seus RGs. O bouncer permite que essas pessoas passem e acessem a sala VIP ou qualquer sala que o bouncer esteja protegendo.Por que esse redirecionamento da página inicial está acontecendo?
Esta aplicação web Express está usando rotas estáticas para renderizar sua interface de usuário. Você mapeia uma ação da interface do usuário com um endpoint ou controlador do servidor. Este mapeamento é fixo até então.
O controlador de rota
/login
que a biblioteca OpenID Connect para Express criou para você tem um valor fixo para o caminho ao qual a Auth0 deve retornar os usuários após eles efetuarem login. Esse valor padrão é a raiz da URL do servidor, /
.No entanto, e se a página
/profile
tivesse recursos públicos e protegidos? Em um cenário como esse, qualquer pessoa pode visitar a página /profile
para ler suas informações públicas. Em seguida, os usuários podem fazer login para ler as informações protegidas. A melhor experiência do usuário é que os usuários retornem à página /profile
após efetuarem login, não à página inicial.Uma maneira de corrigir esse redirecionamento da página inicial é criar uma rota dedicada para cada tipo de login e logout:
GET /sign-up-profile GET /sign-up-external-api GET /login-profile GET /login-external-api GET /logout-profile GET /logout-external-api
No entanto, esse método não vai escalar nada bem. Imagine se você tivesse mais de 10 páginas diferentes que exigem uma experiência de login tranquila.
Seria melhor criar uma única rota dinâmica que pudesse lidar com diferentes "tipos" de ações de login e logout:
GET /sign-up/:page GET /login/:page GET /logout/:page
Como a rota
se comporta de maneira muito parecida com a rota/sign-up
, você também está aprimorando essa rota - caso queira usar o botão "Inscrever-se" em sua aplicação./login
Em seguida, você pode pegar esse parâmetro
:page
e usá-lo para dizer à Auth0 para voltar os usuários para serverUrl/page
depois que eles fizerem login ou logout.Para implementar facilmente esses novos controladores de rota de autenticação, você pode aproveitar a propriedade
activeRoute
que está passando de seus controladores de rota para seus modelos. Dê uma olhada no controlador de rota /profile
, por exemplo:app.get('/profile', (req, res) => { res.render('profile', { activeRoute: req.originalUrl }); });
Você passa este objeto
{ activeRoute: req.originalUrl }
em todos os controladores de rota. Recentemente, você aprendeu como aproveitar res.locals
para disponibilizar o status de autenticação do usuário para toda a aplicação Express. Você pode fazer o mesmo para a propriedade activeRoute
.🛠 As etapas a seguir mostrarão como criar rotas de autenticação dinâmicas. No entanto, se você deseja que o Express redirecione todos os usuários que efetuam logout para a página inicial, pode deixar sua aplicação como está.
🛠 Atualize a seção
App Configuration
no arquivo src/index.js
da seguinte forma:// src/index.js /** * App Configuration */ app.set("views", path.join(__dirname, "views")); app.set("view engine", "pug"); app.use(express.static(...)); app.use( auth({...}) ); app.use((req, res, next) => { res.locals.isAuthenticated = req.oidc.isAuthenticated(); res.locals.activeRoute = req.originalUrl; next(); });
Agora você define outra variável local que todos os modelos Pug podem acessar:
res.locals.activeRoute
. Você não precisa mais passar activeRoute
para seus modelos de cada controlador.🛠 Localize a seção
Routes Definitions
no arquivo src/index.js
. Atualize as subseções > Home
, > Profile
, e > External API
assim:// src/index.js /** * Routes Definitions */ // > Home app.get('/', (req, res) => { res.render('home'); }); // > Profile app.get('/profile', (req, res) => { res.render('profile'); }); // > External API app.get('/external-api', (req, res) => { res.render('external-api'); });
🛠 Agora você precisa criar os controladores de rota
sign-up/:page
, login/:page
e logout/:page
. Volte para a seção Routes Definitions
no arquivo src/index.js
. Atualize a subseção > Authentication
assim:// src/index.js /** * Routes Definitions */ // > Authentication app.get('/sign-up/:page', (req, res) => { const { page } = req.params; res.oidc.login({ returnTo: page, authorizationParams: { screen_hint: 'signup', }, }); }); app.get('/login/:page', (req, res) => { const { page } = req.params; res.oidc.login({ returnTo: page, }); }); app.get('/logout/:page', (req, res) => { const { page } = req.params; res.oidc.logout({ returnTo: page, }); });
Agora, você precisa atualizar seus botões de login e logout para usar esses controladores de rota personalizados em vez dos que vem padrão criados pelo Express OpenID Connect.
🛠 Atualize
src/components/signup-button.pug
dessa forma:mixin signup-button() button( class="btn btn-primary btn-block", onclick=`window.location='/sign-up/${activeRoute}'` ) Sign Up
🛠 Atualize
src/components/login-button.pug
dessa forma:mixin login-button() button( class="btn btn-primary btn-block", onclick=`window.location='/login/${activeRoute}'` ) Log In
🛠 Atualize
src/components/logout-button.pug
dessa forma:mixin logout-button() button( class="btn btn-danger btn-block", onclick=`window.location='/logout/${activeRoute}'` ) Log Out
está disponível em qualquer modelo sem a necessidade de passá-lo de mixin para mixin.activeRoute
🛠 Visite a página "Profile" e tente fazer o login ou logout.
Se você fizer login, observe que você volta para a página "Profile" depois de fazer login usando a página de login universal Auth0.
Se você fizer logout, receberá um erro!
Por que você está recebendo um erro ao fazer logout da página
?/profile
Se você clicar no link "See details for this error" na página de erro, saberá que o erro está relacionado a um
invalid_request
: O parâmetro querystring"returnTo" "http://localhost:4040/profile" não está definido como uma URL válida em "Allowed Logout URLs".Durante a seção de configuração da Auth0 deste guia, você definiu "Allowed Logout URLs" para a aplicação Auth0 que representa sua aplicação Web Express na plataforma Auth0:
Allowed Logout URLs
http://localhost:4040
Auth0 só pode redirecionar seus usuários depois que eles fizerem logout das URLs listadas nesse campo. Assim, você precisa adicionar os caminhos
/profile
e /external-api
a ele.🛠 Volte para a seção "Applications" no Auth0 Dashboard. Selecione sua aplicação"Auth0 Express Sample" e clique na guia "Settings".
🛠 Localize Allowed Logout URLs atualize-as assim:
http://localhost:4040, http://localhost:4040/profile, http://localhost:4040/external-api
🛠 Role para baixo e clique em "Save Changes".
🛠 Volte para a interface de usuário da aplicação no navegador. Visite as páginas "Profile" ou "External API". Atualize a página e tente fazer login e logout. Agora você deve permanecer na mesma página depois que qualquer ação for concluída sem erros.
Nesta seção, você aprendeu como usar os controladores de rota embutidos
/login
e /logout
expostos pela biblioteca OpenID Connect para Express. Você também aprendeu a criar controladores de autenticação personalizados para melhorar a experiência do usuário em sua aplicação e para acomodar diferentes casos de uso.Na próxima seção, você aprenderá como recuperar e exibir informações de perfil de usuário em sua interface de usuário.
Recupere Informações Do Usuário
Você pode usar dados de perfil armazenados em seu banco de dados de usuário Auth0 para personalizar a interface de usuário da sua aplicação Express. A biblioteca OpenID Connect para Express expõe esses dados de perfil no objeto
req.oidc.user
. Algumas das informações do usuário disponíveis incluem o nome, apelido, foto e e-mail do usuário conectado.Como você pode usar
para criar uma página de perfil para seus usuários?req.oidc.user
🛠 Atualize o controlador de rota
/profile
na seção Routes Definitions > Profile
no arquivo src/index.js
dessa forma:// src/index.js /** * Routes Definitions */ // > Profile app.get('/profile', (req, res) => { res.render('profile', { user: req.oidc.user, }); });
🛠 Depois, atualize o modelo
/profile
definido em src/views/profile.pug
assim:extends ../components/layout block content if user div div(class="row align-items-center profile-header") div(class="col-md-2 mb-3") img( class="rounded-circle img-fluid profile-picture mb-3 mb-md-0" src=user.picture alt="Profile" ) div(class="col-md text-center text-md-left") h2 #{user.name} p(class="lead text-muted") #{user.email} div(class="row") pre(class="col-12 text-light bg-dark p-4") | #{JSON.stringify(user, null, 2)}
O que está acontecendo no modelo
profile
?- Você obtém o
,name
epicture
do usuário do objetoemail
que você passou para o modelo do controlador de rotauser
./profile
- Em seguida, você exibe essas três propriedades na interface de usuário. Você apenas renderiza o conteúdo do modelo
se o objetoprofile
estiver definido.user
- Por fim, você exibe o conteúdo completo do token de ID decodificado em uma caixa de código. Agora você pode ver todas as outras propriedades disponíveis para você usar.
O que é um ID Token?
Depois que um usuário efetua login com sucesso, Auth0 envia um ID token para sua aplicação. Os sistemas de autenticação, como Auth0, usam ID Tokens na autenticação baseada em token para armazenar em cache as informações do perfil do usuário e fornecê-las a uma aplicação. O armazenamento em cache de ID tokens pode contribuir para melhorias no desempenho e capacidade de resposta da sua aplicação.
Você pode usar os dados do ID token para personalizar a interface do usuário da sua aplicação. A biblioteca OpenID Connect para Express decodifica o ID token e adiciona as suas informações à propriedade
user
do namespace req.oidc
. Algumas das informações do ID token incluem o nome, apelido, imagem e e-mail do usuário conectado.O modelo
profile
renderiza informações do usuário que você pode considerar protegidas. Além disso, a propriedade user
é null
se não houver um usuário conectado. Portanto, de qualquer forma, este componente só deve renderizar se a Auth0 tiver autenticado o usuário.Como tal, você deve proteger a rota que renderiza este modelo,
. Você aprenderá a fazer exatamente isso na próxima seção.http://localhost:4040/profile
Proteja as Rotas
A biblioteca OpenID Connect para Express expõe uma função de middleware
que você pode usar para exigir que os usuários façam login para acessar uma rota específica. O Express redirecionará para a página de Login Universal Auth0 qualquer usuário que não tenha feito login e tente acessar a rota.requiresAuth()
Um lembrete: para
funcionar, você deve definirrequiresAuth()
comoauthRequired
ao inicializar o Express OpenID Connect usando a função de middlewarefalse
.auth
🛠 Abra o arquivo
src/index.js
e atualize a seção Required External Modules
dessa forma:// src/index.js /** * Required External Modules */ const express = require('express'); const path = require('path'); const { auth, requiresAuth } = require('express-openid-connect');
Você pode adicionar a função de middleware
requiresAuth()
como parte do ciclo de solicitação-resposta de cada controlador que deseja proteger — neste caso, /profile
e /external-api
🛠 Atualize a subseção
Routes Definitions > Profile
do arquivo src/index.js
assim:/** * Routes Definitions */ // > Profile app.get('/profile', requiresAuth(), (req, res) => { res.render('profile', { user: req.oidc.user, }); });
Agora, quando os usuários que não efetuaram login visitarem uma rota protegida, sua aplicação Express redirecionará esse usuário para a página de login. Após o login do usuário, a Auth0 redirecionará o usuário para a página que ele pretendia acessar antes do login.
Agora você pode testar se
/profile
exige que os usuários façam login antes de acessá-lo. Faça o log out e tente acessar a página Profile. Se funcionar, o Express redireciona você para fazer o login com Auth0.Chame Uma API
Esta seção se concentra em mostrar como obter um token de acesso (access token, em inglês) na sua aplicação Express e como usá-lo para fazer chamadas de API para endpoints protegidos.
Ao usar a Auth0, você delega o processo de autenticação a um serviço centralizado. A Auth0 oferece a funcionalidade de fazer login e logout de usuários da aplicação Express. No entanto, sua aplicação pode precisar acessar recursos protegidos de uma API, como contatos, fotos ou histórico de compras.
Você também pode proteger uma API com Auth0. Existem vários guias de início rápido de API para te ajudar a integrar a Auth0 com sua plataforma de back-end.
Ao usar a Auth0 para proteger sua API, você também delega o processo de autorização a um serviço centralizado que garante que apenas aplicações de cliente aprovadas possam acessar recursos protegidos em nome de um usuário.
Como você pode fazer chamadas de API externas seguras a partir do Express?
Sua aplicação Express autentica o usuário e recebe um token de acesso da Auth0. A aplicação pode então passar esse token de acesso para sua API como uma credencial. Por sua vez, sua API pode usar bibliotecas Auth0 para verificar o token de acesso que recebe da aplicação e emitir uma resposta com os dados desejados.
Em vez de criar uma API do zero para testar os fluxos de autenticação e autorização entre o cliente e o servidor, você usará uma API de demonstração Express API que preparei para você.
Obtenha a API de demonstração Express API
🛠 Abra o terminal em uma nova janela e clone o repositório
auth0-express-js-sample
em algum lugar do sistema. Certifique-se de fazer o clone fora do diretório do projeto Express.git clone git@github.com:auth0-blog/auth0-express-js-sample.git
🛠 Depois de clonar este repositório, torne o diretório
seu diretório atual:auth0-express-js-sample
cd auth0-express-js-sample
🛠 Instale as dependências do projeto Node.js:
npm install
Conecte a Express API com Auth0
Crie uma ponte de comunicação entre o Express e Auth0
Este processo é semelhante a como você conectou o Express à Auth0.
🛠 Vá para a seção APIs no Dashboard da Auth0 e clique no botão "Create API".
🛠 Então, no formulário que a Auth0 mostra:
- Adicione um nome à sua API:
Auth0 Express Sample
- Defina seu valor de identificador:
https://express.sample
- Deixe o algoritmo de assinatura como
, pois é a melhor opção do ponto de vista de segurança.RS256
Identificadores são strings únicas que ajudam a Auth0 a diferenciar suas APIs. Recomendamos o uso de URLs para facilitar a criação de identificadores únicos de maneira previsível; no entanto, a Auth0 nunca chama essas URLs.
🛠 Com esses valores preenchidos, clique no botão "Create". Mantenha esta página aberta, pois você precisará de alguns de seus valores na próxima seção.
Adicione as variáveis de configuração da Auth0 à Express
🛠 Crie um arquivo .
env
para o servidor da API no diretório auth0-express-js-sample:
touch .env
🛠 Preencha este arquivo
auth0-express-js-sample/.env
da seguinte forma:SERVER_PORT=6060 CLIENT_ORIGIN_URL=http://localhost:4040 AUTH0_AUDIENCE= AUTH0_DOMAIN=
🛠 Volte para a página da API no dashboard da Auth0 e siga estas etapas para obter a Auth0 Audience:
- 🛠 Clique na guia "Settings".
- 🛠 Localize o campo "Identifier" e copie seu valor.
- 🛠 Cole o valor "Identifier" como o valor de
no arquivoAUTH0_AUDIENCE
..env
Agora, siga estas etapas para obter o valor do Auth0 Domain:
- 🛠 Clique na aba "Test".
- 🛠 Localize a seção chamada "Asking Auth0 for tokens from my application".
- 🛠 Clique na guia cURL para mostrar uma requisição
de exemplo.POST
- 🛠 Copie seu domínio Auth0, que faz parte do valor do parâmetro
.--url: nome-do-tenant.regiao.auth0.com
- 🛠 Cole o valor do domínio Auth0 como o valor de
no arquivoAUTH0_DOMAIN
..env
Dicas para obter o Auth0 Domain
O Auth0 Domain é a substring entre o protocolo,
e o caminhohttps://
./oauth/token
O Auth0 Domain segue este padrão:
.nome-do-tenant.regiao.auth0.com
O subdomínio da região (
,au
ouus
) é opcional. Alguns domínios Auth0 não o possuem.eu
Clique na imagem acima, por favor, se tiver alguma dúvida de como obter o valor do Auth0 Domain.
🛠 Com os valores de configuração
.env
definidos, rode o servidor da API executando o seguinte comando:npm start
Configure o Express para consumir a API de demonstração
Sua aplicação Express precisa passar um token de acesso ao chamar uma API de destino para acessar recursos protegidos. Você pode solicitar um token de acesso do servidor de autorização Auth0 configurando seu middleware
auth()
para incluir o público da API e um tipo de resposta code
. Vamos ver esta configuração auth()
como exemplo:app.use( auth({ authorizationParams: { response_type: 'code', audience: 'https://api.example.com/products', }, }), );
Agora, sempre que você configurar
auth()
para obter um código como seu response_type
, você precisa incluir o Client Secret (segredo do cliente) da sua aplicação Auth0.🛠 Volte para a seção "Applications" do Auth0 Dashboard. Selecione sua aplicação “Auth0 Express Sample" e clique na guia "Settings". Localize o campo "Client Secret".
🛠 Volte para o diretório do projeto
auth0-express-pug-sample
que armazena sua aplicação Express.🛠 Localize o arquivo
auth0-express-pug-sample/.env
e adicione os valores AUTH0_AUDIENCE
, SERVER_URL
, e CLIENT_SECRET
nele:DEV_PORT=4041 PROD_PORT=4040 AUTH0_ISSUER_BASE_URL=https://<AUTH0-DOMAIN>/ AUTH0_CLIENT_ID=<...> BASE_URL=http://localhost:4040 SESSION_SECRET=<...> AUTH0_AUDIENCE=https://express.sample SERVER_URL=http://localhost:6060 CLIENT_SECRET=
🛠 O valor de
AUTH0_AUDIENCE
é o mesmo para a aplicação Web Express e para a API Express.SERVER_URL
é a URL onde o servidor da API Express está rodando.🛠 Use o valor do Client Secret das configurações da aplicação Auth0 como o valor de
CLIENT_SECRET
.O segredo do cliente Auth0 é um valor crítico, pois protege seus recursos, concedendo apenas credenciais relacionadas à autenticação na forma de tokens aos solicitantes se eles forem autorizados. Pense nisso como a senha da sua aplicação, que deve ser mantida em sigilo o tempo todo. Se alguém obtiver acesso ao seu segredo do cliente, pode se passar pela sua aplicação e acessar recursos protegidos.
Juntas, essas variáveis permitem que sua aplicação se identifique como uma parte autorizada para interagir com o servidor de autenticação Auth0.
🛠️ Você precisa reiniciar o servidor Node.js para que sua aplicação reconheça essas novas variáveis de ambiente. Localize a janela do terminal onde você executou o comando
npm run dev
anteriormente, interrompa-a e execute-a novamente.Você pode solicitar um token de acesso em um formato que a API possa verificar passando propriedades
audience
e response_type
para o inicializador auth()
.🛠 Abra o arquivo
src/index.js
, localize a seção App Configuration
e atualize a inicialização de auth()
da seguinte forma:// src/index.js /** * App Configuration */ app.set("views", path.join(__dirname, "views")); app.set("view engine", "pug"); app.use(express.static(path.join(__dirname, "..", "public"))); // 👇 Update the mounting and initialization of auth() app.use( auth({ issuerBaseURL: process.env.AUTH0_ISSUER_BASE_URL, baseURL: process.env.BASE_URL, clientID: process.env.AUTH0_CLIENT_ID, secret: process.env.SESSION_SECRET, authRequired: false, auth0Logout: true, clientSecret: process.env.CLIENT_SECRET, authorizationParams: { response_type: "code", audience: process.env.AUTH0_AUDIENCE, }, }) ); app.use((req, res, next) => {...});
clientSecret
vai no mesmo nível que as outras propriedades. No entanto, quando o Express OpenID Connect faz requisições ao servidor de autorização Auth0, ele usa response_type
e audience
como parâmetros de requisição. Assim, você precisa especificar esses dois valores como propriedades do objeto authorizationParams
.Por que o valor Auth0 Audience é o mesmo para as duas aplicações? Auth0 usa o valor da propriedade
audience
para determinar qual servidor de recurso (API) o usuário está autorizando o acesso da aplicação Express. É como um número de telefone. Você deseja garantir que sua aplicação Express "envie mensagem para a API correta".As ações que a sua aplicação Express pode executar na API dependem dos escopos que seu token de acesso contem.
Lembra daquela tela que você viu quando fez login pela primeira vez com Auth0 pedindo permissão para acessar as informações de seu perfil? Sua aplicação Express fará a requisição da autorização do usuário para acessar os escopos requisitados e o usuário aprovará ou negará a requisição. Você pode ter visto algo semelhante ao compartilhar seus contatos ou fotos de uma plataforma de mídia social com uma aplicação de terceiros.
Quando você não passa uma propriedade
scope
para o objeto authorizationParams
, usado para configurar o auth()
, a biblioteca OpenID Connect para Express usa por padrão os escopos do OpenID Connect: openid profile email
.
: Este escopo informa ao servidor de autorização Auth0 que o cliente está fazendo uma requisição OpenID Connect (OIDC) para verificar a identidade do usuário. OpenID Connect é um protocolo de autenticação.openid
: este valor de escopo requer acesso às informações de perfil padrão do usuário, comoprofile
,name
enickname
.picture
: este valor de escopo requer acesso às informações deemail
eemail
.email_verified
Os detalhes dos escopos do OpenID Connect vão para o token de ID. No entanto, você pode definir escopos de API personalizados para implementar o controle de acesso. Você os identificará nas chamadas que suas aplicações clientes fazem para essa API. Auth0 inclui escopos de API no token de acesso como o valor de declaração de scope.
Os conceitos sobre escopos ou permissões de API são melhor abordados em um tutorial de API Auth0, como"Use TypeScript to Create a Secure API with Node.js and Express: Role-Based Access Control".
🛠 Visite a página "External API" e note que existem dois botões para você solicitar recursos da Express Demo API:
- "Get Public Message" =>
GET /messages/public-message
- "Get Protected Message" =>
GET /messages/protected-message
Qual é o plano para implementar essas chamadas de API em sua aplicação Web Express? Crie mais duas rotas.
Primeiro, você precisará de um pacote para fazer requisições HTTP de seus controladores de rota Express. Para isso vamos usar a biblioteca
got
you🛠 Instale
no seu projeto got
auth0-express-pug-sample
:npm install got
got
se autodenomina uma biblioteca de requisição HTTP poderosa e amigável para aplicações Node.js.🛠 Abra o arquivo
src/index.js
e atualize a seção Required External Modules
da seguinte forma:// src/index.js /** * Required External Modules */ const express = require('express'); const path = require('path'); const { auth, requiresAuth } = require('express-openid-connect'); const got = require('got');
🛠 Em seguida, atualize a subseção
Routes Definitions > External API
em src/index.js
para adicionar duas rotas para lidar com a recuperação de mensagens da API Express:// src/index.js /** * Routes Definitions */ // > External API app.get('/external-api', (req, res) => { res.render('external-api'); }); app.get('/external-api/public-message', async (req, res) => { let message; try { const body = await got( `${process.env.SERVER_URL}/api/messages/public-message`, ).json(); message = body.message; } catch (e) { message = 'Unable to retrieve message.'; } res.render('external-api', { message }); }); app.get('/external-api/protected-message', requiresAuth(), async (req, res) => { const { token_type, access_token } = req.oidc.accessToken; let message; try { const body = await got( `${process.env.SERVER_URL}/api/messages/protected-message`, { headers: { Authorization: `${token_type} ${access_token}`, }, }, ).json(); message = body.message; } catch (e) { message = 'Unable to retrieve message.'; } res.render('external-api', { message }); });
O que está acontecendo nos controladores de rota da API externa?
- Nada muda para
. Ela continua sendo a página inicial deste caminho./external-api
solicita dados de mensagem de um endpoint de API público/external-api/public-message
./api/messages/public-message
- Ele armazena a resposta dessa solicitação na variável
, que passa para o modelomessage
.external-api
- Esta rota não exige login do usuário para acessar a página ou fazer a chamada da API.
- Ele armazena a resposta dessa solicitação na variável
solicita dados de mensagem de um endpoint de API protegido,/external-api/protected-message
./api/messages/protected-message
- Ele obtém o token de acesso e seu tipo no
.req.oidc.accessToken
- Ele usa o token de acesso no cabeçalho de autorização da chamada da API protegida.
- Ele armazena a resposta dessa requisição na variável
, que passa para o modelomessage
.external-api
- Como essa rota requer um token de acesso válido para fazer a requisição da API protegida, ela usa
para solicitar que o usuário faça login.requiresAuth()
- Ele obtém o token de acesso e seu tipo no
O encadeamento do método
de.json()
permite obter as respostas do servidor no formato JSON.got
🛠 Agora, atualize
src/views/external-api.pug
da seguinte forma:extends ../components/layout block content div h1 External API p | Use these buttons to call an external API. The protected API call has an access token in its authorization header. The API server will validate the access token using the Auth0 Audience value. div( class="btn-group mt-5", role="group", aria-label="External API Requests Examples" ) button( type="button", class="btn btn-primary" onclick="window.location='/external-api/public-message'" ) Get Public Message button( type="button", class="btn btn-primary" onclick="window.location='/external-api/protected-message'" ) Get Protected Message if message div(class="mt-5") h6(class="muted") Result div(class="container-fluid") div(class="row") code(class="col-12 text-light bg-dark p-4") | #{JSON.stringify(message, null, 2)}
O que está acontecendo agora dentro do modelo
external-api
?Você aciona chamadas para os controladores de rota
/external-api/public-message
e /external-api/protected-message
do grupo de botões. Se message
for definida, você renderiza a resposta do servidor.🛠 Faça logout e login novamente para obter um novo token de acesso da Auth0 que inclui as informações de audiência.
🛠 Visite
e clique em qualquer um dos botões na página da API externa para testar as respostas. Você pode ser solicitado a fazer login, dependendo da ação que escolher executar.http://localhost:4040/external-api
Obtenha a mensagem pública:
The API doesn't require an access token to share this message.
Obtenha a mensagem protegida:
The API successfully validated your access token.
Agora tem um problema... Visite
. Depois de fazer login, você verá o resultado. Agora tente fazer log out...http://localhost:4040/external-api/protected-message
Você recebe uma mensagem de erro:
Cannot GET /logout/external-api/protected-message
.Se você tentar fazer login em
, receberá um erro semelhante:http://localhost:4040/external-api/public-message
Cannot GET /login/external-api/public-message
Não há um controlador de rota para lidar com as seguintes requisições:
GET /sign-up/:page/:section GET /login/:page/:section GET /logout/:page/:section
Você pode criar um controlador de rota para lidar com esses caminhos específicos, mas não há necessidade. Você pode adicionar
section
como um parâmetro opcional para os controladores de rota de autenticação existentes.🛠 Abra o arquivo
src/index.js
e localize a subseção Routes Definitions > Authentication
. Atualize esta seção da seguinte forma:// src/index.js /** * Routes Definitions */ // > Authentication app.get('/sign-up/:page/:section?', (req, res) => { const { page, section } = req.params; res.oidc.login({ returnTo: section ? `${page}/${section}` : page, authorizationParams: { screen_hint: 'signup', }, }); }); app.get('/login/:page/:section?', (req, res) => { const { page, section } = req.params; res.oidc.login({ returnTo: section ? `${page}/${section}` : page, }); }); app.get('/logout/:page/:section?', (req, res) => { const { page } = req.params; res.oidc.logout({ returnTo: page, }); });
Vamos testar esse ajuste.
🛠 Visite
e faça logout. Você deve ser levado para a página “External API”.http://localhost:4040/external-api/protected-message
🛠 Visite
e faça login daí. Você deveria ter permanecido na mesma página.http://localhost:4040/external-api/public-message
Conclusão
Você implementou a autenticação de usuário no Express para identificar seus usuários, obter informações de perfil de usuário e controlar o conteúdo que seus usuários podem acessar protegendo rotas e recursos de API.
Este tutorial mostrou o caso de uso de autenticação mais comum para uma aplicação web Express: inscrição, login e logout simples e chamada de APIs protegidas.
No entanto, a Auth0 é uma plataforma extensível e flexível que pode te ajudar a chegar mais longe. Se você tiver um caso de uso mais complexo, verifique os Auth0 Architecture Scenarios para saber mais sobre os cenários de arquitetura típicos que identificamos ao trabalhar com clientes na implementação da Auth0.
Num próximo tutorial, vamos cobrir padrões e ferramentas de autenticação avançados, como usar uma pop-up em vez de um redirecionamento para fazer login de usuários, adicionar permissões ao namespace
oidc
, usar metadados para aprimorar perfis de usuário e muito mais.Deixe-me saber nos comentários abaixo se você gostou deste tutorial. Obrigado por ler este post e fica de olho para mais posts como esse.
About the author
Dan Arias
Staff Developer Advocate
The majority of my engineering work revolves around AWS, React, and Node, but my research and content development involves a wide range of topics such as Golang, performance, and cryptography. Additionally, I am one of the core maintainers of this blog. Running a blog at scale with over 600,000 unique visitors per month is quite challenging!
I was an Auth0 customer before I became an employee, and I've always loved how much easier it is to implement authentication with Auth0. Curious to try it out? Sign up for a free account ⚡️.View profile