Executando verificação de segurança...
1
Joab
1 min de leitura ·

Ajuda Autenticação/Login React, React Router

Salve galera, recentemente entrei em um projeto onde sou o único front-end, e tive que desenvolver uma aplicação com login, porém eu estou com dúvida sobre como realizei o login com React.

O código

O login é realizado mandando a requisição post com usuário e a senha para o servidor. Onde ele me devolve um JWT que salvo no localStorage

api.post( "/login",
    {
        username: username,
        psswd: password,
    })
    .then((response) => {
        if (response.data) {
            localStorage.setItem("token",JSON.stringify(response.data));
            return {success: true,message: "login realizado com sucesso"}
        }
    })

Ai criei uma PrivateRoute que valida se existe o token no localStorage ou redireciona a pessoa para o login.

const storageToken = JSON.parse(localStorage.getItem("token"));

    if((storageToken && storageToken.token_type)){
        return (<Outlet />) 
    } else {
        return  <Navigate to="/login" />
    }

Para fazer as requisições no backend ele valida o token, porém ainda não foi me disponibilizado um endpoit para validar o meu token.

Além de validar o token no endpoit para acessar as rotas privadas(Não fiz pq ainda não está disponível o endpoint)

O que eu poderia melhorar?

Carregando publicação patrocinada...
1

Sem poder validar o token não haverá nenhuma rota privada. Nesse caso você apenas verifica se existe um token, isso significa que é possível injetar esse token no localstorage e pronto, a pessoa já tem acesso a rota privada sem autenticação.

Em questão de lógica, acredito que inverter as condicionais será mais vantajoso. Basicamente você tem apenas um caso onde o componente <Outlet /> será exibido, que é quando o usuário está devidamente autenticado. Invertendo as condicionais ficaria algo mais ou menos assim:

const storageToken = JSON.parse(localStorage.getItem("token"));

    if(!storageToken || !storageToken.token_type)){
        return (<Navigate to="/login" />) 
    }
    
    // outras condições aqui
    
    return  <Outlet />

Dessa forma ficaria muito mais fácil para adicionar mais casos onde o usuário seria redirecionado para a página de login, inclusive evitando requisições desnecessárias para o backend.

Outra melhoria sutil seria utilizar async - await ao invés de .then com promisses. Por exemplo, a sua requisição post ficaria assim (estou assumindo que você está usando o axios):

// no axios um erro é retornado quando você recebe um código http de erro
try {
    const { data } = await api.post("/login", {
        username: username,
        psswd: password,
    })
    
    localStorage.setItem("token", JSON.stringify(data))
    return { success: true, message: "login realizado com sucesso" }
} catch (err) { 
    // trata o erro no login
    return { success: false, message: "login não realizado" } // ou algo do tipo
}

Repare que, mesmo com o código ficando maior a leitura e o controle sobre ele são melhores com essa sintaxe. No caso de adicionar esse código dentro de um componente você o colocaria dentro de uma função assíncrona, que pode ser declarada dentro do próprio componente, daí sim utilizaria a sintaxe .then() dentro do componente, mas agora apenas receberia o resultado do login, sem precisar se preocupar com a lógica da requisição.

1

A parte do token eu entendo que falta muita segurança, me disponibilizaram o endpoit hoje para eu poder validar.
Nas condicionais da rota privada ficou muito legal pois vou ter que adicionar mais uma regra que direciona para outra página no primeiro login, da maneira que você colocou aqui vai ficar muito mais claro a regra.

Cara, muito obrigado pela ajuda e pela atenção.