Crie a autenticação de dois fatores no Angular com Twilio Authy
Tempo de leitura: 12 minutos
A autenticação do usuário é um requisito fundamental para muitos aplicativos do Angular e simplesmente fazer login com ID de usuário e senha é uma segurança cada vez menos adequada. A autenticação de dois fatores (2FA) oferece segurança baseada em dispositivo que é substancialmente mais difícil de invadir, mas criar seu próprio sistema 2FA é um grande desafio. O Twilio Authy facilita a adição da 2FA em aplicativos criados com Angular.
Esta publicação mostrará como adicionar o Authy no projeto do Angular. Você também aprenderá como melhorar a experiência do usuário e a segurança do app usando o Angular Universal para implementar o processo de login.
Nesta publicação, iremos:
- Criar um app básico do Angular com uma página de login
- Configurar um serviço de proteção de autorização e um serviço de autorização
- Adicionar a renderização no lado do servidor com o Angular Universal
- Configurar a autenticação do lado do servidor
- Implementar a autenticação de dois fatores com o Twilio Authy
Pré-requisitos para criar com Angular e Authy
Para realizar essas tarefas nesta publicação, você vai precisar do:
- Node.js e npm (a instalação Node.js também vai instalar o npm.)
- Angular CLI
- Uma conta da Twilio (inscreva-se para ter uma conta gratuita.)
Essas ferramentas são mencionadas nas instruções, mas não são necessárias:
Para aprender de forma mais eficaz com esta publicação, você deve ter o seguinte:
- Conhecimento em TypeScript e da estrutura do Angular
- Familiaridade com os observables do Angular, injeção de dependência e pipes
Há um projeto complementar para esta publicação disponível no GitHub. Cada etapa principal nesta publicação tem seu próprio branch no repositório.
Crie um projeto em Angular e gere os componentes
Cada projeto do Angular começa com a inicialização e instalação dos pacotes necessários.
Acesse o diretório em que o projeto será criado e digite as seguintes instruções de linha de comando:
Os comandos anteriores criaram o app e geraram dois componentes:
LoginPageComponent
um formulário para coletar o ID de usuário e a senha eProtectedPageComponent
uma página que será o destino do caminhohome
.
O app usará um serviço para determinar se o usuário está autorizado a acessar páginas específicas no app, como a página ProtectedPageComponent
.
Gere o AuthService
digitando a seguinte na linha de comando:
Implemente o serviço substituindo o conteúdo de src/app/auth.service.ts pelo seguinte código:
No método auth
, os valores para o ID de usuário, login
e password
foram codificados para fins de simplicidade. Em um app de produção, os valores coletados na página /login e passados para o método seriam validados com os dados recuperados em um armazenamento de dados persistente, como um banco de dados.
Se as credenciais forem validadas, a flag booleano authenticated
será definida como verdadeira e o usuário será redirecionado para o URL transmitido pelo AuthGuardService
.
Outro serviço, conhecido como uma route guard (proteção de rota), redirecionará os usuários para longe dos componentes protegidos para a rota de /login se o valor fornecido pelo AuthService
não for true
. Crie o AuthGuardComponent
com este comando:
Implemente o serviço substituindo o código existente em src/app/auth-guard.service.ts pelo seguinte:
A classe AuthGuardService
implementa a interface CanActivate
, que especifica o método public canActivate(): boolean
. O método usa AuthService
para determinar se o usuário está autenticado. Caso contrário, o método passa o URL da rota que invocou e chamou o AuthGuardService
para o AuthService
e retorna false
. Quando o usuário fizer login com êxito, o AuthService
direciona automaticamente para a página que pretendia acessar antes de efetuar login. Se o usuário for autenticado, o método retornará true
, permitindo que o usuário navegue até o componente.
LoginPageComponent
, ProtectedPageComponent
e AuthGuardService
precisam ser adicionados ao roteamento do app. Substitua o conteúdo de src/app/app-routing.module.ts pelo seguinte:
O roteamento do app agora inclui um caminho /login e um caminho /home que usam os componentes criados anteriormente. Há também uma rota para redirecionar o URL raiz para o caminho /home.
O caminho /home usa o ProtectedPageComponent
, que é protegido pelo serviço AuthGuardService
da seguinte forma:
Quando o usuário navega para o URL base do app (www.example.com) ou para o caminho /home, o Angular aciona o método canActivate
, que determina se o usuário tem permissão para abrir determinado recurso.
Para simplificar o HTML processado pelo app remove todos os elementos HTML de src/app/app.component.html, exceto o seguinte:
Além disso, substitua o modelo da página de login em src/app/login-page/login-page.component.html pelo seguinte:
A lógica para a página de login precisa refletir o design da página e implementar AuthService
. Substitua o conteúdo de src/app/login-page/login-page.component.ts pelo seguinte:
Como o componente de login usa conceito de Reactive Form (Formulário reativo), o ReactiveFormsModule
precisa ser incluído no ponto de entrada do app. Para isso, é necessário fazer duas alterações no arquivo src/app/app.module.ts.
1. Adicione a seguinte linha à parte superior do arquivo:
2. Atualize a seção de importações adicionando ReactiveFormsModule para que ela se pareça com o seguinte:
Verifique se o app está funcionando, digitando o seguinte na linha de comando:
Abra as ferramentas do desenvolvedor do navegador (F12) e navegue até [http://localhost:4200](http://localhost:4200). Você deve ver algo semelhante ao seguinte:
O que acabou de acontecer? Você navegou para a rota raiz do app, que o redirecionou para o caminho /home, que é protegido pelo AuthGuardService
. Como você ainda não foi autorizado, houve um redirecionado para o caminho /login.
Digite as credenciais de login (login: foo e senha: bar) e envie o formulário: você deve ver que foi redirecionado para o caminho /home e o HTML de protected-page.component.html é exibido.
Lembre-se de que ProtectedPageComponent
é fornecido como o destino da rota /home em app-routing.module.ts e que as credenciais de login são codificadas em server.ts.
Se quiser acompanhar essa etapa, clone esse branch do repositório do GitHub e execute o app com os comandos abaixo no diretório em que deseja criar o projeto. (Você precisará ter o Git instalado em sua máquina para clonar o repositório)
Mova a autenticação do usuário para o servidor
Manter a lógica de autenticação no navegador não é uma boa ideia. Nesta etapa, vamos "matar dois coelhos com uma cajadada só"adicionando o suporte do Angular Universal. O uso do Angular Universal (AU) irá:
- Melhorar a experiência do usuário e aprimorar a otimização do mecanismo de pesquisa (SEO) diminuindo o tempo até a primeiro carregamento significativo da página e
- Mover a lógica de autorização e autenticação para o lado do servidor do app para aumentar a segurança.
Instale o suporte do Angular Universal usando o @ng-toolkit com o seguinte comando:
O caminho /login que foi executado no front-end do navegador do app precisa ser substituído por um endpoint /auth/login o back-end do servidor. Substitua o código no arquivo /angular-twilio-authy/server.ts pelo seguinte:
Essas alterações criam um endpoint HttpPost
, /auth/login, que valida as credenciais fornecidas pelo usuário em relação aos valores conhecidos pelo app, como mostrado abaixo. Embora as credenciais de login sejam codificadas aqui, em um app de produção, elas normalmente são validadas contra um armazenamento de dados persistente usando uma consulta.
O AuthService
no app consumirá o /auth/login endpoint do servidor. Para alterar a implementação de AuthService
, substitua o código no arquivo src/app/auth.service.ts pelo seguinte:
Como o método auth
não retorna mais void
e agora retorna Observable
o LoginComponent
precisa se inscrever nele. Altere a implementação do método onSubmit()
no arquivo src/app/login-page/login-page.component.ts da seguinte forma:
(Nota: reticências ("...
") em um bloco de código representa uma seção de código elaborada para brevidade.)
Agora seria um bom momento para verificar se o app funciona como esperado. Compile e execute o servidor com os seguintes comandos:
Abra as ferramentas do desenvolvedor (F12) no navegador e selecione a guia Rede para que você possa ver a comunicação entre o navegador e o servidor. Navegue até http://localhost:8080. O app de página única (SPA) será fornecido a partir do back-end. Anote os recursos carregados quando a página for inicialmente fornecida, conforme mostrado na ilustração abaixo.
Insira as credenciais de login e observe as alterações na guia Rede das ferramentas do desenvolvedor. Você verá que a SPA em execução no navegador executou uma chamada REST para o endpoint /auth/login e retornou um código de status de 200 (OK)
.
Se quiser acompanhar essa etapa, execute os seguintes comandos:
(Observe que o comando para executar o app é diferente da última vez que você executou.)
Implemente a autenticação de dois fatores no Angular
O app agora tem um sistema de autenticação seguro no servidor. Mas ele depende de um único fator, o ID de usuário e a senha que estão em posse de um usuário. Este é um fator que o usuário conhece. É amplamente conhecido que essas credenciais são vulneráveis ao comprometimento e uso indevido de várias maneiras. Então, como o app pode ser mais seguro?
Uma das melhores maneiras é implementar um segundo fator de autenticação.
Além de algo que o usuário conhece, a autenticação de dois fatores também requer algo que o usuário possui (posse) ou é (herança).
A autenticação biométrica implementa a herança exigindo que as características físicas exclusivas de um usuário, como uma impressão digital ou um padrão de retina, estabeleçam sua identidade. Esse método é muito seguro, mas pode exigir hardware caro e de finalidade especial.
Twilio Authy para autenticação de dois fatores
O Twilio Authy fornece um segundo fator por meio de posse, algo que quase todas as pessoas tem: um telefone celular (ou outro dispositivo).
Se o telefone usar reconhecimento facial ou uma impressão digital para fazer o desbloqueio, os aspectos da autenticação baseada em herança também serão implementados: o usuário precisa saber sua ID e senha, possuir seu telefone e (opcionalmente) ser o usuário com o rosto ou dedo necessário para desbloquear o telefone ou o computador. Um agente mal-intencionado pode comprometer o ID de login e a senha de um usuário, mas é muito mais difícil para ele conseguir as credenciais, o dispositivo e os dados biométricos associados a um usuário, pelo menos por um período significativo.
O Authy tem vários recursos que aprimoram simultaneamente a experiência do usuário e fornecem opções flexíveis de autenticação:
- Notificações por push
- Tokens de software (códigos de uso único)
- Códigos de segurança de SMS e voz
- Aplicativos Authy para iOS, Android, Windows e macOS
Esta parte do projeto mostrará a rapidez com que você pode adicionar a 2FA a um app do Angular com o app Authy. Você precisará de uma conta da Twilio para concluir essas etapas. Você pode se inscrever em uma conta de avaliação gratuita em alguns minutos.
Depois de ter uma conta da Twilio, faça login e navegue até a seção do Authy no Console da Twilio e execute as etapas a seguir. Você estará pronto em alguns minutos.
- Na seção Authy do console da Twilio, crie um novo app.
- Copie a Production API Key (chave da API de produção) do app em um local seguro. (Você pode encontrar a chave nas Configurações do app se você a perder.)
- No app que você criou, registre-se como um novo usuário usando seu endereço de e-mail e número de celular preferidos.
- Copie o Authy ID do usuário que você acabou de criar em um local seguro.
- Instale o app Authy no seu telefone celular. Você deve ter recebido uma notificação por texto com um link para receber os códigos e concluir a instalação.
Quando tiver concluído com êxito as etapas anteriores, já será possível implementar a autenticação de dois fatores. O diagrama a seguir ilustra o fluxo de comunicação entre o navegador, o servidor e a Twilio:
- O cliente faz a solicitação GET
- O servidor gera a página de login
- O cliente envia o POST do /auth/login
- O servidor solicita autenticação de autenticação de dois fatores do Authy
- O Authy responde com request_id
- O servidor passa request_id para o navegador
- O servidor pergunta ao navegador (repetidamente) se o usuário autorizou com dois fatores
- O servidor solicita o status para a Twilio
- A Twilio responde com status de autorização
- O servidor passa o status para o navegador
Retorne à linha de comando no diretório do projeto e instale as dependências necessárias no projeto executando os seguintes comandos:
A implementação da autenticação de dois fatores no servidor exigirá dois novos endpoints e a modificação do endpoint /auth/login existente:
- /auth/status envia o status da resposta de um usuário à solicitação do Authy fornecida (aprovado, rejeitado, sem resposta).
- /auth/isLogged envia ao navegador um cookie criptografado para indicar que o usuário está conectado.
- /auth/login recebe o resultado do processo do Authy, além de verificar as credenciais de login.
Substitua o código no server.ts pelo seguinte:
Agora substitua os espaços reservados pelos valores copiados do console da Twilio ao configurar o Authy. Coloque a Production API Key na seção de declarações:
Para simplificar esta demonstração, codificamos por hardware os valores para login
(ID de usuário) e password
. Em um app de produção, você normalmente verificaria os valores fornecidos em relação a um armazenamento de dados persistente.
Se o usuário tiver fornecido credenciais válidas, a próxima etapa na 2FA será acionar uma mensagem do Twilio Authy para o dispositivo do usuário usando o ID do usuário no Authy. Assim como ignoramos o processo de registro de um usuário em nosso app, também estamos ignorando o processo de registro programático de um usuário com o Authy. Para tornar esta demonstração mais simples, estamos codificando o ID do Authy criado ao se inscrever como usuário diretamente no Authy.
No código do endpoint /auth/login, substitua o espaço reservado pelo valor do Authy ID salvo quando você criou um usuário:
Quando um usuário aprova a autorização com o app, o servidor envia o cookie contendo o valor supercriptografado. O cliente poderá determinar se o usuário está conectado ou não chamando o endpoint/auth/isLogged.
Dê uma olhada no código do endpoint /auth/isLogged mostrado abaixo. Embora o valor do cookie seja codificado, em um app de produção, você deve gerar um valor exclusivo e criptografado.
Porque o cookie tem um atributo httpOnly
, ele é inacessível no navegador. O cookie é um ótimo lugar para usar um JSON Web Token (JWT) contendo o escopo de autorização do usuário ou outros dados confidenciais. O cookie criptografado também fornece proteção contra o roubo de dados de token em um ataque cross-site scripting (XSS).
Agora que os novos endpoints estão no servidor, eles podem ser consumidos no AuthService. Substitua o código existente em src/app/auth.service.ts pelo seguinte:
Isso é muito código. O que mudou?
Primeiro, o método "auth" usa a autenticação de dois fatores com o Authy. Quando a chamada observable do endpoint /auth/login responde com uma mensagem positiva, o método secondFactor()
é chamado usando o token da API do Authy como um argumento:
A função secondFactor()
usa o método timer
da biblioteca rxjs
para emitir um número a cada segundo enquanto aguarda uma resposta do endpoint /auth/status no servidor. Se a resposta for approved
, o usuário é redirecionado para o URL fornecido para a função auth
. Este URL é o caminho para o qual o usuário tentou originalmente navegar antes de ser solicitado a fazer login.
Se a resposta de /auth/status for denied
, ou não houver resposta após 60 segundos, o observable retorna false
e fecha.
O método canActivate
de AuthGuardService
precisa consumir o AuthService
por um URL observable e retornar o URL de redirecionamento em vez de um booleano. Faça essas alterações copiando o seguinte código no arquivo src/app/auth-guard.service.ts:
O LoginPageComponent
deve manter o usuário informado sobre o status do processo de login. Isso pode ser feito com um rxjs BehaviorSubject, que é um tipo observable que permite que o LoginPageComponent
envie os valores de login
e password
para o método auth
e receba o status da tentativa de autenticação.
Substitua o conteúdo do arquivo src/app/login-page/login-page.component.ts pelo seguinte:
O valor da message
do BehaviorSubject pode ser exibido na página de login. Adicione o seguinte código na parte inferior do código existente no arquivo src/app/login-page/login-page.component.html:
Execute e teste a autenticação de dois fatores com o Authy
Recompile e execute o app digitando os seguintes comandos:
Abra as ferramentas do desenvolvedor (F12) no navegador e selecione a guia Rede para que você possa assistir a comunicação entre o navegador e o servidor. Navegue até http://localhost:8080 e digite as credenciais de login (login: foo, senha: bar) e clique em Enviar.
Duas coisas devem acontecer em sucessão rápida:
- A guia Rede exibirá uma série de eventos de "status" como resultado de o
LoginPageComponent
receber a notificação por push uma vez por segundo dosecondFactor observable
noAuthService
. Esses eventos continuarão a ocorrer até que o Authy receba uma resposta do app em seu telefone ou até que 60 segundos tenham se passado. - Você deve receber uma solicitação de envio como a mostrada abaixo no seu dispositivo móvel.
Aprove a solicitação de autenticação. O app móvel transmitirá com segurança a aprovação para a infraestrutura do Authy do Twilio, que enviará uma notificação por push ao processo do servidor.
O SPA do Angular em execução no navegador receberá a resposta positiva do endpoint /auth/status no servidor com o cookie de autenticação. Na ilustração abaixo, você pode ver a resposta isLogged
e o cookie:
Se quiser acompanhar essa etapa, execute os seguintes comandos:
Preparando o Angular e o Authy para produção
Como mostra este estudo de caso, você pode implementar facilmente a autenticação de dois fatores completa e de alto desempenho em um app do Angular usando o Twilio Authy e o Angular Universal. Mas há outras considerações antes de seu app estar pronto para produção.
A mais importante é a implementação de TLS/SSL para a comunicação criptografada entre o navegador e o servidor. O processo completo de implementação de TLS/SSL está além do escopo deste tutorial e dependerá do seu sistema operacional e de outros fatores, mas você pode configurar facilmente o código mostrado acima para consumir um certificado OpenSSL autoassinado instalado em sua máquina de desenvolvimento.
Substitua o conteúdo do arquivo local.js pelo seguinte código e modifique os caminhos para localhost.key e localhost.cert conforme necessário para sua configuração:
Esse código pode ser encontrado no branch step4 do repositório complementar.
Outras considerações de produção incluem:
- Armazenamento de credenciais de usuário (ID de usuário e senha) de forma criptografada em um armazenamento de dados persistente (como um banco de dados)
- Validação e armazenamento seguros de números de telefone associados a contas de usuário
- Criar novos usuários no Authy e armazenar seu Authy ID com segurança no armazenamento de dados
- Criptografia do cookie usado para validar a autenticação entre o navegador e o servidor com JSON Web tokens (JWT) ou outro técnica
- Configuração de requisitos de ID de usuário e validação de endereços de e-mail
- Definir requisitos de senha e lidar com redefinições de senha
Procure publicações sobre esses tópicos aqui no blog da Twilio.
Resumo: criando a autenticação de dois fatores com Angular e Authy
Falamos sobre um desafio importante para todos os aplicativos maduros: segurança com autenticação de dois fatores (2FA). Vimos como implementar a autenticação no servidor usando o Angular Universal, o que torna o processo rápido e seguro. E implementamos a 2FA com o Twilio Authy, um conjunto abrangente de ferramentas para autenticação, incluindo uma API, um console baseado na Web e aplicativos móveis.
Recursos adicionais do Angular Universal
Se quiser saber mais sobre as técnicas do Angular Universal, confira estas outras publicações no blog da Twilio:
- Introdução ao Serverless Angular Universal no AWS Lambda
- Como criar aplicativos amigáveis da Web internacionalizados ao mecanismo de pesquisa com Angular Universal e ngx-translate
- Crie aplicativos do Angular rápidos e eficientes com o Angular Universal, um serviço TransferState e uma API watchdog
O repositório para o código usado nesta publicação pode ser encontrado no GitHub.
Publicações relacionadas
Recursos relacionados
Twilio Docs
De APIs a SDKs e aplicativos de amostra
Documentação de referência de API, SDKs, bibliotecas auxiliares, guias de início rápido e tutoriais para sua linguagem e plataforma.
Centro de Recursos
Os mais recentes e-books, relatórios do setor e webinars
Aprenda com especialistas em engajamento do cliente para melhorar sua própria comunicação.
Ahoy
Centro da comunidade de desenvolvedores da Twilio
Melhores práticas, exemplos de código e inspiração para criar comunicações e experiências de engajamento digital.