Este guia TypeScript ajudará você a aprender como proteger uma aplicação Angular usando autenticação baseada em token. Você aprenderá como usar o framework Angular para implementar os seguintes recursos de segurança:
- Como adicionar login, inscrição e logout de usuário para aplicações Angular.
- Como criar guardas de rota para proteger rotas de aplicação Angular.
- Como fazer chamadas de API a partir do Angular para solicitar dados de uma API protegida.
- Como obter informações de perfil de usuário para personalizar uma interface de usuário Angular.
Este guia usa o SDK da Auth0 para Angular que fornece às pessoas desenvolvedoras uma API de alto nível para lidar com muitos detalhes da implementação de autenticação de usuário. Você pode proteger suas aplicações Angular seguindo as melhores práticas de segurança e ainda escrever menos código.
Configuração Rápida Do Angular
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 Angular 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 Angular, retornando JSON Web Tokens (JWTs) com informações de autenticação e de usuário.
Obtenha a aplicação Angular inicial
Criamos um projeto inicial usando a linha de comando do Angular (Angular CLI) para te ajudar a aprender os conceitos de segurança do Angular por meio da prática. Você pode se concentrar em construir componentes e serviços Angular e serviços para proteger sua aplicação.
Comece clonando o repositório spa_angular_typescript_hello-world
no branch starter
.
git clone -b starter git@github.com:auth0-developer-hub/spa_angular_typescript_hello-world.git
Depois de clonar o repositório spa_angular_typescript_hello-world
, torne ele o seu diretório atual:
cd spa_angular_typescript_hello-world
Instale as dependências do projeto Angular da seguinte forma:
npm install
Este projeto Angular 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 Angular 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 Angular 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:
API_SERVER_URL=http://localhost:6060
Este projeto usa um script npm para integrar o conteúdo do arquivo .env
com o framework Angular. Confira o arquivo set-env.ts
:
const { writeFile } = require('fs');
const { promisify } = require('util');
const dotenv = require('dotenv');
dotenv.config();
const writeFilePromisified = promisify(writeFile);
const targetPath = './src/environments/environment.ts';
const envConfigFile = `export const environment = {
production: false,
api: {
serverUrl: '${process.env['API_SERVER_URL']}',
},
};
`;
(async () => {
try {
await writeFilePromisified(targetPath, envConfigFile);
} catch (err) {
console.error(err);
throw err;
}
})();
Este script usa o pacote dotenv
para carregar variáveis de ambiente de um arquivo .env
para process.env
. O script então usa um modelo de string para criar o conteúdo do arquivo ./src/environments/environment.ts
. Em seguida, ele grava esse arquivo com o conteúdo prescrito no projeto Angular.
O script npm env
definido em package.json
executa o script set-env.ts
usando ts-node
. No entanto, você não precisa executar o comando npm run env
diretamente. O script npm start
executará isso para você antes de iniciar o servidor de desenvolvimento Angular.
Assim, execute o seguinte comando para executar a aplicação Angular:
npm start
Em seguida, execute o seguinte comando para executar a API do servidor JSON:
npm run api
Tudo pronto para você começar a implementar a autenticação do usuário neste projeto Angular. Primeiro, você precisará configurar a aplicação Angular para se conectar com sucesso à Auth0. Posteriormente, você usará o SDK da Auth0 para Angular 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 Angular 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 Angular Code Sample
Application Type (Tipo da aplicação):
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 será carregada.
Na próxima etapa, você aprenderá como ajudar o Angular e a Auth0 a se comunicarem.
Qual é a relação entre Auth0 Tenants e aplicações Auth0?
Digamos que você tenha uma aplicação Angular de compartilhamento de fotos chamado “NG-Gram”. Você então criaria um Auth0 tenant chamado ng-gram
. Do ponto de vista do cliente, NG-Gram é o produto ou serviço desse cliente.
Agora, digamos que o NG-Gram 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 NG-Gram pertencem ao tenant NG-Gram, que os compartilha em suas aplicações Auth0.
Crie uma ponte de comunicação entre o Angular 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 Angular 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 Angular. 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 Angular, sua aplicação Angular 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 Angular
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 Angular 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:
"Domain" e "Client ID" permitem que sua aplicação Angular 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 Angular da seguinte forma:
API_SERVER_URL=http://localhost:6060
AUTH0_DOMAIN=<AUTH0-DOMAIN>
AUTH0_CLIENT_ID=<AUTH0-CLIENT-ID>
AUTH0_CALLBACK_URL=http://localhost:4040/callback
Lembre-se de preencher os valores para as variáveis AUTH0_DOMAIN
e AUTH0_CLIENT_ID
com as informações obtidas na página da sua aplicação no dashboard da Auth0.
Depois de chegar à seção "Chamar uma API protegida a partir do Angular" deste guia, você aprenderá como usar 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.
Atualize o arquivo de script set-env.ts
para integrar essas novas variáveis de ambiente Auth0 de .env
em seu arquivo Angular rc/environments/environment.ts
:
const { writeFile } = require('fs');
const { promisify } = require('util');
const dotenv = require('dotenv');
dotenv.config();
const writeFilePromisified = promisify(writeFile);
const targetPath = './src/environments/environment.ts';
const envConfigFile = `export const environment = {
production: false,
auth0: {
domain: '${process.env['AUTH0_DOMAIN']}',
clientId: '${process.env['AUTH0_CLIENT_ID']}',
authorizationParams: {
redirect_uri: '${process.env['AUTH0_CALLBACK_URL']}',
},
},
api: {
serverUrl: '${process.env['API_SERVER_URL']}',
},
};
`;
(async () => {
try {
await writeFilePromisified(targetPath, envConfigFile);
} catch (err) {
console.error(err);
throw err;
}
})();
Você está criando um objeto auth0
usando os valores de configuração da aplicação Auth0 criado no Dashboard Auth0: Auth0 Domain e Client ID.
Além disso, você usa o objeto de configuração authorizationParams
para definir os parâmetros de consulta que o Angular precisa incluir em suas chamadas para o endpoint /authorize
da Auth0. Você define a propriedade redirect_uri
dentro deste objeto para especificar a URL da sua aplicação Angular para onde a Auth0 deve redirecionar seus usuários após efetuarem login com sucesso.
Posteriormente, você usará as propriedades do objeto auth0
para configurar o AuthModule
do SDK da Auth0 para Angular usando o padrão forRoot()
.
Reinicie seu servidor de desenvolvimento Angular para gerar novamente o arquivo src/environments/environment.ts
:
npm start
Lide com o comportamento pós-login Auth0
Observe que a URL de retorno de chamada Auth0, 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 Angular, você vai renderizar um componente de uma página simples para a rota /callback
.
Comece criando um arquivo CallbackModule
no diretório src/app/features
usando o Angular CLI:
ng g module features/callback --routing
Em seguida, use a CLI Angular para criar um CallbackComponent
no diretório src/app/features/callback
e declare-o no CallbackModule
:
ng g component features/callback --module=features/callback/callback.module.ts --skip-tests --style=none
Atualize o CallbackModule
para incluir o SharedModule
em seu array imports
:
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { SharedModule } from '@app/shared';
import { CallbackComponent } from './callback.component';
import { CallbackRoutingModule } from './callback-routing.module';
@NgModule({
declarations: [CallbackComponent],
imports: [CommonModule, SharedModule, CallbackRoutingModule],
})
export class CallbackModule {}
Atualize o CallbackRoutingModule
para definir CallbackComponent
como a rota padrão:
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { CallbackComponent } from './callback.component';
const routes: Routes = [
{
path: "",
component: CallbackComponent,
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class CallbackRoutingModule { }
Preencha o arquivo de template src/app/features/callback/callback.component.html
da seguinte maneira:
<div class="page-layout">
<app-nav-bar></app-nav-bar>
<app-mobile-nav-bar></app-mobile-nav-bar>
<div class="page-layout__content">
<ng-content></ng-content>
</div>
</div>
O componente CallbackComponent
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 é carregar o CallbackModule
usando o roteador Angular.
Localize o arquivo src/app/app-routing.module.ts
e atualize-o da seguinte forma:
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
const routes: Routes = [
{
path: '',
pathMatch: 'full',
loadChildren: () =>
import('./features/home/home.module').then((m) => m.HomeModule),
},
{
path: 'profile',
loadChildren: () =>
import('./features/profile/profile.module').then((m) => m.ProfileModule),
},
{
path: 'public',
loadChildren: () =>
import('./features/public/public.module').then((m) => m.PublicModule),
},
{
path: 'protected',
loadChildren: () =>
import('./features/protected/protected.module').then(
(m) => m.ProtectedModule
),
},
{
path: 'admin',
loadChildren: () =>
import('./features/admin/admin.module').then((m) => m.AdminModule),
},
{
path: 'callback',
loadChildren: () =>
import('./features/callback/callback.module').then(
(m) => m.CallbackModule
),
},
{
path: '**',
loadChildren: () =>
import('./features/not-found/not-found.module').then(
(m) => m.NotFoundModule
),
},
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
})
export class AppRoutingModule {}
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 Angular carrega rápido. - Ao não mostrar o rodapé, seus usuários podem achar que sua aplicação Angular carrega sem problemas.
- 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 Angular. 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 Angular, http://localhost:4040
, como a 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 Angular oferece uma página
/profile
que exibirá informações de perfil do usuário, como nome e endereço de e-mail. No entanto, essa aplicação também carrega lentamente a rota/profile
usando o Angular Router. - 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 Angular 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á direcioná-lo para uma página de login. - Depois que seus usuários fizerem login, a Auth0 os redirecionará de volta para sua aplicação Angular 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 Angular 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
.
Instale E Configure O SDK Da Auth0 Para Angular
Execute o seguinte comando para instalar o SDK da Auth0 para Angular:
npm install --save @auth0/auth0-angular
O SDK da Auth0 para Angular expõe vários métodos, variáveis e tipos que ajudam a integrar o Auth0 com sua aplicação Angular de forma idiomática, incluindo um módulo e serviço de autenticação.
Atualize o arquivo src/app/app.module.ts
da seguinte forma para importar o AuthModule
do SDK da Auth0 para Angular para o seu AppModule
e configure-o usando os dados do seu módulo environment
:
import { HttpClientModule } from '@angular/common/http';
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AuthModule } from '@auth0/auth0-angular';
import { environment as env } from '../environments/environment';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule,
AuthModule.forRoot({
...env.auth0,
}),
],
bootstrap: [AppComponent],
})
export class AppModule {}
Você usa o padrão forRoot()
para configurar o AuthModule
, que usa um objeto com as propriedades domain
, clientId
, e authorizationParams
. Você cria esse objeto de configuração espalhando o objeto env.auth
.
A autenticação do usuário é um mecanismo para controlar quem pode acessar sua aplicação. Você pode integrar sua aplicação com a 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 Angular ao usar a Auth0. Sua aplicação Angular 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.
Conexão Auth0 e Angular
Você concluiu a configuração de um serviço de autenticação que sua aplicação Angular pode consumir. Continue construindo o projeto inicial ao longo deste guia, implementando componentes Angular 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 Angular
As etapas de como construir um formulário de login Angular 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 Angular para a página de login.
Comece gerando um arquivo LoginButtonComponent
no diretório src/app/shared/components/buttons
e registre-o no SharedModule
usando o Angular CLI:
ng g component shared/components/buttons/login-button --module=shared/shared.module.ts --inline-template --skip-tests --style=none --flat --export
Preencha src/app/shared/components/buttons/login-button.component.ts
assim:
import { Component } from '@angular/core';
import { AuthService } from '@auth0/auth0-angular';
@Component({
selector: 'app-login-button',
template: `
<button class="button__login" (click)="handleLogin()">Log In</button>
`,
})
export class LoginButtonComponent {
constructor(private auth: AuthService) {}
handleLogin(): void {
this.auth.loginWithRedirect({
appState: {
target: '/profile',
},
});
}
}
Dentro da definição de LoginButtonComponent
, this.auth.loginWithRedirect()
é um método exposto por AuthService
que 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.target
para /profile
, você está informando ao SDK da Auth0 para Angular o seguinte: Quando meus usuários fizerem login com a Auth0 e retornarem à minha aplicação Angular, 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.
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 Angular
O processo de como construir um formulário de inscrição Angular é 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 Angular para a página de inscrição adicionando a propriedade screen_hint=signup
ao objeto de configuração authorizationParams
do método loginWithRedirect()
:
authorizationParams: {
screen_hint: "signup",
}
Este método loginWithRedirect()
é um wrapper do método Auth0 SPA SDK com o mesmo nome. Dessa forma, você pode usar o documento RedirectLoginOptions
do Auth0 SPA SDK para saber mais detalhes sobre essas opções de configuração.
Para ver isso na prática, gere um arquivo SignupButtonComponent
no diretório src/app/shared/components/buttons
e registre-o no SharedModule
usando o Angular CLI:
ng g component shared/components/buttons/signup-button --module=shared/shared.module.ts --inline-template --skip-tests --style=none --flat --export
Preencha src/app/shared/components/buttons/signup-button.component.ts
com o conteúdo abaixo para definir um componente de botão de inscrição:
import { Component } from '@angular/core';
import { AuthService } from '@auth0/auth0-angular';
@Component({
selector: 'app-signup-button',
template: `
<button class="button__sign-up" (click)="handleSignUp()">Sign Up</button>
`,
})
export class SignupButtonComponent {
constructor(private auth: AuthService) {}
handleSignUp(): void {
this.auth.loginWithRedirect({
appState: {
target: '/profile',
},
authorizationParams: {
screen_hint: 'signup',
},
});
}
}
O uso do recurso de inscrição Auth0 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 Angular e vê-los em ação. Você fará isso nas próximas seções.
Adicione Logout De Usuário Para O Angular
Você pode desconectar usuários de sua aplicação Angular efetuando o logout de suas sessões Auth0 usando o método logout()
do SDK da Auth0 para Angular.
Gere um arquivo LogoutButtonComponent
no diretório src/app/shared/components/buttons
e registre-o no SharedModule
usando o Angular CLI:
ng g component shared/components/buttons/logout-button --module=shared/shared.module.ts --inline-template --skip-tests --style=none --flat --export
Preencha src/app/shared/components/buttons/logout-button.component.ts
assim:
import { Component, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/common';
import { AuthService } from '@auth0/auth0-angular';
@Component({
selector: 'app-logout-button',
template: `
<button class="button__logout" (click)="handleLogout()">Log Out</button>
`,
})
export class LogoutButtonComponent {
constructor(
private auth: AuthService,
@Inject(DOCUMENT) private doc: Document
) {}
handleLogout(): void {
this.auth.logout({
logoutParams: {
returnTo: this.doc.location.origin,
},
});
}
}
Ao usar o método logout()
, o SDK da Auth0 para Angular 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 Angular. 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 Angular 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 pessoas desenvolvedoras 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 Condicionalmente
Nesta seção, você aprenderá como renderizar componentes React condicionalmente com base no status do SDK da Auth0 para Angular ou no status de autenticação de seus usuários.
Renderize os botões de autenticação condicionalmente
A aplicação inicial Angular apresenta uma experiência de navegação em desktop e móvel.
Ao usar sua aplicação Angular 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.
Crie uma variável isAuthenticated$
no NavBarButtonsComponent
para implementar a experiência do usuário definida acima:
import { Component } from '@angular/core';
import { AuthService } from "@auth0/auth0-angular";
@Component({
selector: 'app-nav-bar-buttons',
templateUrl: './nav-bar-buttons.component.html',
})
export class NavBarButtonsComponent {
isAuthenticated$ = this.authService.isAuthenticated$
constructor(private authService: AuthService) {}
}
Em seguida, atualize src/app/shared/components/navigation/desktop/nav-bar-buttons.component.html
da seguinte maneira para mostrar e ocultar condicionalmente os botões de login, inscrição e logout:
<div class="nav-bar__buttons">
<ng-container *ngIf="isAuthenticated$ | async; else unAuthenticated">
<app-logout-button></app-logout-button>
</ng-container>
<ng-template #unAuthenticated>
<app-signup-button></app-signup-button>
<app-login-button></app-login-button>
</ng-template>
</div>
O valor isAuthenticated$
reflete o estado de autenticação de seus usuários conforme rastreado pelo SDK da Auth0 para Angular. Esse valor é true
quando o usuário foi autenticado e false
caso contrário. 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/app/shared/components/navigation/mobile/mobile-nav-bar-buttons.component.ts
assim:
import { Component } from '@angular/core';
import { AuthService } from "@auth0/auth0-angular";
@Component({
selector: 'app-mobile-nav-bar-buttons',
templateUrl: './mobile-nav-bar-buttons.component.html',
})
export class MobileNavBarButtonsComponent {
isAuthenticated$ = this.authService.isAuthenticated$
constructor(private authService: AuthService) {}
}
Em seguida, atualize src/app/shared/components/navigation/mobile/mobile-nav-bar-buttons.component.html
da seguinte maneira para mostrar e ocultar condicionalmente os botões de login, inscrição e logout:
<div class="mobile-nav-bar__buttons">
<ng-container *ngIf="isAuthenticated$ | async; else unAuthenticated">
<app-logout-button></app-logout-button>
</ng-container>
<ng-template #unAuthenticated>
<app-signup-button></app-signup-button>
<app-login-button></app-login-button>
</ng-template>
</div>
Vá em frente e tente fazer o login. Sua aplicação Angular 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 Angular leva você para a página de inscrição, onde seus usuários podem se inscrever na aplicação Angular. Experimente!
Observe que, quando você termina de fazer login ou de se inscrever, a Auth0 redireciona você para sua aplicação Angular, 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 Angular 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 Angular for carregado.
Para corrigir a intermitência da interface de usuário (UI), use o valor do observable isLoading$
exposto por AuthService
que emite um valor booleano para renderizar o componente AppComponent
assim que o SDK da Auth0 para Angular terminar de carregar.
Comece importando SharedModule
para AppModule
:
import { HttpClientModule } from '@angular/common/http';
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AuthModule } from '@auth0/auth0-angular';
import { environment as env } from '../environments/environment';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { SharedModule } from './shared';
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule,
SharedModule,
AuthModule.forRoot({
...env.auth0,
}),
],
bootstrap: [AppComponent],
})
export class AppModule {}
Em seguida, abra src/app/app.component.ts
e atribua o observable isLoading$
da Auth0 a uma variável:
import { Component } from '@angular/core';
import { AuthService } from "@auth0/auth0-angular";
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
})
export class AppComponent {
isAuth0Loading$ = this.authService.isLoading$;
constructor(private authService: AuthService) {}
}
Abra o arquivo src/app/app.component.html
e o atualize assim:
<div class="page-layout" *ngIf="isAuth0Loading$ | async; else auth0Loaded">
<app-page-loader></app-page-loader>
</div>
<ng-template #auth0Loaded>
<router-outlet></router-outlet>
</ng-template>
Enquanto o SDK está carregando, o componente PageLoaderComponent
é 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 observable AuthService
.
Abra o arquivo do componente src/app/shared/components/navigation/desktop/nav-bar-tabs.component.ts
que define as guias de navegação da área de trabalho e atualize-o da seguinte forma:
import { Component } from '@angular/core';
import { AuthService } from '@auth0/auth0-angular';
@Component({
selector: 'app-nav-bar-tabs',
templateUrl: './nav-bar-tabs.component.html',
})
export class NavBarTabsComponent {
isAuthenticated$ = this.authService.isAuthenticated$;
constructor(private authService: AuthService) {}
}
Abra o arquivo de componente src/app/shared/components/navigation/desktop/nav-bar-tabs.component.html
e atualize-o da seguinte forma:
<div class="nav-bar__tabs">
<app-nav-bar-tab path="/profile" label="Profile"></app-nav-bar-tab>
<app-nav-bar-tab path="/public" label="Public"></app-nav-bar-tab>
<ng-container *ngIf="isAuthenticated$ | async">
<app-nav-bar-tab path="/protected" label="Protected"></app-nav-bar-tab>
<app-nav-bar-tab path="/admin" label="Admin"></app-nav-bar-tab>
</ng-container>
</div>
Em seguida, abra o arquivo do componente src/app/shared/components/navigation/mobile/mobile-nav-bar-tabs.component.ts
que define suas guias de navegação móvel e atualize-o da seguinte forma:
import { Component, EventEmitter, Output } from '@angular/core';
import { AuthService } from '@auth0/auth0-angular';
@Component({
selector: 'app-mobile-nav-bar-tabs',
templateUrl: './mobile-nav-bar-tabs.component.html',
})
export class MobileNavBarTabsComponent {
@Output() mobileNavBarTabClick = new EventEmitter<string>();
isAuthenticated$ = this.auth.isAuthenticated$;
constructor(private auth: AuthService) {}
onMobileNavBarTabClick(path: string): void {
this.mobileNavBarTabClick.emit(path);
}
}
Abra o arquivo de componente src/app/shared/components/navigation/mobile/nav-bar-tabs.component.html
e atualize-o da seguinte forma:
<div class="mobile-nav-bar__tabs">
<app-mobile-nav-bar-tab
path="/profile"
label="Profile"
(mobileNavBarTabClick)="onMobileNavBarTabClick($event)"
></app-mobile-nav-bar-tab>
<app-mobile-nav-bar-tab
path="/public"
label="Public"
(mobileNavBarTabClick)="onMobileNavBarTabClick($event)"
></app-mobile-nav-bar-tab>
<ng-container *ngIf="isAuthenticated$ | async">
<app-mobile-nav-bar-tab
path="/protected"
label="Protected"
(mobileNavBarTabClick)="onMobileNavBarTabClick($event)"
></app-mobile-nav-bar-tab>
<app-mobile-nav-bar-tab
path="/admin"
label="Admin"
(mobileNavBarTabClick)="onMobileNavBarTabClick($event)"
></app-mobile-nav-bar-tab>
</ng-container>
</div>
Saia de sua aplicação Angular 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 Angular para proteger rotas Angular na próxima seção.
Adicione Guardas De Rota Ao Angular
Você pode criar um guarda de rota de autenticação para proteger as rotas Angular. O Angular solicitará aos usuários que visitam a rota que façam login, caso ainda não o tenham feito. Depois de fazer login, o Angular os leva para a rota que eles tentaram acessar.
Você pode aplicar um guarda a qualquer rota definida no módulo roteador Angular atualizando src/app/app-routing.module.ts
da seguinte forma:
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AuthGuard } from '@auth0/auth0-angular';
const routes: Routes = [
{
path: '',
pathMatch: 'full',
loadChildren: () =>
import('./features/home/home.module').then((m) => m.HomeModule),
},
{
path: 'profile',
loadChildren: () =>
import('./features/profile/profile.module').then((m) => m.ProfileModule),
canActivate: [AuthGuard],
},
{
path: 'public',
loadChildren: () =>
import('./features/public/public.module').then((m) => m.PublicModule),
},
{
path: 'protected',
loadChildren: () =>
import('./features/protected/protected.module').then(
(m) => m.ProtectedModule
),
canActivate: [AuthGuard],
},
{
path: 'admin',
loadChildren: () =>
import('./features/admin/admin.module').then((m) => m.AdminModule),
canActivate: [AuthGuard],
},
{
path: 'callback',
loadChildren: () =>
import('./features/callback/callback.module').then((m) => m.CallbackModule),
},
{
path: '**',
loadChildren: () =>
import('./features/not-found/not-found.module').then(
(m) => m.NotFoundModule
),
},
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
})
export class AppRoutingModule {}
Você usa o AuthGuard
do SDK da Auth0 para Angular para proteger as rotas /profile
, /protected
e /admin
adicionando-as ao valor da propriedade de configuração de rotas canActivate
.
Se as condições definidas pelo AuthGuard
passarem, o componente será renderizado. Caso contrário, o AuthGuard
instrui o Angular a te levar para a página de login universal Auth0 para autenticação.
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 Angular redireciona você para fazer login com Auth0.
Depois de fazer login, o React deve levá-lo à página /profile
conforme especificado pela propriedade appState.target
presente na definição do componente do botão de login.
Os protetores do lado do cliente melhoram a experiência do usuário em sua aplicação Angular, 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 Angular
Depois que um usuário efetua login com sucesso, a Auth0 envia um ID token para sua aplicação Angular. 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 Angular.
Você pode usar os dados do ID token para personalizar a interface do usuário da sua aplicação Angular. O SDK da Auth0 para Angular decodifica o ID token e armazena seus dados através do observable user$
exposto por AuthService
. 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/app/features/profile/profile.component.ts
assim:
import { Component } from '@angular/core';
import { AuthService } from '@auth0/auth0-angular';
import { map } from 'rxjs/operators';
@Component({
selector: 'app-profile',
templateUrl: './profile.component.html',
})
export class ProfileComponent {
title = 'Decoded ID Token';
user$ = this.authService.user$;
code$ = this.user$.pipe(map((user) => JSON.stringify(user, null, 2)));
constructor(private authService: AuthService) {}
}
Depois, atualize src/app/features/profile/profile.component.html
assim:
<app-page-layout>
<div class="content-layout">
<h1 id="page-title" class="content__title">Profile Page</h1>
<div class="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>
<ng-container *ngIf="user$ | async as user">
<div class="profile-grid">
<div class="profile__header">
<img [src]="user.picture" alt="Profile" class="profile__avatar" />
<div class="profile__headline">
<h2 class="profile__title">{{ user.name }}</h2>
<span class="profile__description">{{ user.email }}</span>
</div>
</div>
<ng-container *ngIf="code$ | async as code">
<div class="profile__details">
<app-code-snippet
[title]="title"
[code]="code"
></app-code-snippet>
</div>
</ng-container>
</div>
</ng-container>
</div>
</div>
</app-page-layout>
O que está acontecendo em ProfileComponent
?
- Você exibe três propriedades do objeto
user
na interface do usuário:name
,picture
, eemail
. - Como os dados vêm de um Observable, você não precisa inscrevê-los diretamente no modelo usando a
async
pipe. - 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 ProfileComponent
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 authGuard
para proteger a definição de rota /profile
do seu módulo roteador Angular, src/app/app-routing.module.ts
.
Se você estiver conectado à sua aplicação, visite http://localhost:4040/profile
para ver os detalhes do seu perfil de usuário.
Integre O Angular Com Um Servidor De API
Esta seção se concentra em mostrar como obter um access token em sua aplicação Angular 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 Angular. 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 Angular?
Sua aplicação Angular 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 Angular "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 de 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 Angular (os exemplos listados abaixo estão em inglês):
- Actix Web/Rust API:Authorization Code Sample
- ASP.NET Core Code Sample:Web API Authorization
- ASP.NET Core v5 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
- FastAPI/Python Code Sample:Basic API Authorization
- Flask/Python API:Authorization Code Sample
- Laravel/PHP Code Sample:Basic API Authorization
- Lumen Code Sample:Basic API Authorization
- NestJS Code Sample:Basic API Authorization
- 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
- Spring WebFlux Code Sample:Basic API Authorization
- Golang Code Sample:Basic API Authorization
- Symfony Code Sample:Basic API Authorization
Chame Uma API Protegida Do Angular
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 Angular da seguinte maneira:
API_SERVER_URL=http://localhost:6060
AUTH0_DOMAIN=<AUTH0-DOMAIN>
AUTH0_CLIENT_ID=<AUTH0-CLIENT-ID>
AUTH0_CALLBACK_URL=http://localhost:4040/callback
AUTH0_AUDIENCE=<AUTH0-AUDIENCE>
Lembre-se de preencher os valores para as variáveis AUTH0_DOMAIN
e AUTH0_CLIENT_ID
com as informações obtidas na página da sua aplicação no dashboard da Auth0 como no início deste guia.
Você está usando AUTH0_AUDIENCE
para adicionar o valor de sua Auth0 Audience para que sua aplicação cliente Angular possa solicitar recursos da API que esse valor de audiência representa.
Vamos entender melhor o que representam os valores AUTH0_AUDIENCE
e API_SERVER_URL
.
O 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 Angular 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 Angular.
O valor de Auth0 Audience deve ser o mesmo para a aplicação cliente Angular 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 Angular. É como um número de telefone. Você deseja garantir que sua aplicação Angular "envie mensagem para a API correta".
Assim, atualize o script set-env.ts
para integrar essas novas variáveis de ambiente Auth0 de .env
para o seu arquivo Angular src/environments/environment.ts
:
const { writeFile } = require('fs');
const { promisify } = require('util');
const dotenv = require('dotenv');
dotenv.config();
const writeFilePromisified = promisify(writeFile);
const targetPath = './src/environments/environment.ts';
const envConfigFile = `export const environment = {
production: false,
auth0: {
domain: '${process.env['AUTH0_DOMAIN']}',
clientId: '${process.env['AUTH0_CLIENT_ID']}',
authorizationParams: {
audience: '${process.env['AUTH0_AUDIENCE']}',
redirect_uri: '${process.env['AUTH0_CALLBACK_URL']}',
},
},
api: {
serverUrl: '${process.env['API_SERVER_URL']}',
},
};
`;
(async () => {
try {
await writeFilePromisified(targetPath, envConfigFile);
} catch (err) {
console.error(err);
throw err;
}
})();
Reinicie o seu servidor de desenvolvimento Angular para gerar novamente o arquivo src/environments/environment.ts
:
npm start
Agora você está incluindo uma propriedade audience
no objeto de configuração authorizationParams
que você passa para o método AuthModule.forRoot()
. Lembre-se que o método AuthModule
inicializa o módulo de autenticação do sistema.
Que tal usar escopos?
Uma propriedade que você não está configurando diretamente no método AuthModule.forRoot()
é a propriedade scope. Quando você não passa uma opção scope
para o SDK da Auth0 para Angular, que ativa Auth0Plugin
, 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 Angular fornece um HttpInjector
que anexa automaticamente tokens de acesso a solicitações de saída ao usar o módulo integrado do Angular HttpClient
. No entanto, você deve configurar o injetor para saber a quais solicitações ele precisa anexar tokens de acesso.
Atualize a configuração do AuthModule
presente no array imports
do AppModule
e adicione o AuthHttpInterceptor
ao array providers
da seguinte forma:
import { NgModule } from '@angular/core';
import { HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http';
import { BrowserModule } from '@angular/platform-browser';
import { AuthHttpInterceptor, AuthModule } from '@auth0/auth0-angular';
import { environment as env } from '../environments/environment';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { SharedModule } from './shared/shared.module';
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule,
SharedModule,
AuthModule.forRoot({
...env.auth0,
httpInterceptor: {
allowedList: [`${env.api.serverUrl}/api/messages/admin`, `${env.api.serverUrl}/api/messages/protected`],
},
}),
],
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: AuthHttpInterceptor,
multi: true,
},
],
bootstrap: [AppComponent],
})
export class AppModule {}
Vamos detalhar o que está acontecendo no código acima:
Primeiro, você está importando AuthHttpInterceptor
de @auth0/auth0-angular
junto com HTTP_INTERCEPTORS
de @angular/common/http
. HTTP_INTERCEPTORS
é um token de vários provedores que representa o array de objetos HttpInterceptor
registrados.
Em seguida, você está adicionando a propriedade providers
ao objeto de configuração do AppModule
da seguinte maneira para registrar o injetor AuthHttpInterceptor
como um provedor:
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: AuthHttpInterceptor,
multi: true,
},
],
Isso conclui as ligações necessárias para conectar o AuthHttpInterceptor
com seu ciclo de requisições da aplicação Angular.
Agora, você precisa informar ao SDK a quais solicitações anexar tokens de acesso configurando AuthModule.forRoot()
. Com base nessa configuração, o Angular corresponderá a URL de qualquer solicitação que você fizer usando HttpClient
em uma lista de URLs permitidas:
httpInterceptor: {
allowedList: [`${env.api.serverUrl}/api/messages/admin`, `${env.api.serverUrl}/api/messages/protected`],
},
Se houver uma correspondência, o Angular anexa um token de acesso ao cabeçalho de autorização da solicitação. Você pode usar uma string ou uma expressão regular para a correspondência de URL. Por enquanto, você está permitindo que o Angular anexe um token de acesso às solicitações feitas para http://localhost:6060/api/messages/protected
e http://localhost:6060/api/messages/admin
.
Isso é tudo o que é necessário para integrar o Angular 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 Angular.
Próximos Passos
Você implementou a autenticação de usuário no Angular 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 Angular: 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.