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.
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
Uma conta gratuita oferece:
- Login Universal Auth0 para Web, iOS e Android.
- Até 2 provedores de identidade social, como Google, GitHub e Twitter.
- Até 3 Actions, Rules, & Hooks 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 da aplicação e escolha seu o tipo. Use os seguintes valores:
Nome:
Auth0 React Code Sample
Application Type (Tipo da aplicação):
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:
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:
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>
);
};
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:
- Configure o Chrome para simular conexões de rede lentas para observar como a aplicação é carregada após o login.
- Registre o desempenho do tempo de execução da sua aplicação React. Feito isso, observe a ordem de renderização das páginas e elementos na linha do tempo que o Chrome produz.
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()
.
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 aquiredirect_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 objetohistory
do React Router. Você usa onavigate()
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.
- Você usa o hook
É 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>
);
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".
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.
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!
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 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 paraloginWithRedirect()
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.
- Um objeto de configuração para personalizar o fluxo de autenticação,
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
, eemail
. - 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).
- Actix Web/Rust API: Authorization Code Sample
- ASP.NET Core Code Sample: Web API Authorization
- Django/Python API: Authorization Code Sample
- Express.js Code Sample: Basic API Authorization
- Express.js/TypeScript Code Sample: Basic API Authorization
- Flask/Python API: Authorization Code Sample
- Laravel/PHP API: Authorization Code Sample
- Lumen/PHP API: Authorization Code Sample
- Phoenix/Elixir API: Authorization Code Sample
- Ruby on Rails API: Authorization Code Sample
- Spring Code Sample: Basic API Authorization
- Spring Functional Code Sample: Basic API Authorization
- Golang Code Sample: Basic API Authorization
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, comoname
,nickname
epicture
.email
: este valor de escopo requer acesso às informações deemail
eemail_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.
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íncronoasync 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.
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.