Alura > Cursos de Front-end > Cursos de Next.JS > Conteúdos de Next.JS > Primeiras aulas do curso Next.js: autenticação e gerenciamento de Tokens

Next.js: autenticação e gerenciamento de Tokens

Módulo de login - Apresentação

Olá, pessoas! Eu sou o Mario Souto e muito boas vindas ao nosso curso de Next.js, dessa vez focado especificamente em autenficação.

A ideia aqui é trabalhar do ponto de vista da arquitetura com esse framework sensacional que nos oferece estruturas para lidarmos com autenticação, não só via service rendered, mas também via aplicação do static.

Vamos falar também de alguma vulnerabilidades como, por exemplo, o CSRF (Cross Site Request Forgery) e o XSS (Cross Site Scripting). E ainda bordaremos como as estratégias de guardar token e refresh token podem impactar na segurança dos seus usuários.

Aqui, traremos o conceito geral que vai ajudar vocês a implementarem de acordo com o cenário de suas empresas. Teremos nossas api documentadas e todo nosso projeto para facilitar seu aprendizado. Bora aprender junto?

Módulo de login - Uma visão geral sobre autenticação

Antes de entrarmos nos código, precisamos contextualizar o conceito de autenticação. Para isso, podemos fazer um paralelo do mundo real com o mundo digital. O termo que mais uso para essas comparações é o de "cara-crachá".

Nesse paralelo o crachá faz o importante papel de Identificador, enquanto o porteiro, por exemplo, seria o Autorizador. No mundo real quando queremos entrar em algum local precisamos comprovar que nossa passagem é permitida através de nosso nome e/ou aparência e o autorizador é o resnposnável de checar se essas informações estão corretas e permitir a entrada

Podemos pegar como exemplo o crachá de uma faculdade. Na faculdade o autorizador sabe que você pode ter acesso ou não a algum espaço, mas esse acesso costuma ter um tempo limitado. Em teoria, você não pode ir para a sua aula da faculdade todos os dias em qualquer horário, você precisa ter um tempo limite que, geralmente, é de um ano. Durante um ano se você for aluno da faculdade você pode ter acesso a sua rede interna.

Quando você passar na catraca com o crachá da faculdade, por exemplo, existe um sistema autorizador que sabe que você tem acesso de fevereiro até dezembro ou de janeiro até dezembro. E se você tentar passar em janeiro do ano seguinte, pela regra seu crachá para de valer, porque estará expirado.

Isso é importante. Esse conceito é o que mais nos ajuda a entender como fazemos as autenticações na web. Se tivermos um formaulário com login e senha, como fazemos para conseguir trabalhar com autenticação disso? Na web, normalmente nós temos login e senha - salvo algumas exceções que comentaremos mais adiante.

Em um sistema que tenha login e senha, existe um projeto Front -End que vai pegar seus dados mandar para um Back-End que desempenhará o papel do Autorizador. Esse Back-End precisa de alguma forma saber que esse login e senha estarão válidos para entrada.

Por exemplo, se pegamos uma rede como o Twitter, ele tem que saber que eu sou eu para quando clicar no perfil eu poder mudar as informações e não precisar ficar digitando minha senha todas as vezes. Uma vez que você digita a sua senha e seu usuário em um sistema, ele gera um "crachá digital" que chamamos de Token. E o padrão mais comum que vemos para crachás digitais é o JWT, que vocês verão ao longo das próximas explicações.

Basicamente esse crachá tem um tempo de expiração, mas também pode conter informações extras como o nível de acesso ao sistema.

O token é gerado a partir do seu login e senha e é sempre validado por um autorizador que sabe quanto tempo ele deve durar e quanto acesso lhe é permitido no sistema.

Hoje em dia como tudo é digital, até mesmo o seu crachá físico pode estar integrado com o Token, então essa lógica acaba se misturando, mas gravem isso: você sempre vai precisar de um Identificador e um Autorizador e o identificador pode variar de acordo com a regra do sistema.

Adiante focaremos no código, como ele funciona e como ele sabe quando o login e senha estão errados. Além disso, veremos como gerenciar uma aplicação web para trabalhar tanto do lado do servidor quanto no modo estático.

Vale lembrar que hoje em dia usamos esse formato de Tokens porque podemos ter uma aplicação de terminal, IOS, Android, navegadores, entre outros, existem muitas maneiras de conseguirmos fazer a autenticação. Normalmente o Back-End tem que saber lidar com todas elas, por isso que hoje em dia temos esse formato de tokens e não mais o formato session ID, onde o servidor sabia todos os usuários que estavam conectados.

Hoje em dia com acesso remoto o session ID não é mais a melhor opção e foi substituído pela estratégia dos tokens com tempo de validade, que é o conteúdo que veremos ao longo das próximas aulas. Vejo vocês daqui a pouquinho!

Módulo de login - Começando nosso projeto

Acesse o projeto inicial no github aqui.

Neste link, você encontra um vídeo do meu canal de como validar formulários no React.

Finalmente chegou a hora de irmos para o código. Esse projeto depende de algumas coisas, então preciso que você tenha acesso a uma API feita para ajudar você a entender o que tá acontecendo. Aliás, serias bom que vocês explorassem ela pós curso porque por mais que seja um código de Back-End é um código importante para conseguirmos trabalhar no dia a dia.

Vocês poderão baixar o projeto por aqui. Uma vez baixado, teremos a pasta de Front-End e a pasta de Back-End. Para que tudo funcione, você deverá abrir no terminal por meio deste código.

03-nextjs-couser git:(main) cd backend
backend git(main) yarn install

Aqui usamos o yarn e o link para instalação estará na descrição deste vídeo.

backend git:(main) cd..
03-nextjs-course git:(main) cd frontend
frontend git:(main) yarn install

Assim garantimos que ambos estão instaldados! Agora, vamos estar sempre rodando o frontend com yarn dev e vamos abrir uma nova aba no terminal do VSCode e damos cd backend e o yan dev dele também.

frontend git:(main) yarn dev
03-nextjs-course git(main) cd backend
backedn git:(main) yarn dev

Assim podemos trocar as abas para ver tanto o backend quanto o frontend rodando.

No navegador, vamos abrir "localhost:3000" e ele mostra uma página simples para nos, com "Login" e dois espaços para serem preenchidos com login e senha, respectivamente. Mas se clicarmos em "Entrar" ele não faz nada porque ainda vamos criar os recursos.

Se abrirmos o "localhost:4000" ele mostra a documentação do nosso backend, a rota da API, usuário, senha, entre outros. Tem tudo pronto para só usarmos e sermos felizes!

Como foi sito, estamos trabalhando com o Next.js e se formos na documentação dele, encontramos uma parte falando de autenticação. Boa parte dos exemplos que eles trazem se apoiam muito em usar todos os recursos que o Next.js proporciona.

Porém, a ideia aqui é não criar uma solução que seja acoplada com o Nex.js, mas mostrar como criar uma solução de autenticação do ponto de vista de arquitetura, que seja possível de replicar em Angular, View ou qualquer outro.

Aqui, eles tem um exemplo com uma lib chamada NextAuth.js que dá estrutura para entragarmos login via GitHub, Google entre outros. Mas nós queremos aprender do ponto de vista de arquitetura para que vocês entendam como é o processo. Ale´m disso, no dia-a-dia a chance é que você veja mais da maneira que passamos aqui com algumas variações de acordo com o lugar que você trabalhe. Isso porque o requisito de autenticação de um banco é diferente de um requisito do Facebook que é diferente de um requisito pro Google e assim por diante.

Agora vamos abrir a pasta do Fron-End que está carregando o formulário de login. Esse formulários está simples de propósito porque não queremos focar nos estilos, mas no conteúdo e no mecanimos de gerenciamente dele.

Dentro da pasta "frontend" em "pages", vamos primeiramente tentar fazer trocar de página. Precisamos não só digitar qualquer valor no formulário, mas entrar na próxima página.

export default function HomeScreen() {
return {
    <div>
        <h1>Login</h1>
        <form>
            <input>
                placeholder="Usuário" name="usuario"
                defaultValue="omariosouto"
            />
            <input>
                placeholder="Senha" name="senha" type="password"
                defaultValue="safepassword"
            />
            <div>
                <buttom>
                    Entrar
                </buttom>
            </div>
        </form>
    </div>
    );
)

No primeiro passo aqui será importar o React. Depois, precisamos ter um state, então vamos criar o const e os states vão ser os valores value do formulário e vamos "setar" esses valores (setValues) e vamos dar um React.useState.

Em seguida, dizemos que temos o usuario que é omariosouto e a senha que será safepassword.

import React from 'react':
const [value, setValue] = React.useState({
    usuario: 'omariosouto',
    senha: 'safepassword'
}):

Está feita essa parte! Agora pegamos o defaultValue da linha 13 será value={values.usuario}. E o defaultValue da linha 17 será value={values.senha}.

Uma boa dica é deixarmos o console do navegador aberto para que ele nos guie conforme formos mexendo no código. Agora, por exemplo, ele diz que nos faltou colocar o onChange() nesse campos porque sem digitar ele não muda o valor. Esse onChange() vai pegar handleChange

<input>
                placeholder="Usuário" name="usuario"
                value=(value.usuario) onChange={handleChange}
            />
            <input>
                placeholder="Senha" name="senha" type="password"
                value={value.senha} onChange={handleChange}
            />

Para cada um desses campos precisamos fazer a nova atribução do valor. Para isso, vamos criar um function handleChange() que receberá o event de casa um dos casos e terá o nosso const fielValue igual a event.target.value. E vamos também pegar p tributo name e chamar de cons fielName.

function handleChange(event) {
    const fieldValue = event.target.value;
    const fieldName = event.target.name;
}

Por fim, é só fazermos o setValues. Como vamos usar o valores que já existem, vamos passar uma função que pegará o estado atual currents do values e fará um retorno de tudo que já tinha com o campo que estamos alterando fieldName e seu fieldValue.

function handleChange(event) {
    const fieldValue = event.target.value;
    const fieldName = event.target.name;
    setValues((currentValues) => {
        return {
            ...currentValues,
            [fieldName]: fieldValue
        }
    })
}
}

Aqui abaixo, do input adicionamos um tag de debug pre com JSON.stringify do values, null, 2.

<pre>
    {JSON.stringify(values, null, 2)}
</pre>

Criamos o código da validação do formulário! Se mexermos no formulário, ele mostra para nós que estamos mesxendo no state. Em teoria, poderíamos clicar em "Entrar" e fazer algo aqui.

Como estamos trabalhando com o SPA é importante que não tenha o refresh quando clicamos. Então, vamos comentar o debug do state e no form vamos colocar que no onSubmit o evento event deve previnir o refresh com preventDefault().

Agora se apagarmos e tentarmos entrar ele para de dar o refresh e para de jogar os nomes da URL. O próximo passo agora é trocar de página! Nós teremos duas páginas nessa aplicação, uma delas será o "auth-page-ssr" e a outra será "auth-page-static". Cada um delas terá uma função AuthPage que escreverá propriedades. Vamos começar pela estática.

function AuthPagesStatiic(props) {

}

Vamos retornar um div com um h1 de Auth Page Static.

function AuthPageStatic(props) {
    return (
        <div>
            <h1>
                Auth Page Static
            </h1>
        </div>

Quero ficar debugando com vocês o tempo todo tudo que estivermos recebendo nessas páginas, então podemos copiar aquela estrutura do pre.

function AuthPageStatic(props) {
    return (
        <div>
            <h1>
                Auth Page Static
            </h1>
            <pre>
                {JSON.stringify(values, null, 2)}
            </pre>
        </div>

Agora que fizesmo o static o próximo passo é o ssr.

function AuthPageSSR(props) {
    return (
        <div>
            <h1>
                Auth Page Server Side Render
            </h1>
            <pre>
                {JSON.stringify(values, null, 2)}
            </pre>
        </div>

E finalizamos com um export default do AuthPageStatic e do AuthPageSSR.

A estrtura das páginas é a mesma, a única diferença é realmente o nome! No navegador, já é possível acessar as duas páginas!

Qualquer parâmetro que nós recebermos para identificar os usuários será debugado e é em cima disso que faremos tudo funcionar. Para fechar esse vídeo, só falta fazermos o redirect, ou seja, irmos para uma dessas páginas ao clicarmos em "Entrar".

Para isso, em nosso index precisamos fazer o import do useRouter.

import { useRouter } from 'next/router';

O useRouter faz parte dessas bases de Next.js que já tivemos em outros cursos aqui da Alura. Basicamente, ele é um hook do Next que nos permite trocar de página.

Em HomeScreen() devemos adicionar essa const.

const router = useRouter();

Por fim, na onSubmit() fazemos um router.push para /auth-page-ssr e um para /auth-page-static.

router.push(/auth-page-ssr)
router.push(//auth-page-static)

A diferença é que vamos escolher um dos dois, primeiro vamos mandar os usuários para a página server render então comentamos o static.

O fluxo está acontecendo! Já no SPA e preparado para começarmos a autenticação na próxima aula! Vejo vocês lá!

Sobre o curso Next.js: autenticação e gerenciamento de Tokens

O curso Next.js: autenticação e gerenciamento de Tokens possui 217 minutos de vídeos, em um total de 45 atividades. Gostou? Conheça nossos outros cursos de Next.JS 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 Next.JS acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas