Explorando o Couchbase e o N1QL por meio do Touchbase usando Node.js e Angular.js - Parte 3: Autenticação de usuário baseada em sessão

Parte 3: Modelos de login e sessão

Até o momento, Parte 0 e Parte 1 abrangem o modelo de dados e o documento do usuário usado no aplicativo, seguido de Parte 2 em que verificamos as contas por e-mail usando o Nodemailer e o Sendgrid. Essa é uma parte essencial para iniciar um usuário em qualquer site de mídia social, mas agora precisamos garantir que ele possa fazer login e acessar o conteúdo da nossa rede social. Vamos começar!

Materiais necessários:

  • Node.js
  • Expresso

Módulos de nó usados:

  • SDK do Couchbase Node.js com N1QL
  • analisador de corpo
  • uuid

Primeiro, precisamos autenticar nossos usuários. O ponto de extremidade da API para isso é '/api/loginAuth'.

API '/api/loginAuth

A autenticação começa com a garantia de que o e-mail e a senha sejam transmitidos corretamente para o back-end. Se eles estiverem faltando, será retornado um erro. Na implementação atual dessa API, o erro aparece no front-end com um erro Angular.js, ng-messages. Observe que também enviamos o nome de usuário e a senha para esse endpoint por meio de uma solicitação POST. Isso garante um pouco mais de segurança em relação a um GET, já que a URL não expõe informações secretas. Obviamente, uma implantação adequada do aplicativo deve incluir HTTPS para evitar ataques do tipo man-in-the-middle.

Após a primeira validação, o 'User.advancedSearch' é executada para encontrar o documento do endereço de e-mail que o usuário está procurando. O ideal é que a função retorne um resultado com o endereço de e-mail exato que o usuário possui. Como você pode ver, o primeiro trecho de código da API loginAuth, 'if (x.length === 0)'Em seguida, ele verifica se o endereço de e-mail foi registrado e, se não tiver sido, gera um erro. Em segundo lugar, ele verifica se a combinação de nome de usuário e senha é válida, chamando a função 'User.validatePassword' que garante que a versão com hash da senha inserida pelo usuário corresponda à versão com hash que foi armazenada no documento do usuário. Isso usa a mesma função de hash que usamos no documento original do usuário que criamos no 'User.create' função.

Função User.validatePassword

Em seguida, ele verifica se o e-mail do usuário foi verificado. Se você não tiver certeza de como isso funciona, consulte Parte 2 desta série. Em resumo, há um atributo 'login.emailVerified' que seria alterado se o usuário realmente verificasse seu e-mail. Esse é um atributo booleano, portanto, verificamos se ele é avaliado como "true" e, caso contrário, lançamos uma mensagem de erro para informar ao usuário que seu e-mail ainda não foi verificado.

Por fim, se todas as condições acima forem atendidas, passaremos ao processo de realmente fazer o login do usuário. Isso inclui adicionar a hora atual à matriz, 'timeTracker.loginTimes', no documento correto do usuário. Isso é feito usando a função Usuário.addLoginTime que está em models/usermodel.js.

Função User.addLoginTime

Essa função usa uma consulta N1QL para pegar a matriz do usuário e, essencialmente, defini-la como a mesma matriz, mas com a hora atual anexada à matriz 'timeTracker.loginTimes'. No momento, não há como acrescentar algo a uma matriz existente usando N1QL, portanto, essa é uma solução alternativa a ser usada até que essa funcionalidade seja adicionada. O ATUALIZAÇÃO garante que a chave que estamos procurando já existe e que estamos apenas atualizando um array existente.

OBSERVAÇÃO: Certifique-se sempre de usar o USAR CHAVES sempre que você quiser pesquisar um ID de documento específico. Usando 'WHERE META(bucketname).id=var' ou qualquer outro ONDE não usa a interface K-V super rápida para o Couchbase e pode ser inconsistente com suas alterações. Neste exemplo, usamos USAR CHAVES para a velocidade e passar todas as nossas novas variáveis em uma matriz para o SDK do Node.js usar na consulta. Isso garante que a consulta será mais segura e evitará a injeção de N1QL, semelhante à injeção de SQL. Os pontos em que esses elementos da matriz serão colocados na consulta são indicados com um "$". O número inteiro especificado ao lado do símbolo '$' especifica qual elemento da matriz será usado. A indexação para isso começa em 1.

Após a execução bem-sucedida, podemos voltar para rotas/routes.js para nosso ponto de extremidade da API e veja o 'Session.create' que será executada em seguida. Aqui, chegamos ao início da criação de um aplicativo mais seguro. Usando 'Session.create'passamos o ID do usuário, como fizemos na última função. Isso pode ser encontrado em models/sessionmodel.js.

Função Session.create

Essa função usa o ID do usuário e gera um documento de sessão que tem seu próprio identificador exclusivo, sessionID, e também o ID do usuário associado, para que ele possa ser identificado. O campo "userID" é útil para quando quisermos criar uma página "My Profile" ou identificar quem pode ter feito uma determinada publicação em nossa rede social. Usamos uma inserção simples do SDK do Couchbase para adicionar esse documento. Em seguida, adicionamos uma expiração ao documento para que ele expire uma hora após ser adicionado (3600 milissegundos). Depois que um usuário estiver conectado por mais de uma hora, ele terá que fazer login novamente. Um possível aprimoramento aqui pode ser usar a função touch() para estender a sessão enquanto estiver em uso. Depois que esse documento é criado, enviamos um retorno de chamada com o sessionModel e, em seguida, em nosso rotas/routes.js enviamos um objeto com o sessionID e a expiração para o front-end. Aqui, esse sessionID será armazenado no localStorage do navegador, para que possa ser acessado sempre que necessário.

Depois que o sessionID é adicionado ao localStorage, nós o enviamos no cabeçalho das solicitações HTTP para qualquer rota protegida. Uma rota protegida seria qualquer endpoint de API que tenha informações seguras que só devem ser acessadas por usuários que estejam conectados no momento. Para este projeto, usei o Angular.js, então coloquei o sessionID do localStorage no cabeçalho $http de cada solicitação de API, que pode ser visto no arquivo '$scope.getAllUsers' função.

Função de front-end $scope.getAllUsers

O '/api/advancedSearch' é um exemplo de uma rota protegida e é atingida pela '$scope.getAllUsers' função. No código da função '/api/advancedSearch' e você perceberá que ele chama 'Session.auth'e, em seguida, um retorno de chamada nos argumentos da função.

API '/api/advancedSearch

O 'Session.auth' função em models/sessionmodel.js obtém o sessionID do cabeçalho da solicitação, fazendo uma operação de divisão no cabeçalho $http para analisá-lo. O sessionID pode estar nas instâncias do corpo da solicitação, como o upload de imagens, de modo que isso é tratado no 'Session.auth' também. Depois que o sessionID é obtido do cabeçalho ou de alguma outra parte da solicitação, é realizada uma consulta N1QL para encontrar o documento da sessão. Novamente, 'USE KEYS' (USAR CHAVES) é usado para manter a velocidade em mente. Caso nenhum documento seja encontrado com o sessionID que passamos, o que provavelmente significa que ele expirou após uma hora, uma resposta é enviada com um objeto. Isso pode ser tratado de várias maneiras diferentes no front-end e, na minha implementação, eu simplesmente envio o usuário de volta à página de login Se ('!currentSession').

Função Session.auth

Essa segurança baseada em sessão mantém o site seguro, pois todo o controle de acesso é verificado no back-end. Ao contrário de um cookie simples, em que o usuário é desconectado se o cookie expirar, isso dá ao desenvolvedor controle total sobre o login. O uso puro e simples de cookies expirados permite que o javascript do front-end seja facilmente excluído ou alterado para obter acesso às informações do site. O motivo pelo qual o '/api/loginAuth' também passa a expiração do documento da sessão para o front-end para permitir que outros desenvolvedores adicionem cookies com expiração no front-end, se desejarem.

Se o 'Session.auth' for bem-sucedida e encontrar o documento correto, ela passará o ID de usuário do documento para o objeto de solicitação, que poderá ser acessado por qualquer outra função no ponto de extremidade da API para receber informações específicas do usuário para coisas como "Meu perfil" ou armazenar o ID do usuário em documentos para suas postagens.

Isso conclui nosso quarto tutorial sobre o Touchbase, e espero que tenha sido útil para entender um método de manter um aplicativo seguro. Há outras alternativas, como tokens da Web JSON ou OAuth 2.0, mas, neste caso, escolhi uma abordagem baseada em sessão e espero que isso o ajude a entender esse método de autenticação de usuário. Se você tiver alguma dúvida, comentário ou feedback, comente abaixo.

Compartilhe este artigo
Receba atualizações do blog do Couchbase em sua caixa de entrada
Esse campo é obrigatório.

Autor

Postado por Pranav Mayuram

Pranav Mayuram é estagiário da linguagem de consulta N1QL, Couchbase. Criou uma plataforma de rede social, Touchbase, usando o Couchbase Server, Node.js, Express e Angular.js.

Deixe um comentário

Pronto para começar a usar o Couchbase Capella?

Iniciar a construção

Confira nosso portal do desenvolvedor para explorar o NoSQL, procurar recursos e começar a usar os tutoriais.

Use o Capella gratuitamente

Comece a trabalhar com o Couchbase em apenas alguns cliques. O Capella DBaaS é a maneira mais fácil e rápida de começar.

Entre em contato

Deseja saber mais sobre as ofertas do Couchbase? Deixe-nos ajudar.