Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sistema de Autenticação #106

Closed
filipedeschamps opened this issue Aug 18, 2021 · 16 comments
Closed

Sistema de Autenticação #106

filipedeschamps opened this issue Aug 18, 2021 · 16 comments
Labels
back Envolve modificações no backend

Comments

@filipedeschamps
Copy link
Owner

Descrição

Eu como usuário avançado do site, através de uma API eu gostaria de poder usar os dados de acesso do meu usuário (username/email e password) para me autenticar no sistema, criar uma sessão ativa e a resposta desta requisição marcar nos cookies o token da sessão.

Execução

A execução não deve fugir muito de:

  • Rotas
  • Controllers
  • Model
  • Migration / Tabela no Banco
  • Testes

Sugiro seguirmos o modelo clássico de autenticação com cookies, e de início armazenar as sessões no Postgres (o que não é recomendado, mas como discutimos em live, vamos testar o limite antes de adicionar um outro serviço como Redis).

Sugiro não usarmos JWT

Eu sugiro não utilizarmos JWT, pois vejo que um dos principais motivos de se usar essa tecnologia é ter um sistema de autenticação sem a necessidade de uma máquina de estado (um backend que de forma persistente guarda as sessões), porque isso de fato tem várias vantagens, principalmente na escalabilidade (por não ter o gargalo da persistência que é difícil de escalar horizontalmente).

E também como iremos depender bastante de autorização, iremos precisar colocar isso no token que vai para o client, e eu não fico confortável com o client poder decidir isso no payload, mesmo que para ter qualquer efeito ele precise quebrar a assinatura (o que hoje é algo ainda impraticável caso seja usado uma chave forte, mas procure por brute forcing jwt token).

Outro ponto que vejo um pouco de confusão ao usar essa tecnologia é na hora de precisar invalidar/banir manualmente algum token em específico, que sem a máquina de estado fica impraticável, e com isso as pessoas começam a usar máquina de estado junto com JWT. Acho isso muito estranho, pois você está usando uma tecnologia projetada para não ter estado no backend (e assim conseguir facilidade de implementação e escalabilidade) e no final adiciona estado. É confuso, pois na minha visão fica muito mais limpo você decidir ou ir para o modelo full JWT sem estado, ou full tradicional com estado e cookies... ou eu to enganado?

Por favor, qualquer discussão nesse ponto é super bem vinda, principalmente pelo fato de nunca ter implementado autenticação JWT, apenas estudei a respeito e fiquei muito frustrado com esses pontos.

Dependência

@filipedeschamps filipedeschamps added the back Envolve modificações no backend label Aug 18, 2021
@huogerac
Copy link

huogerac commented Aug 19, 2021

Legal, vou olhar com mais calma os seus pontos contra o uso do JWT!
Se você entende que será mais simples ir sem JWT agora, acho interessante! A implementação mais simples de inicio é um ponto bem forte!

Sobre o banir, concordo que é um ponto fraco sim, mas tem opções bem faceis para resolver:

  • o mecanismo pra isto é o refresh_token, mas se vc entregar um token tem uma expiração curta (10 ou 30min), vai ficar batendo na API o tempo todo para pegar outro token...
  • outra saída interessante é continuar com um token longo, e os endpoints sensíveis (como inserir tabnews), fazer uma consulta no banco para ver se o usuário está ativo antes de inserir uma tabnews...a vantagem com isto é que no geral no login usuários ganham um token com dias ou semanas de expiração e apenas alguns endpoint precisam fazer select na base usuário para ver se é ativo...

Enfim, talvez nem precisa ficar descutindo isto! Bora sem JWT, eu entendo que é uma tabela de sessão no backend e cookies no frontend. Se alguem sabe algo diferente disto! queria saber tambem.
Valeu

@rodrigoKulb
Copy link
Contributor

rodrigoKulb commented Aug 24, 2021

No meu entendimento. Se a API não for ficar disponível para utilização externa, exemplo outros servidores utilizar o backend, podemos seguir sem JWT, pois a session (cookies) precisa de um browser para armazenar.

Achei esse vídeo bem simples com a explicação: https://www.youtube.com/watch?v=UBUNrFtufWo

@joaobracaioli
Copy link

O uso do JWT é interessante quando você tem a necessidade de trafegar informações junto com a autorização, como identificador do usuário, email, roles ou algo desse tipo, assim evita term que bater novamente em algum serviço para recuperar essas informações. Mas acredito que a principio o melhor caminho seja mesmo ir sem o JWT, se não tem essa necessidade.

Eu sugiro fazer um teste integrando com o keycloak se quiser "externalizar" essa atribuição de autorização e não ter que perder muito tempo com isso.

Um ponto de segurança seria já pensar em deixar o Cookie de credencial httponly.

@flanunes
Copy link

Estou trabalhando em um projeto na empresa para a implementação do JWT em uma API bem crítica.

Cogitamos utilizar OAuth2, mas, no nosso caso, por questão de simplicidade na implementação e desempenho, acabamos adotando JWS, que é a versão "assinada" do JWT.

Antes de tocar a implementação do projeto me deparei com esse artigo. Sugiro dar uma olhada nele, pode ajudar a enterrar de vez a possiblidade de uso do JWT ou não. Confesso que fiquei bem receoso pelos pontos levantados, mas pesamos os prós e contras e os cuidados a serem tomados na implementação.

Ao efetuar a autenticação do usuário devolvemos no payload os recursos que podem ser consumidos e inclusive pode-se adotar um tempo variável de expiração do token a depender da criticidade do recurso ou perfil do usuário. Estamos ainda em testes e por enquanto os resultados têm sido bem satisfatórios.

@liverday
Copy link
Contributor

liverday commented Sep 14, 2021

Oi, boa tarde! Primeiramente quero me apresentar, eu mal olhei o projeto e já vim correndo nessa discussão delicinha! Por isso, me perdoem caso eu esteja falando besteira ou não tenha me interado melhor no assunto.

Muito legal o artigo @flanunes! Aqui na empresa onde eu trabalho seguimos a adoção de um modelo OAuth/JWT utilizando Keycloak. Não vejo necessidade de utilizar o Keycloak neste momento, pois mais confundiria a cabeça da gente do que ajudaria, MAS, existe uma técnica muito legal para utilizarmos que resolveria os problemas de acesso que o @filipedeschamps mencionou.

A técnica Refresh Token, conforme o @huogerac falou, resolve esse problema! A vantagem é que nessa estratégia talvez nem precisaremos armazenar os tokens em um banco de dados/redis mantendo o principio stateless na nossa autenticação.

Refresh Token + JWS já resolve a maioria dos problemas que poderiamos ter com uma autenticação stateless.

Fiz um desenho no Excalidraw para ilustrar melhor esse fluxo:

Refresh Token Excalidraw

Dessa forma, a validação para saber se o usuário ainda é apto para utilizar o sistema acontecerá a cada 5 minutos, toda vez que um novo Access Token for requisitado.

No pior dos casos, caso o @filipedeschamps queira banir alguém, esse alguém só terá seu acesso "liberado" pelos próximos 5 minutos.

@gabrielgmrs
Copy link

E aí, pessoal! Nessa thread tenho mais a aprender do que colaborar, mas perguntinha: consideramos um identity manager externo como o AWS Cognito ou Auth0? Alguns benefícios: o Cognito fica gratuito para até 50.000 usuários ativos mensalmente, ambos contam com login passwordless out-of-the-box, ambos tem opção de OTP (one-time password) via SMS, logins sociais, integram com facilidade via next-auth e por aí vai...

Até onde vejo os 2 grandes argumentos para esse tipo de opção são:

  • Menor complexidade para os engenheiros
  • Segurança maior contra ataques

Imagino que não seja uma opção para empresas maiores, mas achei que seria algo legal de considerar pro TN. 😃

@liverday
Copy link
Contributor

E aí, pessoal! Nessa thread tenho mais a aprender do que colaborar, mas perguntinha: consideramos um identity manager externo como o AWS Cognito ou Auth0? Alguns benefícios: o Cognito fica gratuito para até 50.000 usuários ativos mensalmente, ambos contam com login passwordless out-of-the-box, ambos tem opção de OTP (one-time password) via SMS, logins sociais, integram com facilidade via next-auth e por aí vai...

Até onde vejo os 2 grandes argumentos para esse tipo de opção são:

  • Menor complexidade para os engenheiros
  • Segurança maior contra ataques

Imagino que não seja uma opção para empresas maiores, mas achei que seria algo legal de considerar pro TN.

Eu gosto da idéia de ter um ferramental, mas teriamos que adotar a ideia de jogar todos os usuários para o banco de dados disponível por essa ferramenta. Se não for um problema ter que replicar os dados dos usuários na ferramenta, também é uma boa idéia.

@francopan
Copy link

jogar todos os usuários para o banco de dados disponível por essa ferramenta

Até onde eu saiba o Auth0 permite você usar sua própria base de dados. O problema mesmo é o custo. De quem sai o dinheiro? Se o @filipedeschamps vai investir ou criar um catarse ótimo.
Outro problema é tornar-se refém de uma ferramenta desse tipo. Ou seja, para isso não ocorrer ainda seria necessário criar uma estrtura que possa ser adaptada para outras ferramentas de maneira simples, caso seja necessária a mudança.

@gabrielgmrs
Copy link

@francopan Sim, Auth0 é relativamente caro (depois dos 7k ativos/mês). Recomendo a pesquisada no Cognito, que é free até 50k/mês, e depois disso cobra uma fração bem pequena de dólar pelos seguintes (não passa a cobrar os primeiros 50k). Nesse ponto certamente o projeto já vai ter um modelo de monetização e o custo é razoável.

Sobre vendor lock-in, é uma decisão, de fato. Hoje eu tenho mais confiança na estabilidade em médio/longo prazo de um AWS, por exemplo, mas é um bom ponto a ser considerado 👍

@rodrigoKulb
Copy link
Contributor

Seguindo a ideia do @filipedeschamps é criar o MVP, sentir e identificar possíveis problemas, para evoluir com aprendizado.

Minha sugestão é iniciar com uma simples session, avaliar os riscos e possíveis falhas para ir evoluindo.

O que vocês acham?

@wcarugatti
Copy link

O problema de se utilizar AWS Cognito é o vendor locking. Além disso o preço dele depois de 50 mil usuários me parece caro comparado a uma solução própria.

@rhandrade
Copy link
Contributor

Ótima discussão pessoal 👏
Concordo com o @rodrigoKulb que seria legal iniciarmos com algo bem simples e ir validando a necessidade, até chegar no dia que nossa aplicação não estiver aguentando e ai abrimos uma live com o @filipedeschamps para avaliarmos o que da pra ser feito, como ele mesmo já comentou.

@rodrigoKulb
Copy link
Contributor

Voltando a conversar sobre esse assunto, verifiquei no diário que o @filipedeschamps levantou a problemática sobre utilizar o "passwordless" devido ao problema de perder acesso ao e-mail o usuário ficaria sem acesso ao portal.

Vejo que temos 3 opções de autenticação:

01 - Passwordless
Beneficio: Não teremos nenhuma informação de segurança armazenada no nosso banco da dados.
Problema: Se o usuário perder o acesso ao e-mail o processo de recuperação deverá ser manual.

02 - API de auth
Beneficio: Toda segurança dos dados fica por parte da API, mesmo se o usuário perder o acesso no e-mail o provedor já possui sistemas para recuperação das informações.
Problema: Nem todos possuem uma conta no Google, Facebook ou Github.

03 - Senha dentro do TabNews
Beneficio: Teremos total controle na recuperação da senha e possivel alteração na conta de e-mai.
Problema: Segurança de dados sensíveis será total responsabilidade dos desenvolvedores do tabnews

Gostaria saber de vocês o que acham e se existe mais alguma alternativa para ser analisada?

@filipedeschamps
Copy link
Owner Author

@rodrigoKulb eu vejo essas alternativas mesmo 🤝

Em paralelo, a discussão nessa issue aqui está fantástica e é um recurso educacional da vida real que eu não vejo a hora de deixar tudo público 😍

Bom, comecei a implementar a parte da infraestrutura bruta que manda os emails e que pode ser compartilhada pelas duas estratégias (password tradicional ou passwordless). Assim que conseguir voltar com mais tempo para o computador faço o PR junto com o diário de desenvolvimento e parto para as outras camadas da autenticação e sessão 🤝

@rodrigoKulb
Copy link
Contributor

Exemplo de autenticação na Decolar, eles utilizam as 2 opções:
01 - Passwordless
02 - API de auth
Captura de tela em 2022-01-27 10-00-34

@filipedeschamps
Copy link
Owner Author

Turma, já podemos fechar essa issue, faltando apenas a issue de Autorização #107 (e pra fechar essa eu vou propor um desafio no vídeo tutorial que vou gravar).

Mas apesar do escopo dessa issue aqui ter sido concluído, o assunto Autenticação não terminou e está continuando na issue #171

Um dos tópicos lá é trocar autenticação do username por email. Quem quiser participar é super bem vindo 🤝

Em paralelo, issue closed! Let's gooooo 😍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
back Envolve modificações no backend
Projects
None yet
Development

No branches or pull requests

10 participants