Solucionado (ver solução)

Importante

Você está vendo a versão anterior da nova experiência da Alura que estamos preparando para você. Em breve, ela ganha uma identidade visual novinha totalmente pensada em potencializar seus estudos!

Solucionado
(ver solução)
13
respostas

Carregar dados do usuário logado

Como eu poderia fazer para pegar os dados do usuário que esta na sessão? Exibir o nome do usuário logado por exemplo?

Olhando o findOne da api/auth, ele recupera o usuário de acordo com login e senha, então acredito que não sirva como base. Poderia pegar o usuário pelo Token?

13 respostas

Quando você efetua o login, você recebe o usuário, um objeto. Você precisará guardá-lo no localStorage assim como fez no token para poder referenciá-lo onde desejar. Lembre-se que você só terá uma chance para armazená-lo, ou seja, assim que efetuar o login.

Ah, em Single Page Application não existe sessão, só lembrando! Quem guarda informações que seriam equivalente a sessão é seu browser. Eu sei , seu sei, algo completamente diferente de uma aplicação web tradicional.

Eu dei uma olhada no autenticar e fiz o seguinte:

api.autentica = function(req, res) {

         model.findOne({
             login: req.body.login,
             senha: req.body.senha
         })
         .then(function(usuario) {
             if (!usuario) {
                 console.log('Login/senha inválidos');
                 res.sendStatus(401);
             } else {
                console.log(usuario.login)
                 var token = jwt.sign({login: usuario.login}, app.get('secret'), {
                     expiresIn: 84600
                 });
                var usuario = usuario;
                 console.log('Autenticado: token adicionado na resposta');
                 res.set('x-access-token', token, usuario);
                 res.end(); 
             }
         });
     };

O que voce acha?

Alias, apos fazer o clicar no botão de "Login" como eu configuro para qual a pagina ele via? Poderia fazer isso?

Hoje, você tem uma tela de login no seu sistema. Certo? Quando você efetua o login, você não recebe o token? Mas além do token receberá o usuário via res.json. Você não vai colocar o usuário no header http. Troque res.end por res.json(usuario). E lá no seu Angular, recebe o retorno e guarda esse usuário.

Até agora eu fiz o seguinte:

 interceptor.request = function(config) {
            // enviar o token na requisição
            config.headers = config.headers || {};
            if ($window.sessionStorage.token) {
                console.log('Enviando token já obtido em cada requisição');
                config.headers['x-access-token'] = $window.sessionStorage.token;
            }
            return config;
        },

        interceptor.response = function (response) {
            var token = response.headers('x-access-token');
            var usuario = response.json(usuario);
            if (token != null) {
                $window.sessionStorage.token = token;
                $window.sessionStorage.usuario = usuario;
                console.log('Token no session storage: ', token);
            } 
            return response;
        },

        interceptor.responseError = function(rejection) {

            if (rejection != null && rejection.status === 401) {
                console.log('Removendo token da sessão')
                delete $window.sessionStorage.token;
                delete $window.sessionStorage.usuario;
                $location.path("/login");
            } 
            return $q.reject(rejection);
        }

Ainda estou com duvida no interceptor.request, como eu faria?

Descreva o fluxo passo a passo para mim do que você acha que deve acontecer. Isso lhe ajudará a fazer as perguntas certas. Inclusive, evitará tentativa e erro.

No atutentica eu vou devolver o usuario em json:

api.autentica = function(req, res) {

         model.findOne({
             login: req.body.login,
             senha: req.body.senha
         })
         .then(function(usuario) {
             if (!usuario) {
                 console.log('Login/senha inválidos');
                 res.sendStatus(401);
             } else {
                console.log(usuario.login)
                 var token = jwt.sign({login: usuario.login}, app.get('secret'), {
                     expiresIn: 84600
                 });
                var usuario = usuario;
                 console.log('Autenticado: token adicionado na resposta');
                 res.set('x-access-token', token);
                 res.json(usuario);
             }
         });
     };

La no angular eu tenho que pegar esse json e enviar a cada nova requisição que foi feita. O token foi enviado usando res.set, mas o usuario foi enviado com res.json, então eu não tenho onde me basear para dar continuidade.

O fluxo não é esse.

Seu token pode guardar qualquer coisa dentro dele no payload, certo? O que você guarda hoje lá? Se não me engano, é o nome do usuário. Mas a aplicação Angular não consegue descriptografar o token. Perfeito? Então, para exibir o nome do usuário em sua aplicação, você precisa guardar o nome do usuário ou o objeto usuário assim que se logar. Certo?

No envio para o servidor, não muda nada. Você só envia o token. La no servidor você descriptografa o token como já faz. Se lá dentro desse token, você colocou alguma informação de permissão do usuário, poderá acessa-la e decidir se bloqueia ou não acesso a determinado recurso. Só isso.

No lado do angular você só guarda o usuário poara poder aplicar alguma lógica sobre ele.

Existem diversas formas de se fazer isso, tente achar a que faça mais sentido para você.

Talvez esse vídeo possa complementar seu entendimento.

https://thinkster.io/tutorials/angularjs-jwt-auth

Lembrando que autenticação em SPA não tem nada a ver com autenticação baseada em sessão no lado do servidor, não existe session. Por isso sua APP angular tem que guardar o estado da aplicação. É esse o pulo do gato que você tem que ter sempre em mente.

Aliás, o problema que você esta tentando resolver é interessante, porque depois que você encaixar cada peça, é a mesma coisa com qualquer outra linguagem.

solução!

Na verdade isso não deveria nem ser um problema, ja que eu estou passando o usuario.login quando crio o Token. Eu deveria conseguir recuperar isso facilmente depois.

var token = jwt.sign({login: usuario.login}, app.get('secret'), {
                     expiresIn: 84600
                 });

Ficar enviando o json do usuário a cada requisição como você sugeriu no começo não me parece fazer sentido, eu não vou usar ele em todas as paginas.

Eu preciso extrair o usuário a partir do token nas paginas que eu for utilizar alguma informação do usuario.

https://auth0.com/docs/api/authentication#get-user-info

Poderia criar uma função que tem como parametro o token e retiro o usuario dela.

Mas como estou começando agora, não posso ficar na tentativa e erro como voce comentou.

Acredito que vou ter que trocar toda a implementação de autorização que foi usada no curso para outra.

Não faz sentido no interceptor. Ta tudo no caminho. A unica coisa que você precisa reenviar é o token e não o usuario que recebeu. O usuario vc recebe no login e guarda. Servidor não o envia mais.Esse usuario pode ser objeto cheio de propriedades e não uma string apenas.

Vc precisa dele para o angular ocultar coisas de acordo com perfil. O mesmo dado esta no token e e usado no server para saber se o usuario pode ou não acessar api.

Pegou a ideia?

Recebe o usuário e coloca no $rootScope. Dai você acessa via AE o dado do usuário de onde quiser.