paint-brush
Mas, mas, mas auTH é HaaRrRrRrRrRdpor@dbozhinovski
511 leituras
511 leituras

Mas, mas, mas auTH é HaaRrRrRrRrRd

por Darko Bozhinovski8m2024/08/19
Read on Terminal Reader

Muito longo; Para ler

Não, não é. É chato, burocrático, um problema resolvido... mas não o chame de difícil como uma declaração geral.
featured image - Mas, mas, mas auTH é HaaRrRrRrRrRd
Darko Bozhinovski HackerNoon profile picture


Não, não é. É chato, burocrático, um problema resolvido... mas não o chame de difícil como uma declaração geral.


Tenho "Usei MD5 para fazer hash de senhas em PHP" anos. Claro, foi uma ideia horrível, mesmo em 2012. Mas, naquela época, não me lembro de considerar a autenticação "difícil". Era uma provação bem direta por si só - pegue um e-mail ou um nome de usuário, pegue uma senha, faça o hash (com MD5, como "Deus pretendia") e, se você fosse especialmente consciente da segurança, [ salt ] a senha. Armazene tudo isso em algum lugar, geralmente em um banco de dados. Ta-da, inscrição concluída.


Hoje em dia, a narrativa mudou. "Auth é difícil" parece uma narrativa sempre presente que está a um clique do HackerNews ou Reddit de distância. Mas é mesmo? Na minha opinião, a verdade é que a autenticação não é difícil de construir - qualquer um pode aprender (e todos nessa linha de trabalho devem aprender o básico). O verdadeiro desafio está nos extras: MFA, gerenciamento de usuários, redefinições de senha, cada uma das centenas de provedores OAuth e mesclagens de contas de diferentes provedores. É a morte por mil cortes. Como a autenticação é um problema resolvido, reinventar a roda não é o melhor uso do seu tempo. Mas isso não significa que "auth é difícil" como uma declaração geral esteja correta ou mesmo perto de correta. Você deve experimentar, entender o básico e construir a partir daí. A complexidade só aumenta com a escala (ou escala potencial) do que você está criando.


Então, quão difícil a autenticação pode realmente ser? Vamos lá.


Antigamente...

Continuando de onde parei a história sobre PHP e md5, a criação de uma funcionalidade de login seguiu um conjunto semelhante de etapas: obter um e-mail e uma senha, verificar a existência do e-mail em seu armazenamento, fazer o hash da senha junto com o salt armazenado para esse e-mail, comparar o hash resultante com o armazenado no banco de dados e, se tudo der certo, definir um cookie via setcookie (ainda estamos na terra do PHP aqui - não que a lógica geral fosse muito diferente em outros ecossistemas).


Sair era ainda mais simples - basta invalidar o cookie no servidor e pronto. Se o servidor não vir um cookie com a próxima solicitação, você não está logado. Então, fazer rotas autenticadas também era uma provação simples no geral. As coisas podiam ficar cabeludas quando se tratava de permissões, mas, na maioria das vezes, com os aplicativos que eu tinha que criar, tínhamos apenas administradores e usuários. O que era algo que você poderia simplesmente armazenar junto com o registro do usuário ou em uma tabela de permissões se você precisasse expandir a quantidade de funções que tinha para seu aplicativo.


Divulgação completa — eu trabalho para a SuperTokens . Este artigo, no entanto, é fruto de uma frustração pessoal sobre uma narrativa onipresente sobre o quão difícil a autenticação é como uma declaração geral. Em outras palavras, não estou tentando "vender minha coisa". Use o que quiser.


Faça você mesmo - uma abordagem "moderna"

E-mail/senha e autenticação social

Para chegar onde estamos hoje, vamos começar do começo... Surpreendente, eu sei. Provavelmente podemos concordar que esses componentes são suficientes para fazer um PoC de e-mail/senha + login social:


  1. Um servidor que gerencia rotas - inscrição, login, logout...
  2. Algum tipo de armazenamento para manter os registros do usuário (uma matriz na memória também funciona)
  3. Visualizações - telas de login, inscrição e "painel" autenticado.
  4. Manipuladores para autenticação social


Seguindo com Express e Passport, já que não vamos reinventar a roda, chegamos a exatamente 150 linhas de código muito, muito chato e repetitivo: https://github.com/supertokens/auth-express/blob/master/index.mjs . A próxima seção será uma explicação superficial do que está acontecendo no código, então sinta-se à vontade para pular adiante se você já estiver familiarizado com os conceitos. O aplicativo express é um PoC de qualquer maneira.


Vamos dissecar rapidamente:

Renderizando coisas na tela

Do jeito que eu vejo, há duas maneiras de abordar isso - começar com a renderização e seguir para a rota de autenticação ou vice-versa. Principalmente por acaso, acabei sendo um plebeu FE-heavy (ainda consigo fazer SQL, caso você esteja se perguntando), então vou começar com a abordagem de "renderizar coisas na tela".


Como este é um PoC, não vamos ficar todos React-fancy. O bom e velho SSR com ejs vai servir: https://github.com/supertokens/auth-express/tree/master/views

Adicionando rotas

Com base em alguns exemplos do passport.js , mas simplificando ainda mais, precisamos do seguinte:

  1. Algumas dependências: npm i passport passport-local express-session . Vamos resumir cada uma delas:

    1. Passport.js - o middleware de autenticação original para express e node.
    2. passport-local - uma estratégia de autenticação para o Passport; Uma estratégia de autenticação em um módulo que manipula o processo de autenticação para um método de autenticação específico - neste caso, um login local usando um nome de usuário (e-mail) e senha.
    3. express-session - um middleware que gerencia dados de sessão, permitindo que você armazene e persista sessões de usuário entre solicitações HTTP. Ele funciona atribuindo um ID de sessão exclusivo a cada cliente, que é armazenado em um cookie no lado do cliente e usado para recuperar dados de sessão no servidor.
  2. Um lugar para armazenar nossos usuários (o exemplo vinculado acima usa uma matriz na memória): https://github.com/supertokens/auth-express/blob/master/index.mjs#L13

  3. Configuração para nossa instância do Passport e nossa instância LocalStrategy para lidar com solicitações de entrada para pesquisa de usuário: https://github.com/supertokens/auth-express/blob/master/index.mjs#L18

  4. Inicialize o passport ( https://github.com/supertokens/auth-express/blob/master/index.mjs#L60 ) e o express-session ( https://github.com/supertokens/auth-express/blob/master/index.mjs#L69 ).


Verbose, claro. Difícil? Acho que não, pelo menos não no sentido de implementar-como-brinquedo. Mas já passamos do uso de combos de e-mail/senha há algum tempo. Vamos inspecionar o quão difícil é adicionar um provedor social em cima do que temos.


Como exemplo de provedor aqui, decidi usar o GitHub por um motivo simples: se você decidir seguir adiante, é um dos provedores mais fáceis de começar (estou olhando para você, Google).


Se você decidir seguir completamente, aqui está um link descrevendo como obter essas chaves do GitHub: https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/creating-an-oauth-app Ah, e a propósito, as que estão no repositório não são válidas, caso você esteja preocupado ;)

Integrando o GitHub OAuth2 em nosso PoC

Primeiro, precisamos de mais uma dependência, npm i passport-github2 . passport-github2 é uma estratégia de autenticação para o Passport, permitindo a integração com a API OAuth2 do GitHub.


Alguns manipuladores ( https://github.com/supertokens/auth-express/blob/master/index.mjs#L122-L133 ) e configuração ( https://github.com/supertokens/auth-express/blob/master/index.mjs#L29-L45 ) depois, bem, é isso. Complicado? Provavelmente não. Burocracia? Pode apostar. Chato? Com certeza. Especialmente se você tiver que fazer isso repetidamente. É um problema resolvido; reinventar a roda geralmente não é o melhor uso do tempo, como estabelecemos.


A grande ideia

Agora, provavelmente podemos concordar que Auth não é difícil de construir . Portanto, não é essa coisa mágica que apenas magos de barba branca que falam a linguagem mística dos JWTs podem entender e implementar.


Não, na verdade, eu diria que, como desenvolvedor, é preciso entender o básico de como a autenticação funciona. E muitas vezes vejo uma narrativa que afirma o contrário - algo como "confie em mim, mano, podemos cuidar disso para você". E claro, concordo que, na maior parte, criar sua própria autenticação é perda de tempo. Mas não é tão difícil de construir e certamente não é algo místico. Onde realmente fica complicado é com tudo que envolve a autenticação e a experiência do usuário.


Considere isto - no exemplo acima, temos uma coisa de auth funcionando. Mais ou menos. Mas aqui está o que ela não pode fazer (também mencionado no abridor do artigo):

  • 2FA, autenticação multifator
  • Redefinições de senha
  • Cada um dos centenas de provedores OAuth com sua especificidade
  • Gerenciamento de usuários
  • Mesclagem de contas de diferentes provedores
  • Cubra todos os possíveis casos extremos e potenciais falhas de segurança
  • ...e eu posso continuar


Provavelmente podemos implementar cada um deles. E por si só, cada parte pode ser considerada simples. Mas isso se soma. Então, não é necessariamente a implementação — é mantê-la, ser responsável por ela, manter-se atualizado com os padrões, violações de segurança e assim por diante. Além disso, uma demonstração de mãos — quantos de vocês gostam de ler RfCs? Não imagino que veria muitas mãos levantadas se estivéssemos em um meetup.


O que quero dizer é que auth não é fácil, tomado como um todo. Claro, podemos facilmente improvisar algo para um PoC, como fizemos acima. Mas não é mágico, não é impossível de entender e, por favor, por favor, não diga que é. Essa linha de pensamento (e marketing), na minha opinião, é prejudicial para a indústria como um todo.


Então, a pergunta natural seria: quando você deve criar o seu próprio?

Projeto de brinquedo, indie e atividades educacionais

...por todos os meios. Eu até encorajaria. Você aprende muito fazendo, então por que não? Se seu projeto indie/toy ou blog crescer e tiver uma base de usuários ou seguidores considerável, mude para um serviço, uma solução auto-hospedada ou outra coisa. Afinal, você tem um produto naquele ponto, e seu tempo, sem dúvida, será melhor gasto construindo esse produto em vez de mantendo a autenticação.

Startups

Geralmente, se você estiver construindo produtos, não role sua própria autenticação. É reinventar uma roda muito chata e burocrática. Você tem muitas opções para escolher. Além disso, você está construindo algo, certo? Por que estamos tendo essa conversa se seu produto não é autenticação?

Scaleups e acima (independentemente de como escolhermos defini-los)

Não. O mesmo motivo das startups - mas certamente se aplica mais aqui.


Você provavelmente pode ver onde quero chegar com isso. "Auth is hard" é, eu diria, um discurso de marketing quando usado como uma declaração geral. Você pode entender auth, você pode construí-la, mas é chato, não é divertido de manter e é um problema que está resolvido. Portanto, pode ser considerada uma mercadoria — uma que você pode escolher na prateleira em qualquer sabor que escolher (algumas opções abaixo).

O cenário auto-hospedado e FOSS

Para aqueles que gostam de ter sua própria pilha (como eu), vocês também têm muitas opções para escolher:

Bibliotecas de autenticação

  • Passport.js, abordado acima em detalhes
  • Lucia - Uma biblioteca de autenticação simples e flexível para aplicativos web modernos, com foco na experiência do desenvolvedor e facilidade de uso.
  • Auth.js - Uma biblioteca de autenticação leve e personalizável para Node.js, projetada para ser facilmente integrada em várias estruturas e aplicativos. Começou como uma biblioteca para Next.

Servidores de autenticação

  • Keycloak - Um servidor de gerenciamento de identidade e acesso de código aberto que oferece recursos como logon único (SSO), corretagem de identidade e federação de usuários.
  • SuperTokens (veja o aviso acima) - Uma solução de autenticação de código aberto que fornece recursos pré-criados, como gerenciamento de sessão, login social e autenticação de e-mail/senha, com foco em segurança e simplicidade.
  • FusionAuth - Uma plataforma de autenticação flexível voltada para desenvolvedores, oferecendo recursos como gerenciamento de usuários, autenticação multifator (MFA) e logon único (SSO).
  • Authelia - Um servidor de autenticação de código aberto que fornece autenticação multifator (MFA) e SSO, projetado para proteger aplicativos usando proxies reversos.

Armazenamento + Autenticação

  • Supabase - Uma plataforma de backend como serviço (BaaS) de código aberto que fornece recursos de banco de dados, autenticação e tempo real, projetada como uma alternativa ao Firebase.
  • Pocketbase - Uma solução de backend de código aberto que combina banco de dados, autenticação e armazenamento de arquivos, com o objetivo de simplificar o desenvolvimento de aplicativos modernos para web e dispositivos móveis.


Então, mesmo que você não goste de usar software de terceiros para autenticação, você pode simplesmente escolher um de código aberto, dependendo de suas necessidades e preferências, e seguir em frente.

Conclusão: a autenticação é a "burocracia" do desenvolvimento

Minha "grande" lição é evitar reinventar rodas, especialmente se for um problema resolvido, como auth é. Eduque-se sobre as ditas rodas, experimente com elas, construa uma roda de brinquedo e entenda-a. Mas, por favor, por favor, não a venda como algo impossivelmente difícil de entender e construir. Eduque, não faça gatekeeper.