Solucionado (ver solução)
Solucionado
(ver solução)
5
respostas

Dúvida sobre autenficicação do usuário.

Olá, primeiramente gostaria de compartilha meu humor no momento que é de muita raiva, porem isso faz parte. Vamos ao problema fiz uma aplicação em Angular2 e uma api em Node.JS, Mean Stack para ser mais claro, a ideia é fazer a autenticação do usuário com forme o curso. Funciona perfeitamente quanto eu utilizo o curl no terminal para enviar o post com os dados do usuário porém não funciona no angular, ele sempre vai para rota de verficar token app.use('/*', api.verificaToken); no lugar de ir para app.post('/v1/auth', api.auth); resolvi isso utilizando um use no lugar de post porém quanto ele faz a verificação no findOne ele sempre cai no dados inválidos mesmo estando certo e retornando o usuário.

route.auth.js

module.exports = function(app){
    var api = app.api.auth;

    app.use('/v1/auth', api.auth);
    app.use('/*', api.verificaToken);
}

Lembrando que estou utilizando use no lugar do post pois quando envio um post pelo angular ele cai no verificaToken (Sim eu verifiquei estou enviando um post e com Content-type: application/json).

api/auth.js

var mongoose = require('mongoose');
var jwt = require('jsonwebtoken');
var api = {}

module.exports = function(app) {
    var model = mongoose.model('Usuario');

    /*
    *   Autentifica usuário
    */
    api.auth = function(req,res){

        model.findOne({
            login: req.body.login,
            senha: req.senha
        }).then(function(usuario) {

            if(!usuario){
                res.status(401).end();
                console.log('dados invalidos');
            }else {
                var token = jwt.sign({login:usuario.login}, app.get('secret'), {
                    expiresIn: 84600
                });
                console.log('mandou token');
                res.set('x-access-token', token); 
            }

        }, function(error) {
            console.log('error auth');
            res.status(500).json(error)
        });
    }

    // código do verificaToken, tirei pra ocupar menos espaço.
    return api;
};

config/express

var express = require('express')
    ,app = express()
    ,consign = require('consign')
    ,bodyParser = require('body-parser');

module.exports = function() {
    app.set('secret', 'frazedeseguranca');

    app.use(bodyParser.json());
    app.use(express.static('./public'));

    app.use(function(req, res, next) {
        res.header("Access-Control-Allow-Origin", "*");
        res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        next();
    });

    consign({ cwd: 'app'})
        .include('models')
        .then('api')
        .then('routes/auth.js')
        .then('routes')
        .into(app);

    return app;
}

Aqui estou liberando o Access-Control-Allow-Origin porque o angular roda em uma porta diferente do servidor (acho que o problema pode está aqui).

Angular service

import { Injectable } from '@angular/core';
import { Http, Headers, Response } from '@angular/http';
import { Observable } from 'rxjs';

import { User } from "app/auth/user.class";

@Injectable()
export class AuthService {

    private http: Http;
    private headers: Headers;

    constructor(http: Http) {
        this.http = http;
        this.headers = new Headers({ 'Content-Type': 'application/json' });
    }

    auth(user: User): Observable<Response> {
        return this.http.post('http://localhost:2000/v1/auth', user, { headers: this.headers });
    }

}

Angular component

import { Component, } from '@angular/core';
import { User } from "app/auth/user.class";
import { AuthService } from "app/services/auth.service";

@Component({
    selector: 'auth',
    templateUrl: './auth.component.html'
})
export class AuthComponent  {

    private user: User = new User();

    constructor(private authService: AuthService) { }

    onAuth() {
        this.authService
            .auth(this.user)
            .subscribe(result => console.log(result), erro => console.log(erro));
    }

}

Lembrando que eu verifiquei se o angular estava enviando os dados corretos dando um res.json(req.body).end(); na api

Resposta do console do servidor / post enviado do angular

[nodemon] 1.11.0
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: *.*
[nodemon] starting `node app.js`
consign v0.1.4 Initialized in app
+ ./models/auth.js
+ ./models/vacation.js
+ ./api/auth.js
+ ./api/vacation.js
+ ./routes/auth.js
+ ./routes/vacation.js
server true
Conectado com MongoDB.
(node:83843) DeprecationWarning: Mongoose: mpromise (mongoose's default promise library) is deprecated, plug in your own promise library instead: http://mongoosejs.com/docs/promises.html
dados invalidos

Ele da esse aviso (DeprecationWarning) que não entendi muito bem

Post enviado pelo terminal

curl http://localhost:2000/v1/auth -X POST -v -H "Content-type: application/json" -d '{ "login": "teste@hotmail.com", "senha": "teste1" }';

Resposta

* Adding handle: conn: 0x7fa259003a00
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x7fa259003a00) send_pipe: 1, recv_pipe: 0
* About to connect() to localhost port 2000 (#0)
*   Trying ::1...
* Connected to localhost (::1) port 2000 (#0)
> POST /v1/auth HTTP/1.1
> User-Agent: curl/7.30.0
> Host: localhost:2000
> Accept: */*
> Content-type: application/json
> Content-Length: 61
> 
* upload completely sent off: 61 out of 61 bytes

Resposta do console do servidor / post pelo terminal

[nodemon] 1.11.0
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: *.*
[nodemon] starting `node app.js`
consign v0.1.4 Initialized in app
+ ./models/auth.js
+ ./models/vacation.js
+ ./api/auth.js
+ ./api/vacation.js
+ ./routes/auth.js
! Ignoring hidden entity /Users/andersonmenezes/Desktop/Projects/Agrinco/Servidor/app/routes/.DS_Store
+ ./routes/vacation.js
server true
Conectado com MongoDB.
(node:83905) DeprecationWarning: Mongoose: mpromise (mongoose's default promise library) is deprecated, plug in your own promise library instead: http://mongoosejs.com/docs/promises.html
mandou token
5 respostas

Você tem duas aplicações em separado , certo? Cada um em uma porta, confere ?

Já. Vetificou aqui?

https://cursos.alura.com.br/forum/topico-autenticacao-por-token-34556

Sobre o lado da aplicação angular não há solução consolidada para lidar com guardas de rota. Como Angular 2 é novo há várias soluções. Não sei dizer se a escolhida por você é a melhor.

Sim dei uma estudada sobre guardas de rotas e estou utilizando, mas voltando ao problema sobre ele sempre cair no verificaToken acredito que seja porque está em servidores/portas diferente ele envia duas requisições um OPTIONS depois o POST porém isso não é problema a ideia é fazer o build da aplicação angular e coloca no /public depois de pronto.

Images as duas requisições ( http://imgur.com/XuTLCvF / http://imgur.com/IWRjov7)

Os parametros estão email e password porque é como estou usando, apenas mudei para login e senha no código abaixo para facilita a visualização.

Sobre o problema de sempre cair no dados inválidos acredito que o problema seja realmente da promise do findOne

api.auth = function(req,res){

        model.findOne({
            login: req.body.login,
            senha: req.body.senha
        }).then(function(usuario) {

            if(!usuario){
                res.status(401).end();
                console.log('dados invalidos');
            }else {
                var token = jwt.sign({login:usuario.login}, app.get('secret'), {
                    expiresIn: 84600
                });
                console.log('mandou token');
                res.set('x-access-token', token); 
            }

        }, function(error) {
            console.log('error auth');
            res.status(500).json(error)
        });
    }

Parece que ele executa todo código antes dos dados do usuario chega por isso sempre cai no !usuario, porém quando eu coloco ( res.json(usuario).end(); ) no lugar do if ele traz os dados do usuário.

Dever ser algo com esse aviso que ele da no console.

(node:83843) DeprecationWarning: Mongoose: mpromise (mongoose's default promise library) is deprecated, plug in your own promise library instead: http://mongoosejs.com/docs/promises.html

Porém não entendi como usa essa mpromise.

solução!

Sobre o deprecation warning

https://cursos.alura.com.br/forum/topico-promise-biblioteca-de-promessa-padrao-do-mongoose-e-depreciada-35987

Você usou o modulo de cors que foi usado no link que te passei da propria alura?

Eu não to acreditando nisso, tanta dor de cabeça só por eu esqueci de coloca o (mongoose.Promise = Promise;)

Problema resolvido era só adiciona o mongoose.Promise = Promise; antes de conectar no mongodb, eu tinha acabado de ver em um post do github e já estava vindo compartilha a solução.

E sim usei o cors e ajudou também.