如何将JWT与passport-facebook结合起来?

时间:2016-09-10 16:46:40

标签: node.js express passport.js jwt passport-facebook

我正在使用passportJS创建一个快速应用程序,我正在尝试使用JSON Web令牌验证我的api:

该应用程序同时具有本地用户和Facebook用户,并以mongoose架构一起定义:

var mongoose = require('mongoose');
var bcrypt   = require('bcrypt-nodejs');

var UserSchema = mongoose.Schema({

    name: {
        type: String
    },
    password: {
        type: String
    },
    local: {
        type: String,
        enum: [
            '0',
            '1'
        ]
    },

    fbId : String,
    fbToken : String,
    fbEmail : String,
    fbName : String

});

UserSchema.pre('save', function(callback) {

    var user = this;

    if (user.local == '1') {

        if (!user.isModified('password')) 
            return callback();

        bcrypt.genSalt(5, function (err, salt) {

            if (err) 
                return callback(err);

            bcrypt.hash(user.password, salt, null, function (err, hash) {

                if (err) 
                    return callback(err);

                user.password = hash;
                callback();
            });
        });
    }
    else {
        callback();
    }
});

UserSchema.methods.verifyPassword = function(password, cb) {
    bcrypt.compare(password, this.password, function(err, isMatch) {
        if (err) return cb(err);
        cb(null, isMatch);
    });
};

module.exports = mongoose.model('User', UserSchema);

主app.js文件包含以下代码,我使用config / passport.js文件(紧随其后)配置护照

var express = require('express');
var app = express();

var passport = require('passport');
var jwt = require('jsonwebtoken');

app.use(passport.initialize());
require('./config/passport')(passport);

app.get('/auth/facebook', passport.authenticate('facebook', {scope:['email']}));

app.get('/auth/facebook/callback',
    passport.authenticate('facebook', {session: false, failureRedirect: '/', successRedirect: '/user'})
);

app.post('/authenticate', function(req, res) {
    User.findOne({
        name: req.body.name
    }, function(err, user) {
        if (err) throw err;

        if (!user) {
            res.send({success: false, msg: 'Authentication failed. User not found.'});
        } else {
            user.verifyPassword(req.body.password, function (err, isMatch) {
                if (isMatch && !err) {
                    var token = jwt.sign(user, "mysecret");
                    res.json({success: true, token: 'JWT ' + token});
                } else {
                    res.send({success: false, msg: 'Authentication failed. Wrong password.'});
                }
            });
        }
    });
});

app.all('/api/*',
    passport.authenticate('jwt', {session: false}),
    function (req, res, next) {
        next();
    });

这是config / passport.js文件,我在其中定义了JwtStrategy和FacebookStrategy。此外,这是我为Facebook用户发出令牌的地方:

var FacebookStrategy = require('passport-facebook').Strategy;

var User = require('../models/user');

var jwt = require('jsonwebtoken');
var JwtStrategy = require('passport-jwt').Strategy;
var ExtractJwt = require('passport-jwt').ExtractJwt;

module.exports = function(passport) {

    var opts = {};
    opts.jwtFromRequest = ExtractJwt.fromAuthHeader();
    opts.secretOrKey = "mysecret";
    passport.use(new JwtStrategy(opts, function (jwt_payload, done) {

        console.log("I'm here!");

        User.findOne({id: jwt_payload.id}, function (err, user) {
            if (err) {
                return done(err, false);
            }
            if (user) {
                done(null, user);
            } else {
                done(null, false);
            }
        });
    }));

    passport.use(new FacebookStrategy(

        {
            clientID        : '...',
            clientSecret    : '...',
            callbackURL     : 'http://localhost:3000/auth/facebook/callback',
            profileFields   : ['id', 'emails', 'name']
        },

        function(accessToken, refreshToken, profile, done) {

            process.nextTick(function() {

                User.findOne({ 'fbId' : profile.id }, function(err, user) {

                    if (err)
                        return done(err);

                    if (user) {
                        var token = jwt.sign(user, "mysecret");
                        console.log('JWT ' + token); //I'm doing this in orer to copy the token and paste it on Postman
                        return done(null, ({success: true, token: 'JWT ' + token}));
                    } else {

                        var newUser = new User();

                        newUser.local = '0';
                        newUser.fbId = profile.id;
                        newUser.fbToken = accessToken;
                        newUser.fbName = profile.name.givenName + " " + profile.name.familyName;
                        newUser.fbEmail = profile.emails[0].value;

                        newUser.save(function(err) {
                            if (err)
                                throw err;

                            var token = jwt.sign(newUser, "mysecret");
                            return done(null, {success: true, token: 'JWT ' + token});
                        });
                    }
                });
            });
        }
    ));
};

本地用户的身份验证和授权工作正常,我已经使用Postman进行了测试:

enter image description here

但是当我用我为facebook用户创建的令牌替换本地用户的令牌时,我没有获得授权:

enter image description here

另外,当我尝试使用facebook用户的令牌访问API时,我甚至没有得到“我在这里!!”控制台日志消息(我已在JwtStrategy中定义),而在本地用户的情况下,我这样做。

任何想法我做错了什么?

提前多多感谢!

编辑:我发现如果我代替用户签署以下对象:

var toSign = user.fbId + user.fbName + user.fbEmail

即。没有fbToken,我获得了授权。

为什么会这样?

0 个答案:

没有答案