Node Express pg-promise Passport-local JWT无法发布

时间:2016-09-19 05:54:19

标签: node.js express passport.js

我是一名Node初学者,他正在尝试通过一些教程和示例来启动和运行。我想构建一个允许本地,Facebook,Twitter和谷歌登录的JSON API,所以我使用passport.js。目前我正在尝试将https://github.com/vitaly-t/pg-promise-demohttp://blog.slatepeak.com/refactoring-a-basic-authenticated-api-with-node-express-and-mongo/合并(对不起代码是如此不匹配的样式)并且遇到了我的登录POST返回的问题:无法发布/ auth / login /本地,当我提供正确的凭据时,如果我的凭据不好,它可以正常工作我真的不明白为什么行为会有所不同,除非本地护照在我没有考虑的后台做某事。我认为相关的文件是:

SERVER.js

'use strict';

var db = require('./db/db.js').db
    , express = require('express')
    , auth = require('./routes/auth')
    , router = express.Router()
    , app = express()
    , routes = require('./routes/routes.js')
    , bodyParser = require('body-parser') //must be before passport
    , config = require('./conf/main'); 

app.use(bodyParser.urlencoded({ extended: true })); 
app.use(bodyParser.json());
app.use('/auth', auth);

// Enable CORS from client-side - Will I need this?
app.use(function(req, res, next) {  
  res.header("Access-Control-Allow-Origin", "*");
  res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization, Access-Control-Allow-Credentials");
  res.header("Access-Control-Allow-Credentials", "true");
  next();
});

//////////////////////////////////////////////
// Users Web API
//////////////////////////////////////////////
app.post('/users/local', routes.userAddLocal);
app.get('/users', routes.getAllUsers); //This should go into the Admin App. Will they both be able to use Postgres at once?


app.listen(config.port, () => {
    console.log('\nReady for requests on http://localhost:' + config.port);
});

AUTH.js

'use strict';
///////////////////////// Passport Setup

var passport = require('passport')
    , LocalStrategy = require('passport-local').Strategy
    , JwtStrategy = require('passport-jwt').Strategy
    , ExtractJwt = require('passport-jwt').ExtractJwt
    , jwt = require('jsonwebtoken')  
    , db = require('../db/db.js').db
    , config = require('../conf/main')
    , express = require('express')
    , bodyParser = require('body-parser') //must be before passport
    , bcrypt = require('bcrypt-nodejs');

const jwtOptions = {  
  // Telling Passport to check authorization headers for JWT
  jwtFromRequest: ExtractJwt.fromAuthHeader(),
  // Telling Passport where to find the secret
  secretOrKey: config.secret
};

passport.use('local', new LocalStrategy({
    usernameField: 'email'
    , passReqToCallback: false
    , session: false //Turn off sessions, this is a stateless REST service using JWT
  },
  function(username, password, done) {
    db.users.findByEmail(username)
        .then(function (user){
            if (!user) { return done(null, false); }
            var pwMatch = bcrypt.compareSync(password, user.password);
            if (!pwMatch) { return done(null, false); }
            return done(null, user);
        })
        .catch(function(error){
            return done(error);
        })
    }
));

passport.use('jwt', new JwtStrategy(jwtOptions, function(payload, done) {  
     console.log("jwt strategy top line");
    db.users.findById(payload._id) //maybe need payload.doc._id or payload.document._id
        .then(function (user){
           if (user) {
                done(null, user);
            } else {
                done(null, false);
            } 
        })
        .catch(function(error){
            return done(err, false);
        })
}));

function generateToken(user) {  
  return jwt.sign(user, config.secret, {
    expiresIn: 10080 // in seconds
  });
};

var authRoutes = express.Router();
authRoutes.use(bodyParser.urlencoded({ extended: true })); 
authRoutes.use(bodyParser.json());
authRoutes.use(passport.initialize());  

authRoutes.post('/login/local', passport.authenticate('local', {
    function(req, res) {
        var tokenObj = auth.generateToken({email: req.body.email, displayName: req.body.DisplayName});
        res.status(201).json({
            token: 'JWT ' + tokenObj,
            user: req.body.displayName
        });
    },
        failureRedirect: '/auth/notauth',
        session: false
    }));

authRoutes.get('/notauth', function (req, res){
    res.status(401).send("Login Failed");
});

module.exports = authRoutes;
module.exports.generateToken = generateToken;

任何人都可以提供的帮助将非常感激。

编辑#1:我尝试重写PORT的路由('login / local'),现在它登录但由于某种原因我没有req和req.user对象可供我使用。我google的所有内容都说我需要包含会话,但我没有使用会话,所以这对我来说不合适。这是新路线:

authRoutes.post('/login/local', passport.authenticate('local',
    function(req, res){
        console.log("authentication successful");
        var tokenObj = generateToken({email: req.body.email, displayName: req.body.DisplayName});
        res.status(201).json({
            token: 'JWT ' + tokenObj,
            user: req.body.displayName
        });
    }
    , {failureRedirect: '/auth/notauth'}
    , {session: false}
));

有人可以告诉我如何解决这个问题,以便根据Passport文档提供req.user吗?

编辑#2:似乎成功函数是一个null,一个对象包含来自users表的db记录。看起来就像我在用户成功登录时返回的内容。不知怎的,我已经破坏了Passport-Local而且它没有这样做。

1 个答案:

答案 0 :(得分:1)

可以使用一些更改:

passport.use('local', new LocalStrategy({
    usernameField: 'email'
   // , passReqToCallback: false
    , passReqToCallback: true
    , session: false //Turn off sessions, this is a stateless REST service using JWT
  },
  //function(username, password, done) {
      function(req, username, password, done) {
    db.users.findByEmail(username)
        .then(function (userRecord){
            if (!userRecord) { return done(null, false); }
            var pwMatch = bcrypt.compareSync(password, userRecord.password);
            if (!pwMatch) { return done(null, false); }
            //return done(null, userRecord);
             return done(null, req, userRecord);
        })
        .catch(function(error){
            return done(error);
        })
    }
));

authRoutes.post('/login/local', passport.authenticate('local',
    function(err, req, userRecord){  
        console.log("authentication successful");
        var tokenObj = generateToken({email: userRecord.email, displayName: userRecord.DisplayName});
        var res = req.res; //nfi why i need this
        res.status(201).json({
            token: 'JWT ' + tokenObj,
            user: userRecord.displayName
        });
    }
    , {failureRedirect: '/auth/notauth'}
    , {session: false}
));