Alura > Cursos de Front-end > Cursos de Angular > Conteúdos de Angular > Primeiras aulas do curso Angular: trabalhando com Tokens JWT na autenticação e cadastro

Angular: trabalhando com Tokens JWT na autenticação e cadastro

Criando a tela de login - Apresentação

Nayanne: Que tal aprender como implementar a autenticação em seus projetos Angular? Eu sou a Nay!

Audiodescrição: Nayanne Batista se autodeclara uma mulher de pele morena. Tem cabelos longos e lisos na cor castanho. Seu rosto é quadrado, no qual há sobrancelhas bem desenhadas e olhos castanhos. Usa óculos de armação transparente. Está com uma camiseta laranja.

Rafaela: E eu sou a Rafa!

Audiodescrição: Rafaela Petelin é uma mulher de pele branca com cabelos castanhos cacheados, abaixo dos ombros. Tem o rosto quadrado, sobrancelhas grossas e olhos castanhos. Usa óculos de armação marrom-escura e fones pretos por cima das orelhas. Está com uma camiseta azul-escura.

Gostaríamos de te desejar boas-vindas a mais um curso da Formação de Angular, no qual continuaremos a construção do projeto Jornada Milhas!

Nayanne: Isso mesmo, Rafa. Vamos construir em conjunto as telas de login, de edição do perfil e de cadastro. Para isso, aprenderemos a manipular tokens e realizar a autenticação com JWT, além de utilizar as boas práticas do Angular, implementando o Interceptor e a Guarda de Rotas.

Rafaela: Você já deve ter acessado um site no qual precisou realizar login com a sua senha e questionou sua segurança. Nesse curso, aprenderemos a implementar a autenticação para reforçar a segurança da sua aplicação web por meio de tokens.

Nayanne: Para aprender conosco, é necessário conhecer HTML, CSS, Typescript e ter cursado as etapas anteriores da Formação.

Se você atende todos os pré-requisitos, venha mergulhar no Angular!

Rafaela: Nos vemos no próximo vídeo.

Criando a tela de login - Tela de login

Rafaela Para iniciar essa nova etapa, acessaremos o Figma do projeto para entender os componentes a serem construídos. O primeiro deles é a tela de login, portanto, vamos visualizá-la.

Quando pensamos em login, precisamos criar avisos para a pessoa usuária saber se está preenchendo os campos corretamente ou não. Faremos isso por meio da implementação de validações.

Utilizaremos a abordagem de formulários reativos para facilitar as validações, pois eles permitem uma entrega de avisos mais simples e organizada, certo, Nay?

Nayanne: Isso mesmo, Rafa. A abordagem de formulários reativos criam um template (modelo) mais limpo, já que a criação do formulário e toda a lógica de validação são alocados no componente.

Vamos acessar o VS Code com o projeto aberto.

Acesse as atividades desta aula para baixar o projeto base.

Em seu interior, criaremos o componente de login. Já que ele possui um escopo de página, ele será criado na pasta "pages". Para isso, digitaremos o comando abaixo na aba do terminal.

ng g c pages/login

Após a criação, executaremos a aplicação com o comando abaixo.

ng serve

Em seguida, criaremos a rota desse componente no arquivo app-routing.module.ts. Para acessá-lo, percorreremos o caminho de pastas "src > app" por meio do explorador na lateral esquerda.

Em seu interior, acessaremos o bloco routes, dentro do qual duplicaremos o bloco entre chaves que possui o path abaixo de si.

No bloco copiado, modificaremos os atributos. Em path, adicionaremos login entre aspas simples e em component, adicionaremos o LoginComponent para que este seja carregado.

const routes: Routes = [
  {
    path: '',
    component: HomeComponent
  }
    {
    path: 'login',
    component: LoginComponent
  }
];

Vamos importar esse componente clicando na lâmpada à esquerda da linha atual e selecionando a opção "Add import from '.pages/login/login.component'". Isso gerará o código abaixo no início do arquivo.

import { LoginComponent } from './pages/login/login.component';

Vamos fechar esse arquivo e acessar o componente de login por meio do caminho de pastas "src > app > login". Vamos abrir os seus três arquivos: login.component.html, login.component.scss e login.component.ts.

Na guia do arquivo SCSS, colaremos o código dos estilos a serem utilizados. É possível acessá-lo e copiá-los nas atividades desta aula.

Vamos fechar essa guia e acessar a guia do HTML, no interior do qual limparemos o código pré-definido e iniciaremos a criação do formulário.

Se voltarmos à tela de login no Figma, veremos um banner, portanto, apesar da imagem ser diferente daquelas em outras telas, já temos um componente para isso.

Ademais, temos o componente de login, no qual há uma imagem de bússola, os campos de texto a serem preenchidos, um botão de acesso e abaixo deles, um texto.

Tela de login do Jornada Milhas, no Figma, constituída por um cabeçalho preto com a logo do aplicativo, dois menus e dois botões, um rodapé preto com informações do aplicativo e uma tela principal. O fundo da tela principal possui no topo uma foto com um homem de remos em um barco de madeira sobre águas cristalinas. Essa foto esmaece conforme se aproxima do centro da tela, sendo substituída gradativamente por um fundo branco. No centro da tela, há duas sessões. Na seção esquerda, a imagem de uma bússola laranja com contornos brancos. Na seção direita, quatro elementos alinhados na vertical. De cima para baixo, há o título "Login", em preto, o campo de texto com bordas roxas rotulado "E-mail ou CPF", cujo interior exibe o texto "Digite seu e-mail ou CPF", o campo de texto com bordas roxas rotulado "Senha", cujo interior exibe o texto "Digite sua senha" e um botão roxo cujo interior exibe o texto "ACESSAR MINHA CONTA", em branco. Abaixo das duas seções, há o texto "Ainda não possui sua conta? Clique aqui para se cadastrar!". Neste, a segunda frase possui o efeito negrito.

Voltaremos ao HTML e iniciaremos a implementação com o componente <app-banner>, que possui tags de abertura e fechamento.

Rafaela Criamos esse banner em cursos anteriores. Seu código também estará disponível.

Nayanne: Devemos informar duas propriedades para esse banner:

<app-banner
  src="assets/imagens/banner-login.png"
  alt="Banner da tela de login">
</app-banner>

Vamos acessar o Jornada Milhas no navegador, por meio da URL abaixo, para verificar se o banner será exibido.

localhost:4200/login

Na tela da aplicação, veremos que o banner é exibido.

Voltando ao VS Code, criaremos uma <section> com a classe login-component abaixo do <app-banner>. Em seu interior, utilizaremos um <mat-card> com a classe "login".

No interior desse cartão do Material, informaremos duas <div>s:

No interior da primeira, informaremos a tag <figure>, dentro da qual informaremos a tag <img src="assets/imagens/simbolo-bussola.png alt="Símbolo de uma bússola laranja">.

No interior da segunda <div>, adicionaremos o título, os campos e o botão por meio das tags do Material, os quais já utilizamos em outros cursos e continuaremos utilizando.

Acessando a página de Componentes na documentação do Material para Angular, veremos as tags que devemos utilizar:

Voltando ao interior da segunda <div> no VS Code, adicionaremos o <mat-card-header>, dentro do qual adicionaremos o <mat-card-title>. No interior desse último, adicionaremos o título "Login".

Abaixo do <mat-card-header>, criaremos a tag <form>, cujo interior receberá o <mat-card-content> representando o conteúdo propriamente dito do formulário. Este receberá em seu interior o <mat-card-field appearance="outline"> para representar cada campo com uma borda.

No interior do <mat-card-field>, haverá um <mat-label> dentro do qual adicionaremos o texto "E-mail" e um <input> do tipo matInput que terá um type="email" e um placeholder="Digite seu e-mail".

< !-- Código omitido -- >
</app-banner>
<section class="login-component">
  <mat-card class="login">
    <div class="image-container">
      <figure>
        <img src="assets/imagens/simbolo-bussola.png" alt="Símbolo de uma bússola laranja">
      </figure>
    </div>
    <div class="form-container">
      <mat-card-header>
        <mat-card-title>Login</mat-card-title>
      </mat-card-header>
      <form>
        <mat-card-content>
          <mat-form-field appearance="outline">
            <mat-label>E-mail</mat-label>
            <input matInput type="email" placeholder="Digite seu e-mail">
          </mat-form-field>
        </mat-card-content>
      </form>
    </div>
  </mat-card>
</section>

Para criar o próximo campo, duplicaremos todo o bloco <mat-form-field> abaixo de si mesmo, substituindo os seguintes elementos:

<section class="login-component">
  <mat-card class="login">
    <div class="image-container">
      <figure>
        <img src="assets/imagens/simbolo-bussola.png" alt="Símbolo de uma bússola laranja">
      </figure>
    </div>
    <div class="form-container">
      <mat-card-header>
        <mat-card-title>Login</mat-card-title>
      </mat-card-header>
      <form>
        <mat-card-content>
          <mat-form-field appearance="outline">
            <mat-label>E-mail</mat-label>
            <input matInput type="email" placeholder="Digite seu e-mail">
          </mat-form-field>
          <mat-form-field appearance="outline">
            <mat-label>Senha</mat-label>
            <input matInput type="password" placeholder="Digite sua senha">
          </mat-form-field>
        </mat-card-content>
      </form>
    </div>
  </mat-card>
</section>

Nos resta adicionar o botão e o texto abaixo dele. Para isso, abaixo do fechamento da tag <mat-card-content>, adicionaremos um <mat-card-actions> para alocar os botões de ação — neste caso, apenas aquele que representa o botão de acesso à conta: o <button> do tipo mat-flat-button com a cor "primary" (roxa).

No interior desse botão, adicionaremos o texto "ACESSAR MINHA CONTA".

Para adicionar a frase abaixo dos outros campos, criaremos um <p> abaixo do fechamento da tag <mat-card-actions>, cujo interior receberá o texto "Ainda não possui conta?" e o link com a tag <a>. Em seu interior, adicionaremos um link posteriormente.

Por fim, ainda no interior de <a>, adicionaremos o texto "Clique aqui para se cadastrar" com o efeito negrito por meio das tags <strong> e <u>, ambas com abertura e fechamento envolvendo a frase.

<section class="login-component">
  <mat-card class="login">
    <div class="image-container">
      <figure>
        <img src="assets/imagens/simbolo-bussola.png" alt="Símbolo de uma bússola laranja">
      </figure>
    </div>
    <div class="form-container">
      <mat-card-header>
        <mat-card-title>Login</mat-card-title>
      </mat-card-header>
      <form>
        <mat-card-content>
          <mat-form-field appearance="outline">
            <mat-label>E-mail</mat-label>
            <input matInput type="email" placeholder="Digite seu e-mail">
          </mat-form-field>
          <mat-form-field appearance="outline">
            <mat-label>Senha</mat-label>
            <input matInput type="password" placeholder="Digite sua senha">
          </mat-form-field>
        </mat-card-content>
                <mat-card-actions>
          <button mat-flat-button color="primary" (click)="login()">
            ACESSAR MINHA CONTA
          </button>
        </mat-card-actions>
        <p>Ainda não possui conta?
          <a><strong><u>Clique aqui para se cadastrar!</u></strong></a>
        </p>
      </form>
    </div>
  </mat-card>
</section>

Voltando ao navegador, veremos a bússola à esquerda, o título login, os dois campos de texto à direita, o botão de acesso e a frase abaixo dele.

O visual da tela de login está pronto. A seguir, implementaremos o seu funcionamento por meio da criação do formulário no componente.

Criando a tela de login - Controlando o formulário reativo

Rafaela: Anteriormente, construímos a parte visual da tela de login.

Dica: Caso tenha sentido dificuldades em lidar com o Angular Material, acesse o primeiro curso dessa Formação, na qual disponibilizamos materiais que abordam especificamente essa biblioteca.

Neste vídeo, criaremos o Component dessa tela para fazê-la funcionar. Vamos lá, Nay?

Nayanne: Vamos lá, Rafa. Voltando ao VS Code, já temos o HTML pronto, portanto, acessaremos o arquivo login.component.ts.

Em seu interior, criaremos o formulário. Para começar, acessaremos o espaço entre as chaves da classe LoginComponent, onde criaremos a propriedade loginForm para representar o formulário.

Ela será do tipo FormGroup, uma classe do Angular para auxiliar na criação de formulários.

export class LoginComponent {

  loginForm: FormGroup;
    
}

Para importar o FormGroup, clicaremos nesse comando e na lâmpada à esquerda da linha atual, selecionando a opção "Add import from '@angular/forms'". Isso gerará o código de importação abaixo no início do arquivo.

import { FormGroup } from '@angular/forms';

O loginForm acusará um erro, pois não foi inicializado. Para resolver esse problema, adicionaremos o operador de asserção não nulo do TypeScript(!) à sua direita, permitindo que o inicializemos posteriormente.

export class LoginComponent {

  loginForm!: FormGroup;
    
}

Abaixo do loginForm!, vamos criar o Construtor. Nas versões mais recentes do Angular, o construtor() e a classe OnInit não são trazidos por padrão.

Vamos injetar o serviço private FormBuilder do tipo FormBuilder entre os parênteses do Construtor. Vamos utilizá-lo para construir o formulário.

export class LoginComponent {

  loginForm!: FormGroup;
    
    constructor(private formBuilder: FormBuilder) {}
    
}

Rafaela: Esse serviço já está presente no Angular, diferentemente dos próximos que criaremos.

Nayanne: Verdade. Ele também faz parte do pacote @angular/forms. Vamos importá-lo na mesma linha em que importamos o FormGroup.

import { FormBuilder, FormGroup } from '@angular/forms';

Implementaremos a classe OnInit para inicializar o formulário por meio do comando implements OnInità esquerda de LoginComponent.

export class LoginComponent implements OnInit{

  loginForm!: FormGroup;
    
    constructor(private formBuilder: FormBuilder) {}
    
}

Quando escrevermos o nome dessa classe, vamos importá-la, acessando a lista de sugestões do editor e selecionando a opção "OnInit" proveniente do "@angular/core". O resultado será o acrescentado ao import do Component, no início do arquivo.

import { Component, OnInit } from '@angular/core';

Ocorrerá um erro em LoginComponent, pois a interface OnInit não foi implementada. Para corrigir esse problema, clicaremos em LoginComponent e na lâmpada à sua esquerda, selecionando a opção "Implement interface 'OnInit'" ("Implementar interface 'OnInit'").

Isso implementará a classe e gerará o bloco ngOnInit(): void no interior do Construtor.

export class LoginComponent implements OnInit{

  loginForm!: FormGroup;
    
    constructor(private formBuilder: FormBuilder) {}
    
    ngOnInit(): void {
        throw new Error('Method not implemented.');
    }
}

Vamos apagar a linha throw new Error('Method not implemented.'), pois não será utilizada. Ainda no interior do método OnInit(), criaremos o formulário digitando this.loginForm que receberá o this.formBuilder com o método .group().

Entre os parênteses deste último, adicionaremos um bloco de chaves, dentro do qual informaremos os campos de formulário — ou seja, os inputs que criamos no HTML:

export class LoginComponent implements OnInit{

  loginForm!: FormGroup;
    
    constructor(private formBuilder: FormBuilder) {}

    ngOnInit(): void {
        this.loginForm = this.formBuilder.group({
            email: [null],
            senha: [null]
        })
    }
}

Após essa implementação, precisamos associar as duas partes. Para isso, acessaremos o arquivo login.component.html e buscar a tag de abertura <form>. À esquerda do sinal de maior que, adicionaremos por meio da sintaxe dos colchetes (Property Binding) a tag [formGroup] que receberá um "loginForm".

Para associar cada campo, utilizaremos a diretiva formControlName que receberá o nome do campo do formulário, conforme abaixo:

<section class="login-component">
  <mat-card class="login">
    <div class="image-container">

      < !-- Código omitido -- >

      <form [formGroup]="loginForm">

          < !-- Código omitido -- >

            <input formControlName="email" matInput type="email" placeholder="Digite seu e-mail">
          < !-- Código omitido -- >

            <input formControlName="senha" matInput type="password" placeholder="Digite sua senha">

          < !-- Código omitido -- >

      </form>
    </div>
  </mat-card>
</section>

Também associaremos um evento para o clique no botão. Dentro da tag <button>, à esquerda da propriedade mat-flat-button, adicionaremos a escuta (click) para o clique do botão, associado ao método login().

<section class="login-component">
  <mat-card class="login">
    
        < !-- Código omitido -- >
        
    <div class="form-container">
        
            < !-- Código omitido -- >
            
      <form>
        
                < !-- Código omitido -- >
                
        </mat-card-content>
                <mat-card-actions>
          <button mat-flat-button color="primary" (click)="login()">
            ACESSAR MINHA CONTA
          </button>
        </mat-card-actions>
                
                < !-- Código omitido -- >
                
      </form>
    </div>
  </mat-card>
</section>

Vamos copiar o trecho login(), acessar o arquivo login.component.ts e, criar esse método abaixo do bloco ngOnInit().

Por enquanto, adicionaremos em seu interior um console.log('Login realizado com sucesso') para verificar se a associação funciona. À esquerda das aspas simples, adicionaremos um this.loginForm.value para verificar se os valores dos campos de formulário estão sendo coletados.

export class LoginComponent implements OnInit{

  loginForm!: FormGroup;
    
    constructor(private formBuilder: FormBuilder) {}

    ngOnInit(): void {
        this.loginForm = this.formBuilder.group({
            email: [null],
            senha: [null]
        })
    }
    
    login() {
        console.log('Login realizado com sucesso', this.loginForm.value)
    }
}

Vamos voltar à aplicação aberta no navegador. Na barra de busca do navegador, informaremos o endereço da página de login.

localhost:4200/login

Com a página de login aberta, acessaremos a aba de Inspeção à esquerda, pressionando "Ctrl+Shift+J". Em seu interior, vamos acessar e limpar a aba secundária "Console".

Na página de login, preencheremos os campos de e-mail e senha com os seguintes dados de exemplo:

E-mail:


rafa@gmail.com

Senha:

 
1234
 

Quando clicarmos no botão "ACESSAR MINHA CONTA", veremos a seguinte mensagem no Console:

Login realizado com sucesso

{email: 'rafa@email.com', senha: '1234'}

email: "rafa@email.com"

senha: "1234"

[[Prototype]]: Object

Rafaela: Com isso, conseguimos associar nosso template com o componente para controlar os campos do formulário. Agora, autenticaremos essas informações, enviando o e-mail e a senha para o servidor.

Contudo, por questões de organização, essa tarefa não pode ser realizada no componente. Portanto, construiremos um serviço separado para realizar o contato com o servidor e trazer a resposta com o login bem-sucedido ou não.

Faremos isso no próximo vídeo.

Sobre o curso Angular: trabalhando com Tokens JWT na autenticação e cadastro

O curso Angular: trabalhando com Tokens JWT na autenticação e cadastro possui 191 minutos de vídeos, em um total de 51 atividades. Gostou? Conheça nossos outros cursos de Angular em Front-end, ou leia nossos artigos de Front-end.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda Angular acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas