close icon
React

Autenticação com React na prática: Usando React Router 6

Aprenda a adicionar autenticação para aplicações React v18 e como integrar Auth0 com o React Router v6 para proteger as páginas e chamar APIs protegidas.

May 16, 2023

Os exemplos do React neste guia se aplicam ao React v18+ e ao React Router v6. Esses exemplos ajudam você a aprender os seguintes conceitos de segurança:

  • Como adicionar login, inscrição e logout de usuário para aplicações React.
  • Como usar funcionalidades novas do React Router v6 para criar guardas de rota para proteger rotas de aplicações React.
  • Como fazer chamadas de API a partir do React para solicitar dados de uma API protegida.
  • Como obter informações de perfil de usuário para personalizar uma interface de usuário React.

Este guia usa o SDK da Auth0 para React que fornece às pessoas desenvolvedoras uma API de alto nível para lidar com muitos detalhes de implementação de autenticação de usuário. Você pode proteger suas aplicações React seguindo as melhores práticas de segurança e ainda escrever menos código.

Se você precisar de orientação sobre como integrar o React Router v5 com a Auth0 para proteger aplicações React, siga o guia "React Authentication By Example: Using React Router 5" (em inglês).

Configuração Rápida Do React

Com a ajuda da Auth0, você não precisa ser especialista em protocolos de identidade, como OAuth 2.0 ou OpenID Connect, para entender como proteger sua stack de aplicações web.

Você começa integrando sua aplicação React com a Auth0. Sua aplicação redirecionará os usuários para uma página de login personalizável sempre que precisarem fazer login. Após seus usuários fazerem login com sucesso, a Auth0 os redirecionará de volta para a sua aplicação React, retornando JSON Web Tokens (JWTs) com informações de autenticação e de usuário.

Obtenha a aplicação React inicial

Criamos um projeto inicial usando create-react-app para te ajudar a aprender os conceitos de segurança do React por meio da prática. Você pode se concentrar em construir componentes React e serviços JavaScript para proteger sua aplicação.

Comece clonando o repositório spa_react_javascript_hello-world_react-router-6 no branch starter:

git clone -b starter git@github.com:auth0-developer-hub/spa_react_javascript_hello-world.git

Depois de clonar o repositório, torne spa_react_javascript_hello-world_react-router-6 seu diretório atual:

cd spa_react_javascript_hello-world

Instale as dependências do projeto React da seguinte forma:

npm install

Este projeto React inicial oferece uma aplicação funcional que consome dados de uma API externa para hidratar a interface do usuário. Para simplicidade e conveniência, o projeto inicial simula a API externa localmente usando json-server. Posteriormente, você integrará esta aplicação React com um servidor de API real usando uma tecnologia de back-end de sua escolha.

O servidor de API compatível é executado em http://localhost:6060 por padrão. Dessa forma, para conectar sua aplicação React com esse servidor de API, crie um arquivo .env no diretório raiz do projeto:

touch .env

Preencha o arquivo .env com as seguintes variáveis de ambiente:

REACT_APP_API_SERVER_URL=http://localhost:6060

Lembre-se de que um projeto React gerado usando a aplicação create-react-app só irá expor variáveis de ambiente de .env ao seu código processado se essas variáveis forem prefixadas com REACT_APP_. Essa prática ajuda a evitar o vazamento acidental das variáveis de ambiente do sistema para a aplicação cliente.

Em seguida, execute o seguinte comando para executar a API do servidor JSON:

npm run api

Por fim, abra outra guia de terminal (ou outra janela) e execute este comando para executar sua aplicação React:

npm start

Tudo pronto para você começar a implementar a autenticação do usuário neste projeto React. Primeiro, você precisará configurar a aplicação React para se conectar com sucesso à Auth0. Posteriormente, você usará o SDK da Auth0 para React para proteger rotas, exibir informações de perfil do usuário e solicitar dados protegidos de um servidor de API externo para hidratar algumas das páginas da aplicação.

Configure o React com a Auth0

Siga as etapas para começar a usar a plataforma de identidade Auth0 rapidamente:

Se inscreva e crie uma Aplicação Auth0

Autenticação para pessoas desenvolvedoras

Obtenha a Auth0 gratuitamente com até 7.000 usuários ativos e logins ilimitados. Não é necessário cartão de crédito. Crie uma conta Auth0 gratuita.

Uma conta gratuita oferece:

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 da aplicação e escolha seu o tipo. Use os seguintes valores:

Nome:

Auth0 React Code Sample

Application Type (Tipo da aplicação):

Single Page 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 React e a Auth0 a se comunicarem.

Qual é a relação entre Auth0 Tenants e aplicações Auth0?

Digamos que você tenha uma aplicação Vue.js de compartilhamento de fotos chamado “Reactigram”. Você então criaria um Auth0 tenant chamado reactigram. Do ponto de vista do cliente, Reactigram é o produto ou serviço desse cliente.

Agora, digamos que o Reactigram 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.

Os usuários do Reactigram pertencem ao tenant Reactigram, que os compartilha em suas aplicações Auth0.

Crie uma ponte de comunicação entre React e Auth0

Ao usar a plataforma de identidade 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 o Login Universal funciona?

Sua aplicação React 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 React. 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, localize a seção “Application URIs” 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 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 fizerem logout.

Origens Web permitidas (Allowed Web Origins em inglês):

http://localhost:4040

Usando o SDK da Auth0 para React, sua aplicação React fará requisições internas a uma URL da Auth0 para lidar com as requisições de autenticação. Você precisa adicionar a URL de origem da aplicação React para evitar problemas de Compartilhamento de recursos de origem cruzada (Cross-Origin Resource Sharing (CORS)).

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 React

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 React use a ponte de comunicação que você criou.

O que exatamente é um domínio Auth0 e um ID de cliente Auth0?

Domínio

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ê irá usar para acessar as APIs Auth0 e a URL que você vai redirecionar os usuários para fazer login:

Auth0 também oferece suporte a domínios personalizados para permitir que a Auth0 faça o trabalho pesado de autenticação para você sem comprometer sua experiência de branding.

ID do Cliente

A Auth0 atribui um ID de cliente (Client ID) a cada aplicação quando criada, 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 Single Page Application (SPA) 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 estiverem 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 Client Secret, poderá se passar pela sua aplicação e acessar recursos protegidos.

Volte para a página da aplicação Auth0 e clique na guia "Settings".

Localize a seção "Basic Information" e siga estas etapas para obter os valores de Auth0 Domain e Auth0 Client ID:

Configurações da aplicação Auth0 para habilitar autenticação de usuário

As variáveis REACT_APP_AUTH0_DOMAIN e REACT_APP_AUTH0_CLIENT_ID permitem que sua aplicação React se identifique como uma parte autorizada para interagir com o servidor de autenticação Auth0.

Agora, atualize o arquivo .env no diretório do projeto React da seguinte forma:

REACT_APP_API_SERVER_URL=http://localhost:6060
REACT_APP_AUTH0_DOMAIN=<AUTH0-DOMAIN>
REACT_APP_AUTH0_CLIENT_ID=<AUTH0-CLIENT-ID>
REACT_APP_AUTH0_CALLBACK_URL=http://localhost:4040/callback

Lembre-se de ajustar preencher os valores REACT_APP_AUTH0_DOMAIN e REACT_APP_AUTH0_CLIENT_ID de acordo com aqueles encontrados respectivamente em "Domain" e "Client ID" na guia "Settings" do Dashboard.

Reinicie seu servidor de desenvolvimento para seu projeto React para saiba dessas alterações no arquivo .env:

npm start

Depois de chegar à seção "Chamar uma API protegida a partir do React" deste guia, você aprenderá como usar REACT_APP_API_SERVER_URL junto com um valor Auth0 Audience para solicitar recursos protegidos de uma API externa que também é protegida por Auth0. Por enquanto, a aplicação está usando json-server para simular a API.

Lide com o comportamento pós-login Auth0

Observe que a URL de retorno de chamada Auth0, REACT_APP_AUTH0_CALLBACK_URL, aponta para http://localhost:4040/callback, que é a URL que Auth0 usa para redirecionar seus usuários após eles efetuarem login com sucesso. Para esta aplicação React, você vai renderizar um componente de uma página simples para a rota /callback.

Crie um arquivo callback-page.js no diretório src/pages:

touch src/pages/callback-page.js

Preencha src/pages/callback-page.js com o seguinte código:

import React from "react";
import { NavBar } from "../components/navigation/desktop/nav-bar";
import { MobileNavBar } from "../components/navigation/mobile/mobile-nav-bar";

export const CallbackPage = () => {
 return (
   <div className="page-layout">
     <NavBar />
     <MobileNavBar />
     <div className="page-layout__content" />
   </div>
 );
};

O componente callback-page.js renderizará apenas a barra de navegação e um contêiner de conteúdo vazio para te ajudar a criar uma transição suave entre uma rota sem conteúdo, /callback, para uma rota com conteúdo, como a página /profile.

A próxima etapa é integrar seu componente callback-page.js com o roteador React.

Localize o arquivo src/app.js, que define as rotas da sua aplicação React usando os componentes <Routes> e <Route> do React Router v6 e atualize-o da seguinte forma:

import React from "react";
import { Route, Routes } from "react-router-dom";
import { AdminPage } from "./pages/admin-page";
import { CallbackPage } from "./pages/callback-page";
import { HomePage } from "./pages/home-page";
import { NotFoundPage } from "./pages/not-found-page";
import { ProfilePage } from "./pages/profile-page";
import { ProtectedPage } from "./pages/protected-page";
import { PublicPage } from "./pages/public-page";

export const App = () => {
 return (
   <Routes>
     <Route path="/" element={<HomePage />} />
     <Route path="/profile" element={<ProfilePage />} />
     <Route path="/public" element={<PublicPage />} />
     <Route path="/protected" element={<ProtectedPage />} />
     <Route path="/admin" element={<AdminPage />} />
     <Route path="/callback" element={<CallbackPage />} />
     <Route path="*" element={<NotFoundPage />} />
   </Routes>
 );
};

Para obter mais detalhes sobre como atualizar do React Router v5 para v6, confira o guia oficial (em inglês).

Quais são os benefícios de usar uma página de callback

A implementação de uma página especializada em lidar com o redirecionamento do usuário da página de login universal da Auth0 para sua aplicação (o evento callback) traz alguns benefícios:

  • Seus usuários não verão nenhum componente piscando na página inicial, que é renderizado no caminho raiz, /.
  • Ao mostrar a barra de navegação na rota /callback, seu usuário pode sentir que sua aplicação React carrega rápido.
  • Ao não mostrar o rodapé, seus usuários podem achar que sua aplicação React carrega sem problemas.
    • Se você renderizar o componente do rodapé, sua aplicação pode parecer instável, pois o rodapé pode aparecer brevemente, mas seria empurrado para baixo quando o conteúdo acima dele fosse carregado.
  • Você pode evitar chamadas de API desnecessárias ou custosas que podem ser executadas ao carregar os componentes da página inicial.

Depois de adicionar um botão de login e logout nesta aplicação, você pode verificar essa melhoria na experiência de usuário usando as ferramentas de desenvolvedor do seu navegador. No caso do Google Chrome, você pode fazer o seguinte:

Se você ainda não se convenceu, vamos explorar mais detalhes sobre o impacto dessa estratégia.

Imagine que você deseja redirecionar seus usuários para o /profile depois que eles fizerem login. Se você fosse usar a URL raiz da sua aplicação React, http://localhost:4040, como o Auth0 Callback URL, você pode prejudicar a experiência do usuário quando a conexão do usuário é lenta ou quando a rota /profile é carregada lentamente:

  • Esta aplicação React oferece uma página /profile que exibirá informações de perfil do usuário, como nome e endereço de e-mail.
  • Como as informações do perfil do usuário são privadas, elas devem ser protegidas contra acesso não autorizado.
  • O SDK da Auth0 para React permite que você exija facilmente que os usuários façam login antes de poder acessar uma rota.
  • Quando um usuário que não está logado clica na aba de navegação da página /profile, a Auth0 irá redirecioná-lo para uma página de login.
  • Depois que seus usuários fizerem login, a Auth0 os redirecionará de volta para sua aplicação React com alguns metadados que permitem que sua aplicação os redirecione para a página protegida que eles pretendem acessar.
  • Quando você usa http://localhost:4040 como a Auth0 Callback URL, a Auth0 redirecionará seus usuários para a página inicial primeiro. Dependendo da rapidez com que sua aplicação renderiza páginas e lida com redirecionamentos, seus usuários podem ver a página inicial antes que o React os leve para a página /profile quando a conexão estiver lenta ou quando você estiver carregando lentamente essa rota. Esse rápido reencaminhamento faz a interface do usuário "piscar", dando a impressão que a interface do usuário é irregular ou apresenta falhas.
  • No entanto, quando você usa http://localhost:4040/callback como Auth0 Callback URL, a Auth0 levará seus usuários a uma rota /callback após o login. Você pode exibir uma animação de carregamento ou nada nessa rota especial. Isso torna a transição de /callback para /profile mais suave, pois nenhum conteúdo não relacionado ou inesperado aparece no processo.

Além disso, ao carregar a página inicial, /, você pode acionar a lógica que busca dados de uma API externa ou executa qualquer outra lógica de negócios relacionada à hidratação da página inicial. Se sua intenção é mostrar aos usuários uma página /profile após eles efetuarem login, não há necessidade ou valor em executar qualquer lógica de negócios da página inicial que não afete a renderização da página /profile. Em vez disso, você pode aumentar seus custos operacionais executando lógica desnecessária quando qualquer um de seus usuários fizer login. Nesse caso, é melhor lidar com o redirecionamento Auth0 em uma rota especializada mínima e de alto desempenho, /callback.

Configure Um Provedor De Autenticação React

Execute o seguinte comando para instalar o SDK da Auth0 para React:

npm install @auth0/auth0-react

Por baixo dos panos, o SDK da Auth0 para React usa o React Context. O SDK usa um componente Auth0Context para gerenciar o estado de autenticação de seus usuários. Por sua vez, o SDK expõe o componente Auth0Provider que fornece esse Auth0Context para seus componentes filhos. Dessa forma, você pode agrupar seu componente raiz, como App, com Auth0Provider para integrar Auth0 com sua aplicação React:

<Auth0Provider>
 <App />
</Auth0Provider>

No entanto, a autenticação do usuário é um mecanismo para controlar quem pode acessar sua aplicação. Você pode integrar sua aplicação com Auth0 para impedir que usuários que não efetuaram login acessem uma rota /profile ou /admin.

Se os usuários quiserem acessar uma rota protegida da sua aplicação, a Auth0 os interromperá e solicitará que apresentem suas credenciais. Se a Auth0 puder verificar quem eles são e se eles devem entrar lá, a Auth0 os deixará entrar.

O processo de autenticação não acontecerá dentro da sua camada de aplicação React ao usar a Auth0. Sua aplicação React redirecionará seus usuários para a página de Login Universal Auth0, onde a Auth0 solicitará credenciais e redirecionará o usuário de volta para sua aplicação com o resultado do processo de autenticação.

O Auth0Provider do SDK da Auth0 para React lembra a rota que o usuário deseja acessar e, se a autenticação for bem-sucedida, leva o usuário a essa rota. Dessa forma, o Auth0Provider precisa ter acesso ao histórico de sessão da aplicação. A aplicação React inicial usa o React Router v6 para gerenciar seu roteamento. O React Router v6 expõe um React Hook que facilita o acesso ao histórico da sessão por meio de um objeto history useNavigate().

No React Router v6, o hook [ substitui o hook useHistory do React Router v6 para acessar o histórico da sessão. Visite o documento "Use useNavigate em vez de useHistory" (em inglês) para obter mais detalhes.

Consequentemente, você precisa agrupar o Auth0Provider com o BrowserRouter do React Router, que usa um componente RouterContext.Provider por baixo dos panos para manter o estado de roteamento:

<BrowserRouter>
 <Auth0Provider>
   <App />
 </Auth0Provider>
</BrowserRouter>

Aqui, o que você vê em jogo é um pilar da arquitetura do React: você estende os componentes, não por herança, mas por composição.

Como você cria um Auth0Provider com acesso ao histórico de sessão da aplicação?

Crie um auth0-provider-with-navigate.js no diretório src para definir um componente Auth0ProviderWithNavigate, que usa composição para disponibilizar React Router Hooks para Auth0Provider:

touch src/auth0-provider-with-navigate.js

Preencha src/auth0-provider-with-navigate.js com o seguinte:

import { Auth0Provider } from "@auth0/auth0-react";
import React from "react";
import { useNavigate } from "react-router-dom";

export const Auth0ProviderWithNavigate = ({ children }) => {
 const navigate = useNavigate();

 const domain = process.env.REACT_APP_AUTH0_DOMAIN;
 const clientId = process.env.REACT_APP_AUTH0_CLIENT_ID;
 const redirectUri = process.env.REACT_APP_AUTH0_CALLBACK_URL;

 const onRedirectCallback = (appState) => {
   navigate(appState?.returnTo || window.location.pathname);
 };

 if (!(domain && clientId && redirectUri)) {
   return null;
 }

 return (
   <Auth0Provider
     domain={domain}
     clientId={clientId}
     authorizationParams={{
       redirect_uri: redirectUri,
     }}
     onRedirectCallback={onRedirectCallback}
   >
     {children}
   </Auth0Provider>
 );
};

O que está acontecendo dentro de Auth0ProviderWithNavigate

  • Você precisa do SDK da Auth0 para React para se conectar com a aplicação Auth0 correta para processar a autenticação. Como tal, você precisa configurar o Auth0Provider para usar o domínio Auth0 e o ID do cliente.
  • Você usa o objeto de configuração authorizationParams para definir os parâmetros de consulta que serão enviados durante a chamada para o endpoint /authorize da Auth0. Dessa forma, você está passando aqui redirect_uri, que é a URL onde a Auth0 redirecionará seus usuários de volta à sua aplicação React.
  • Você usa o método onRedirectCallback() para lidar com o evento em que a Auth0 redireciona seus usuários da página de Login Universal Auth0 para sua aplicação React.
    • Você usa o hook useNavigate() para obter o objeto history do React Router. Você usa o navigate() para levar os usuários de volta à rota que pretendiam acessar antes da autenticação.
    • Nas próximas seções deste guia, você criará botões de login e inscrição que definem o valor da propriedade appState.returnTo. Você irá personalizar o comportamento da experiência de login do usuário especificando para qual rota o React deve levar seus usuários após eles se autenticarem com Auth0.

É isso! Envolver qualquer árvore de componentes com Auth0ProviderWithNavigate dará a ela acesso ao Auth0Context.

Como você usa Auth0ProviderWithNavigate?

O Auth0ProviderWithNavigate requer que o componente BrowserRouter do React Router seja seu pai, avô ou tataravô.

O Context do React Router deve estar presente na árvore de componentes em um nível superior para Auth0ProviderWithNavigate acessar o hook useNavigate() do React Router.

Abra src/index.js e atualize-o da seguinte forma para construir a árvore de componentes adequada para alimentar os recursos de roteamento e autenticação do usuário da sua aplicação React:

import React from "react";
import { createRoot } from "react-dom/client";
import { BrowserRouter } from "react-router-dom";
import { App } from "./app";
import { Auth0ProviderWithNavigate } from "./auth0-provider-with-navigate";
import "./styles/styles.css";

const container = document.getElementById("root");
const root = createRoot(container);

root.render(
 <React.StrictMode>
   <BrowserRouter>
     <Auth0ProviderWithNavigate>
       <App />
     </Auth0ProviderWithNavigate>
   </BrowserRouter>
 </React.StrictMode>
);

Se você é uma pessoa nova no React v18, saiba mais sobre como a nova API root funciona lendo o documento link_title "Atualizações sobre renderizar APIs Clientes" (em inglês).

Nas próximas seções, você usará o hook useAuth0() em qualquer componente React para consumir o Auth0Context associado ao Auth0ProviderWithNavigate. O hook useAuth0() lhe dará acesso ao estado de carregamento do SDK da Auth0 para React, ao status de autenticação do usuário, às informações do perfil do usuário e aos métodos auxiliares que acionam eventos relacionados ao processo de autenticação.

Conexão Auth0 e React

Você concluiu a configuração de um serviço de autenticação que sua aplicação React pode consumir. Continue construindo o projeto inicial ao longo deste guia, implementando componentes React 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.

Adicione Login De Usuário Para React

As etapas de como construir um formulário de login React ou página de login são complexas. Você pode economizar tempo de desenvolvimento usando uma página de login hospedada pela Auth0 que possui um formulário de login integrado que oferece suporte a diferentes tipos de autenticação de usuário: nome de usuário e senha, login social e autenticação multifator (MFA). Você só precisa criar um botão que leve as pessoas usuárias da sua aplicação React para a página de login.

Comece criando um diretório buttons no diretório src/components:

mkdir src/components/buttons

Crie um arquivo login-button.js no diretório src/components/buttons:

touch src/components/buttons/login-button.js

Preencha o arquivo src/components/buttons/login-button.js assim:

import { useAuth0 } from "@auth0/auth0-react";
import React from "react";

export const LoginButton = () => {
 const { loginWithRedirect } = useAuth0();

 const handleLogin = async () => {
   await loginWithRedirect({
     appState: {
       returnTo: "/profile",
     },
   });
 };

 return (
   <button className="button__login" onClick={handleLogin}>
     Log In
   </button>
 );
};

O método loginWithRedirect() de Auth0Context executa um redirecionamento para o endpoint Auth0 /authorize para iniciar o processo de autenticação. Você pode passar um objeto de configuração para esse método para personalizar a experiência de login.

Ao configurar o valor de appState.returnTo para /profile, você está informando ao SDK da Auth0 para React o seguinte: Quando meus usuários fizerem login com a Auth0 e retornarem à minha aplicação React, leve-os do caminho da URL de callback padrão, /callback, para a página "Profile", /profile. Se você não especificar esta opção appState.returnTo, seus usuários serão redirecionados por padrão para o caminho / após efetuarem login.

Este método loginWithRedirect() oferece suporte a qualquer uma das propriedades RedirectLoginOptions para personalizar a experiência de login do usuário. Na próxima seção, você vai configurar esse método para criar um botão no qual seus usuários podem clicar para se inscrever na sua aplicação.

Adicione Inscrição De Usuário Ao React

O processo de como construir um formulário de inscrição React é muito mais complexo. No entanto, você pode usar um formulário de inscrição hospedado pela Auth0 que possui uma verificação de força de senha integrada.

Você pode criar um botão que leve os usuários da sua aplicação React para a página de inscrição adicionando outra propriedade ao objeto de configuração loginWithRedirect(): authorizationParams. O SDK da Auth0 para React usará as propriedades definidas no objeto authorizationParams como parâmetros de consulta da chamada para o endpoint Auth0 /authorize. Dessa forma, adicione a propriedade screen_hint a esse objeto com um valor de signup para atingir esse objetivo:

authorizationParams: {
 screen_hint: "signup",
}

Para observar isso na prática, crie um arquivo signup-button.js dentro do diretório src/components/buttons:

touch src/components/buttons/signup-button.js

Preencha src/components/buttons/signup-button.js dessa forma para definir um componente botão de inscrição:

import { useAuth0 } from "@auth0/auth0-react";
import React from "react";

export const SignupButton = () => {
 const { loginWithRedirect } = useAuth0();

 const handleSignUp = async () => {
   await loginWithRedirect({
     appState: {
       returnTo: "/profile",
     },
     authorizationParams: {
       screen_hint: "signup",
     },
   });
 };

 return (
   <button className="button__sign-up" onClick={handleSignUp}>
     Sign Up
   </button>
 );
};

O uso do recurso de inscrição exige que você ative o Auth0 New Universal Login Experience em seu tenant.

Abra a seção Login Universal do dashboard Auth0 e escolha a opção "New" na subseção "Experience".

opções da Auth0 Universal Login Experience

Role para baixo e clique no botão "Save Changes".

A diferença entre a experiência de usuário em login e inscrição ficará mais evidente quando você integrar esses componentes à aplicação React e vê-los em ação. Você fará isso nas próximas seções.

Adicione Logout De Usuário Para O React

Crie um arquivo logout-button.js no diretório src/components/buttons:

touch src/components/buttons/logout-button.js

Preencha src/components/buttons/logout-button.js assim:

import { useAuth0 } from "@auth0/auth0-react";
import React from "react";

export const LogoutButton = () => {
 const { logout } = useAuth0();

 const handleLogout = () => {
   logout({
     logoutParams: {
       returnTo: window.location.origin,
     },
   });
 };

 return (
   <button className="button__logout" onClick={handleLogout}>
     Log Out
   </button>
 );
};

Ao usar o método logout(), o SDK da Auth0 para React limpa a sessão da aplicação e redireciona para o endpoint Auth0 /v2/logout para limpar a sessão Auth0 por baixo dos panos.

Assim como nos métodos de login, você pode passar um argumento de objeto para logout() para customizar o comportamento ao desconectar o usuário na aplicação React. Você pode definir a propriedade logoutParams no objeto de configuração para definir parâmetros da chamada /v2/logout. Este processo é bastante invisível para o usuário. Consulte LogoutParams (em inglês) para obter mais detalhes sobre os parâmetros disponíveis.

Aqui, você passa a opção logoutParams.returnTo para especificar a URL onde a 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ê fosse fazer o deploy da sua aplicação React para produção, você precisa adicionar a URL de saída 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 localhost. Definir logoutParams.returnTo como window.location.origin fará exatamente isso.

Uma prática recomendada ao trabalhar com Auth0 é ter tenants diferentes para seus diferentes ambientes de projeto. Por exemplo, é recomendável que os desenvolvedores especifiquem um tenant de produção. Um tenant de produção obtém limites de taxa mais altos do que os tenants que não são de produção. Confira o documento Auth0 "Configurar vários ambientes" (em inglês) para saber mais sobre como configurar ambientes de desenvolvimento, staging e produção na plataforma de identidade Auth0.

Renderize Componentes React Com Base Na Autenticação

Nesta seção, você aprenderá como renderizar componentes React condicionalmente com base no status do SDK da Auth0 para React ou no status de autenticação de seus usuários.

Renderize os botões de autenticação condicionalmente

A aplicação inicial React apresenta uma experiência de navegação em desktop e móvel.

Ao usar sua aplicação React em uma viewport grande o suficiente para corrigir uma experiência de desktop ou tablet, você verá uma barra de navegação na parte superior da página.

Ao usar uma viewport que se ajusta às restrições de tela de um dispositivo móvel, você verá um botão de menu no canto superior direito da página. Tocar ou clicar no botão de menu abre um modal que mostra as diferentes páginas que você pode acessar na aplicação.

Nesta seção, você irá expor os componentes do botão que acionam os eventos de login, inscrição e logout por meio desses elementos de navegação da página.

Vamos começar com a experiência do usuário de navegação na área de trabalho. Você mostrará os botões de login e inscrição na barra de navegação quando o usuário não estiver logado. Naturalmente, você mostrará o botão de logout quando o usuário estiver logado.

Atualize o arquivo src/components/navigation/desktop/nav-bar-buttons.js da seguinte maneira para implementar a experiência do usuário definida acima:

import { useAuth0 } from "@auth0/auth0-react";
import React from "react";
import { LoginButton } from "../../buttons/login-button";
import { LogoutButton } from "../../buttons/logout-button";
import { SignupButton } from "../../buttons/signup-button";

export const NavBarButtons = () => {
 const { isAuthenticated } = useAuth0();

 return (
   <div className="nav-bar__buttons">
     {!isAuthenticated && (
       <>
         <SignupButton />
         <LoginButton />
       </>
     )}
     {isAuthenticated && (
       <>
         <LogoutButton />
       </>
     )}
   </div>
 );
};

O valor isAuthenticated reflete o estado de autenticação de seus usuários conforme rastreado pelo SDK da Auth0 para React. Esse valor é true quando o usuário foi autenticado e false quando não. Dessa forma, você pode usar o valor isAuthenticated para renderizar elementos de IU condicionalmente, dependendo do estado de autenticação de seus usuários, como você fez acima.

A experiência de navegação móvel funciona da mesma maneira, exceto que os botões relacionados à autenticação estão inseridos no modal do menu móvel.

Atualize src/components/navigation/mobile/mobile-nav-bar-buttons.js assim:

import { useAuth0 } from "@auth0/auth0-react";
import React from "react";
import { LoginButton } from "../../buttons/login-button";
import { LogoutButton } from "../../buttons/logout-button";
import { SignupButton } from "../../buttons/signup-button";

export const MobileNavBarButtons = () => {
 const { isAuthenticated } = useAuth0();

 return (
   <div className="mobile-nav-bar__buttons">
     {!isAuthenticated && (
       <>
         <SignupButton />
         <LoginButton />
       </>
     )}
     {isAuthenticated && (
       <>
         <LogoutButton />
       </>
     )}
   </div>
 );
};

Vá em frente e tente fazer o login. Sua aplicação React 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.

Formulário da nova experiência do Login Universal Auth0

No entanto, quando você clica no botão de inscrição diretamente em sua aplicação, o React leva você para a página de inscrição, onde seus usuários podem se inscrever na aplicação React. Experimente!

Nova página de inscrição na Experiência de Login Universal Auth0

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 .

Observe que, quando você termina de fazer login ou de se inscrever, a Auth0 redireciona você para sua aplicação React, mas os botões de login e inscrição podem aparecer brevemente antes do botão de logout renderizar. Você vai consertar isso já já.

Renderize a aplicação condicionalmente

A interface do usuário "pisca" porque sua aplicação React não sabe se a Auth0 já autenticou o usuário. Sua aplicação saberá o status de autenticação do usuário depois que o SDK da Auth0 para React for carregado.

Para corrigir a intermitência da interface de usuário (UI), use o valor isLoading do hook React useAuth0() para renderizar o componente App assim que o SDK da Auth0 para React terminar de carregar.

Abra o arquivo src/app.vue e atualize dessa forma:

import { useAuth0 } from "@auth0/auth0-react";
import React from "react";
import { Route, Routes } from "react-router-dom";
import { PageLoader } from "./components/page-loader";
import { AdminPage } from "./pages/admin-page";
import { CallbackPage } from "./pages/callback-page";
import { HomePage } from "./pages/home-page";
import { NotFoundPage } from "./pages/not-found-page";
import { ProfilePage } from "./pages/profile-page";
import { ProtectedPage } from "./pages/protected-page";
import { PublicPage } from "./pages/public-page";

export const App = () => {
 const { isLoading } = useAuth0();

 if (isLoading) {
   return (
     <div className="page-layout">
       <PageLoader />
     </div>
   );
 }

 return (
   <Routes>
     <Route path="/" element={<HomePage />} />
     <Route path="/profile" element={<ProfilePage />} />
     <Route path="/public" element={<PublicPage />} />
     <Route path="/protected" element={<ProtectedPage />} />
     <Route path="/admin" element={<AdminPage />} />
     <Route path="/callback" element={<CallbackPage />} />
     <Route path="*" element={<NotFoundPage />} />
   </Routes>
 );
};

Enquanto o SDK está carregando, o componente PageLoader é renderizado, o que mostra uma animação. Faça logout e login novamente para ver isso em ação. A “piscada” na interface do usuário não deve mais acontecer.

Renderize guias de navegação condicionalmente

Pode haver casos de uso em que você deseja ocultar elementos da interface do usuário para aqueles usuários que não efetuaram login em sua aplicação. Para esta aplicação inicial, apenas usuários autenticados devem ver as guias de navegação para acessar as páginas /protected e /admin.

Para implementar esse caso de uso, você contará novamente com o valor isAuthenticated do hook useAuth0().

Abra o arquivo do componente src/components/navigation/desktop/nav-bar-tabs.js que define as guias de navegação da área de trabalho e atualize-o da seguinte forma:

import { useAuth0 } from "@auth0/auth0-react";
import React from "react";
import { NavBarTab } from "./nav-bar-tab";

export const NavBarTabs = () => {
 const { isAuthenticated } = useAuth0();

 return (
   <div className="nav-bar__tabs">
     <NavBarTab path="/profile" label="Profile" />
     <NavBarTab path="/public" label="Public" />
     {isAuthenticated && (
       <>
         <NavBarTab path="/protected" label="Protected" />
         <NavBarTab path="/admin" label="Admin" />
       </>
     )}
   </div>
 );
};

Em seguida, abra o arquivo do componente src/components/navigation/desktop/mobile-nav-bar-tabs.js que define suas guias de navegação móvel e atualize-o da seguinte forma:

import { useAuth0 } from "@auth0/auth0-react";
import React from "react";
import { MobileNavBarTab } from "./mobile-nav-bar-tab";

export const MobileNavBarTabs = ({ handleClick }) => {
 const { isAuthenticated } = useAuth0();

 return (
   <div className="mobile-nav-bar__tabs">
     <MobileNavBarTab
       path="/profile"
       label="Profile"
       handleClick={handleClick}
     />
     <MobileNavBarTab
       path="/public"
       label="Public"
       handleClick={handleClick}
     />
     {isAuthenticated && (
       <>
         <MobileNavBarTab
           path="/protected"
           label="Protected"
           handleClick={handleClick}
         />
         <MobileNavBarTab
           path="/admin"
           label="Admin"
           handleClick={handleClick}
         />
       </>
     )}
   </div>
 );
};

Saia de sua aplicação React e observe como agora você só pode ver as guias das páginas /profile e /public na barra de navegação, juntamente com os botões de login e inscrição. Faça o login e veja o resto da barra de navegação aparecer.

Lembre-se de que isso não restringe o acesso às páginas /admin e /protected. Você aprenderá como usar o SDK da Auth0 para React para proteger rotas React na próxima seção.

Adicione Guardas De Rota Ao React

Você criará um componente <AuthenticationGuard> que exige que os usuários efetuem login antes de poderem acessar uma rota do React. Um guarda é uma ferramenta que ajuda a promover a privacidade e proteção de dados, bem como a personalização da interface do usuário. O <AuthenticationGuard> é um componente wrapper que usa withAuthenticationRequired para torná-lo reutilizável para os componentes que você precisa proteger. Dessa forma, você pode passar o <AuthenticationGuard> organicamente como um elemento para o componente <Route> do React Router v6.

Para obter orientação sobre como integrar o React Router v5 com a Auth0 para proteger aplicações React, siga o guia "React Authentication By Example: Using React Router 5" (em inglês).

Para começar, crie um arquivo authentication-guard.js no diretório src/components/:

touch src/components/authentication-guard.js

Preencha src/components/authentication-guard.js assim:

import { withAuthenticationRequired } from "@auth0/auth0-react";
import React from "react";
import { PageLoader } from "./page-loader";

export const AuthenticationGuard = ({ component }) => {
 const Component = withAuthenticationRequired(component, {
   onRedirecting: () => (
     <div className="page-layout">
       <PageLoader />
     </div>
   ),
 });

 return <Component />;
};

O withAuthenticationRequired Higher-Order Component (HOC) aceita os seguintes argumentos:

  • O componente que você quer proteger.
    • Um objeto de configuração para personalizar o fluxo de autenticação, WithAuthenticationRequiredOptions. Este objeto tem as seguintes propriedades opcionais:
      • loginOptions: Ele se comporta exatamente como as opções de configuração que você pode passar para loginWithRedirect() para personalizar a experiência de login.
      • returnTo: permite especificar um caminho para o React redirecionar um usuário após a conclusão da transação de login que o usuário acionou neste componente.
      • onRedirecting: renderiza um componente enquanto sua aplicação React redireciona o usuário para a página de login.

No exemplo acima, os usuários que não efetuaram login veem o componente <PageLoader> assim que chegam em uma rota protegida. O componente onRedirecting melhora a experiência do usuário evitando qualquer flash de componentes da interface do usuário (componentes públicos e protegidos).

Você pode aplicar o guarda de rota a qualquer rota do React atualizando src/app.js da seguinte maneira:

import { useAuth0 } from "@auth0/auth0-react";
import React from "react";
import { Route, Routes } from "react-router-dom";
import { PageLoader } from "./components/page-loader";
import { AuthenticationGuard } from "./components/authentication-guard";
import { AdminPage } from "./pages/admin-page";
import { CallbackPage } from "./pages/callback-page";
import { HomePage } from "./pages/home-page";
import { NotFoundPage } from "./pages/not-found-page";
import { ProfilePage } from "./pages/profile-page";
import { ProtectedPage } from "./pages/protected-page";
import { PublicPage } from "./pages/public-page";

export const App = () => {
 const { isLoading } = useAuth0();

 if (isLoading) {
   return (
     <div className="page-layout">
       <PageLoader />
     </div>
   );
 }

 return (
   <Routes>
     <Route path="/" element={<HomePage />} />
     <Route
       path="/profile"
       element={<AuthenticationGuard component={ProfilePage} />}
     />
     <Route path="/public" element={<PublicPage />} />
     <Route
       path="/protected"
       element={<AuthenticationGuard component={ProtectedPage} />}
     />
     <Route
       path="/admin"
       element={<AuthenticationGuard component={AdminPage} />}
     />
     <Route path="/callback" element={<CallbackPage />} />
     <Route path="*" element={<NotFoundPage />} />
   </Routes>
 );
};

Você usa o componente <AuthenticationGuard> para proteger as rotas /profile, /protected e /admin.

Agora você pode testar se esses caminhos protegidos exigem que os usuários façam login antes de acessá-los. Faça logout e tente acessar as páginas Profile, Protected ou Admin. Se funcionar, o React redireciona você para fazer login com Auth0.

Depois de fazer login, o React deve levá-lo à página /profile conforme especificado pela propriedade appState.returnTo presente na definição do componente do botão de login.

Uma nota sobre React.StrictMode e React v18

Ao executar este exemplo de código React v18 localmente no modo de desenvolvimento, você vai perceber que, em alguns cenários, o React faz a mesma chamada de API duas vezes. Abra as ferramentas de desenvolvedor do seu navegador para analisar o tráfego de rede e as chamadas. Em seguida, visite a página /public, a página /protected ou a página /admin. Você verá que o React chama sua API "Hello World" duas vezes.

React está funcionando como esperado. Não há nada de errado acontecendo. O React v18 torna o React mais rigoroso, introduzindo uma nova verificação somente de desenvolvimento para React.StrictMode, que esta aplicação de exemplo de código usa.

O changelog do React v18 explica que "React desmontará e remontará automaticamente todos os componentes, sempre que um componente for montado pela primeira vez, restaurando o estado anterior na segunda montagem. Se isso quebrar a sua aplicação, considere remover o Strict Mode até que você possa consertar os componentes para ser resiliente à remontagem com o estado existente."

No entanto, quando você executa suas aplicações React v18 em produção, o React fará apenas uma solicitação.

Os protetores do lado do cliente melhoram a experiência do usuário em sua aplicação React, não sua segurança.

No Security StackExchange, Conor Mancone explica que as proteções do lado do servidor visam proteger os dados, enquanto as proteções do lado do cliente visam melhorar a experiência do usuário.

As principais conclusões de sua resposta são:

  • Você não pode confiar em restrições do lado do cliente, como protetores de navegação e rotas protegidas, para proteger informações confidenciais.
    • Os invasores podem eventualmente contornar as restrições do lado do cliente.
  • Seu servidor não deve retornar nenhum dado que um usuário não deva acessar. A abordagem errada é retornar todos os dados do usuário do servidor e deixar o framework de front-end decidir o que exibir e o que ocultar com base no status de autenticação do usuário.
    • Qualquer pessoa pode abrir as ferramentas para pessoas desenvolvedoras do navegador e inspecionar as solicitações de rede para visualizar todos os dados.
  • O uso de guardas de navegação ajuda a melhorar a experiência do usuário, não a segurança do usuário.
    • Sem guardas, um usuário que não fez login pode entrar em uma página com informações restritas e ver um erro, como "Acesso negado".
    • Com guardas que correspondem às permissões do servidor, você pode impedir que os usuários vejam erros impedindo-os de visitar a página restrita.

Obtenha Informações De Perfil De Usuário No React

Depois que um usuário efetua login com sucesso, a Auth0 envia um ID token para sua aplicação React. 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 cliente. O armazenamento em cache de ID tokens pode contribuir para melhorias no desempenho e capacidade de resposta da sua aplicação React.

Você pode usar os dados do ID token para personalizar a interface do usuário da sua aplicação React. O SDK da Auth0 para React decodifica o ID token e armazena seus dados através do objeto user exposto pelo método useAuth0(). Algumas das informações do ID token incluem o nome, apelido, imagem e e-mail do usuário conectado.

Como você pode usar o ID token para criar uma página de perfil para seus usuários?

Atualize src/pages/profile-page.js assim:

import { useAuth0 } from "@auth0/auth0-react";
import React from "react";
import { CodeSnippet } from "../components/code-snippet";
import { PageLayout } from "../components/page-layout";

export const ProfilePage = () => {
 const { user } = useAuth0();

 if (!user) {
   return null;
 }

 return (
   <PageLayout>
     <div className="content-layout">
       <h1 id="page-title" className="content__title">
         Profile Page
       </h1>
       <div className="content__body">
         <p id="page-description">
           <span>
             You can use the <strong>ID Token</strong> to get the profile
             information of an authenticated user.
           </span>
           <span>
             <strong>Only authenticated users can access this page.</strong>
           </span>
         </p>
         <div className="profile-grid">
           <div className="profile__header">
             <img
               src={user.picture}
               alt="Profile"
               className="profile__avatar"
             />
             <div className="profile__headline">
               <h2 className="profile__title">{user.name}</h2>
               <span className="profile__description">{user.email}</span>
             </div>
           </div>
           <div className="profile__details">
             <CodeSnippet
               title="Decoded ID Token"
               code={JSON.stringify(user, null, 2)}
             />
           </div>
         </div>
       </div>
     </div>
   </PageLayout>
 );
};

O que está acontecendo no componente <ProfilePage>?

  • Você exibe três propriedades do objeto user na interface do usuário: name, picture, e email.
  • Como os dados vêm de um objeto simples, você não precisa buscá-los usando nenhuma chamada assíncrona.
  • Por fim, você exibe o conteúdo completo do ID token decodificado em uma caixa de código. Agora você pode ver todas as outras propriedades disponíveis para você usar. As propriedades são conhecidas como "token claims" (atributos de token).

O componente <ProfilePage> processa informações do usuário que você pode considerar privadas ou confidenciais. Além disso, a propriedade do user é null se não houver nenhum usuário conectado. De qualquer forma, esse componente só deve renderizar se Auth0 tiver autenticado o usuário. Você já está restringindo o acesso a este componente de página usando o <AuthenticationGuard> para proteger a definição de rota /profile da sua aplicação React, src/app.js.

Se você estiver conectado à sua aplicação, visite http://localhost:4040/profile para ver os detalhes do seu perfil de usuário.

Integre O React Com Um Servidor De API

Esta seção se concentra em mostrar como obter um access token em sua aplicação React e como usá-lo para fazer chamadas de API para endpoints de API 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 React. No entanto, sua aplicação pode precisar acessar recursos protegidos de uma API.

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 seguras a partir do React?

Sua aplicação React 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 o fluxo de autenticação e autorização entre o cliente e o servidor, você pode emparelhar essa aplicação cliente com um servidor de API que corresponda à stack de tecnologia que você usa no trabalho. A aplicação cliente React "Hello World" que você construiu pode interagir com qualquer uma das amostras de servidor da API "Hello World" do Auth0 Developer Center.

As amostras do servidor API "Hello World" são executadas em http://localhost:6060 por padrão, que é a mesma URL de origem e porta em que o servidor JSON simulado está sendo executado. Assim, antes de configurar o servidor da API "Hello World", localize a guia onde você está executando o comando npm run api e interrompa o servidor JSON simulado.

Escolha um exemplo de código de API no seu framework back-end preferido na lista abaixo e siga as instruções na página de exemplo de código para configurá-lo. Depois de concluir a configuração do servidor de API de exemplo, retorne a esta página para aprender como integrar esse servidor de API com sua aplicação React (os exemplos listados abaixo estão em inglês).

Chame Uma API Protegida Do React

Depois de configurar a amostra de código do servidor API, você deve ter criado um valor Auth0 Audience. Agora, atualize o arquivo .env no diretório do projeto React assim e coloque o valor do Auth0 Audience na variável nova:

REACT_APP_API_SERVER_URL=http://localhost:6060
REACT_APP_AUTH0_DOMAIN=<AUTH0-DOMAIN>
REACT_APP_AUTH0_CLIENT_ID=<AUTH0-CLIENT-ID>
REACT_APP_AUTH0_CALLBACK_URL=http://localhost:4040/callback
REACT_APP_AUTH0_AUDIENCE=<AUTH0-AUDIENCE>

Você está usando REACT_APP_AUTH0_AUDIENCE para adicionar o valor de sua Auth0 Audience para que sua aplicação cliente React possa solicitar recursos da API que esse valor de audiência representa.

Reinicie seu servidor de desenvolvimento para que seu projeto React possa tomar conhecimento dessas alterações no arquivo .env:

npm start

Vamos entender melhor o que representam os valores REACT_APP_AUTH0_AUDIENCE e REACT_APP_API_SERVER_URL.

O REACT_APP_API_SERVER_URL é simplesmente a URL onde seu servidor de API de exemplo atende às requisições. Em produção, você irá alterar esse valor para a URL do seu servidor ativo.

Sua aplicação React deve passar um token de acesso quando chama uma API de destino para acessar recursos protegidos. Você pode solicitar um token de acesso em um formato que a API possa verificar passando o audience para o SDK da Auth0 para React.

O valor de Auth0 Audience deve ser o mesmo para a aplicação cliente React e o servidor da API que você decidiu configurar.

E por que o valor Auth0 Audience é o mesmo para ambas as aplicações? A Auth0 usa o valor audience para determinar qual servidor de recurso (API) o usuário está autorizando o acesso da aplicação React. É como um número de telefone. Você deseja garantir que sua aplicação React "envie mensagem para a API correta".

Assim, atualize o arquivo src/auth0-provider-with-navigate.js de seu projeto React da seguinte maneira para adicionar o campo audience:

import { Auth0Provider } from "@auth0/auth0-react";
import React from "react";
import { useNavigate } from "react-router-dom";

export const Auth0ProviderWithNavigate = ({ children }) => {
 const navigate = useNavigate();

 const domain = process.env.REACT_APP_AUTH0_DOMAIN;
 const clientId = process.env.REACT_APP_AUTH0_CLIENT_ID;
 const redirectUri = process.env.REACT_APP_AUTH0_CALLBACK_URL;
 const audience = process.env.REACT_APP_AUTH0_AUDIENCE;

 const onRedirectCallback = (appState) => {
   navigate(appState?.returnTo || window.location.pathname);
 };

 if (!(domain && clientId && redirectUri && audience)) {
   return null;
 }

 return (
   <Auth0Provider
     domain={domain}
     clientId={clientId}
     authorizationParams={{
       audience: audience,
       redirect_uri: redirectUri,
     }}
     onRedirectCallback={onRedirectCallback}
   >
     {children}
   </Auth0Provider>
 );
};

Agora você está incluindo uma propriedade audience no authorizationParams no Auth0Provider.

Que tal usar escopos?

Uma propriedade que você não está configurando diretamente no método <Auth0Provider> é a propriedade scope. Quando você não passa uma opção scope para o SDK da Auth0 para React, que ativa Auth0Provider , o SDK por padrão usa os escopos do OpenID Connect: openid profile email.

  • openid: Este escopo informa ao servidor de autorização Auth0 que o cliente está fazendo uma requisição OpenID Connect para verificar a identidade do usuário. OpenID Connect é um protocolo de autenticação.
  • profile: este valor de escopo requer acesso às informações de perfil padrão do usuário, como name, nickname e picture.
  • email: este valor de escopo requer acesso às informações de email e 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 identifica nas chamadas que suas aplicações clientes fazem para essa API. A 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".

O SDK da Auth0 para React fornece um método para obter um token de acesso da Auth0: getAccessTokenSilently(). Se você já possui um token de acesso armazenado na memória, mas o token é inválido ou expirou, este método fornecerá um novo. Normalmente, obter novos tokens de acesso exige que o usuário faça login novamente. No entanto, o SDK da Auth0 para React permite que você obtenha um em segundo plano sem interromper o usuário. Como o nome indica, é um método para conseguir um token silenciosamente getTokenSilently()... 🤫😶

Agora é hora de atualizar as páginas /protected e /admin para permitir que os usuários recuperem dados privados do servidor da API. Certifique-se de que seu servidor da API de exemplo esteja em execução ao concluir as etapas a seguir

Comece atualizando os métodos de serviço presentes no arquivo src/services/message.service.js da seguinte forma:

import { callExternalApi } from "./external-api.service";

const apiServerUrl = process.env.REACT_APP_API_SERVER_URL;

export const getPublicResource = async () => {
 const config = {
   url: `${apiServerUrl}/api/messages/public`,
   method: "GET",
   headers: {
     "content-type": "application/json",
   },
 };

 const { data, error } = await callExternalApi({ config });

 return {
   data: data || null,
   error,
 };
};

export const getProtectedResource = async (accessToken) => {
 const config = {
   url: `${apiServerUrl}/api/messages/protected`,
   method: "GET",
   headers: {
     "content-type": "application/json",
     Authorization: `Bearer ${accessToken}`,
   },
 };

 const { data, error } = await callExternalApi({ config });

 return {
   data: data || null,
   error,
 };
};

export const getAdminResource = async (accessToken) => {
 const config = {
   url: `${apiServerUrl}/api/messages/admin`,
   method: "GET",
   headers: {
     "content-type": "application/json",
     Authorization: `Bearer ${accessToken}`,
   },
 };

 const { data, error } = await callExternalApi({ config });

 return {
   data: data || null,
   error,
 };
};

Você está alterando a assinatura dos métodos getProtectedResource() e getAdminResource() para incluir um parâmetro accessToken.

Em seguida, você passa o valor accessToken como uma credencial de portador no cabeçalho de autorização do objeto config da requisição. Você faz requisições de sua aplicação React usando o método auxiliar callExternalApi() definido no módulo src/services/external-api.service.js. callExternalApi() usa axios para fazer suas chamadas de API.

Com os métodos de serviço de mensagens em vigor, prossiga para atualizar o src/pages/protected-page.vue da seguinte forma:

import { useAuth0 } from "@auth0/auth0-react";
import React, { useEffect, useState } from "react";
import { CodeSnippet } from "../components/code-snippet";
import { PageLayout } from "../components/page-layout";
import { getProtectedResource } from "../services/message.service";

export const ProtectedPage = () => {
 const [message, setMessage] = useState("");

 const { getAccessTokenSilently } = useAuth0();

 useEffect(() => {
   let isMounted = true;

   const getMessage = async () => {
     const accessToken = await getAccessTokenSilently();
     const { data, error } = await getProtectedResource(accessToken);

     if (!isMounted) {
       return;
     }

     if (data) {
       setMessage(JSON.stringify(data, null, 2));
     }

     if (error) {
       setMessage(JSON.stringify(error, null, 2));
     }
   };

   getMessage();

   return () => {
     isMounted = false;
   };
 }, [getAccessTokenSilently]);

 return (
   <PageLayout>
     <div className="content-layout">
       <h1 id="page-title" className="content__title">
         Protected Page
       </h1>
       <div className="content__body">
         <p id="page-description">
           <span>
             This page retrieves a <strong>protected message</strong> from an
             external API.
           </span>
           <span>
             <strong>Only authenticated users can access this page.</strong>
           </span>
         </p>
         <CodeSnippet title="Protected Message" code={message} />
       </div>
     </div>
   </PageLayout>
 );
};

O que está acontecendo agora dentro do componente <ProtectedPage>?

  • Você chama o método getMessage() para solicitar dados de seu servidor de API para hidratar sua página.
  • Dentro do corpo do método getMessage(), você chama o método assíncrono async getAccessTokenSilently() para buscar um novo token de acesso do servidor de autorização Auth0. Por baixo dos panos, o SDK da Auth0 para React faz uma chamada para o endpoint da Auth0 /oauth/token.
    • Sua requisição de login anterior não incluiu um parâmetro audience<. Dessa forma, o SDK da Auth0 para React não possui um token de acesso armazenado na memória e solicita um novo.
    • O SDK agora armazenará esse token de acesso na memória. Para futuras chamadas de getAccessTokenSilently(), o SDK usará o token de acesso armazenado e só solicitará um novo quando o token de acesso armazenado expirar.
  • Em seguida, use o método de serviço getProtectedResource() para buscar a mensagem protegida do seu servidor de API.
    • Você passa o token de acesso obtido para esse método de serviço.
    • Por sua vez, getProtectedResource() passa esse token de acesso como uma credencial de portador no cabeçalho de autorização da requisição que faz ao seu servidor de API.
  • Por fim, se você recuperar os dados do servidor corretamente, exibirá os dados da mensagem na caixa de mensagens. Caso contrário, você mostrará a mensagem de erro correspondente.

Faça logout e login novamente para obter um novo token de acesso da Auth0 que inclui as informações de audiência.

Visite a página http://localhost:4040/protected e verifique se você obteve uma resposta válida do servidor.

Agora, atualize o componente src/pages/admin-page.js para implementar a mesma lógica de negócios descrita anteriormente, mas desta vez usando o método de serviço getAdminResource() dentro do método getMessage() para recuperar a mensagem correta:

import { useAuth0 } from "@auth0/auth0-react";
import React, { useEffect, useState } from "react";
import { CodeSnippet } from "../components/code-snippet";
import { PageLayout } from "../components/page-layout";
import { getAdminResource } from "../services/message.service";

export const AdminPage = () => {
 const [message, setMessage] = useState("");

 const { getAccessTokenSilently } = useAuth0();

 useEffect(() => {
   let isMounted = true;

   const getMessage = async () => {
     const accessToken = await getAccessTokenSilently();
     const { data, error } = await getAdminResource(accessToken);

     if (!isMounted) {
       return;
     }

     if (data) {
       setMessage(JSON.stringify(data, null, 2));
     }

     if (error) {
       setMessage(JSON.stringify(error, null, 2));
     }
   };

   getMessage();

   return () => {
     isMounted = false;
   };
 }, [getAccessTokenSilently]);

 return (
   <PageLayout>
     <div className="content-layout">
       <h1 id="page-title" className="content__title">
         Admin Page
       </h1>
       <div className="content__body">
         <p id="page-description">
           <span>
             This page retrieves an <strong>admin message</strong> from an
             external API.
           </span>
           <span>
             <strong>
               Only authenticated users with the{" "}
               <code>read:admin-messages</code> permission should access this
               page.
             </strong>
           </span>
         </p>
         <CodeSnippet title="Admin Message" code={message} />
       </div>
     </div>
   </PageLayout>
 );
};

Isso é tudo o que é necessário para integrar o React com um servidor de API externo que também é protegido pela Auth0 e usar um token de acesso para consumir recursos de servidor protegidos da sua aplicação cliente React.

Próximos Passos

Você implementou a autenticação de usuário no React 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 React: login e logout simples. 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 Cenários de Arquitetura Auth0 (em inglês) para saber mais sobre os cenários de arquitetura típicos que identificamos ao trabalhar com clientes na implementação da Auth0.

Tem um caso de uso complexo?

Garantiremos que sua equipe de desenvolvimento esteja preparada para o sucesso desde o primeiro dia. Fale com um especialista

Abordaremos padrões e ferramentas de autenticação avançada em guias futuros, como usar um pop-up em vez de redirecionar os usuários para fazer login, adicionar permissões a tokens de ID, usar metadados para aprimorar perfis de usuário e muito mais.

  • Twitter icon
  • LinkedIn icon
  • Faceboook icon