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á.
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.
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:
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:
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
Com base em alguns exemplos do passport.js , mas simplificando ainda mais, precisamos do seguinte:
Algumas dependências: npm i passport passport-local express-session
. Vamos resumir cada uma delas:
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
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
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 ;)
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.
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):
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?
...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.
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?
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).
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
Servidores de autenticação
Armazenamento + Autenticação
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.
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.