一切都在localhost中运行。在生产中(使用Heroku),我设置了Facebook ID和Secret,但没有收到任何重定向错误。但是,当我尝试进行身份验证时,该网址会更改为https://xxxx.herokuapp.com/xxxx.herokuapp.com/auth/facebook/callback?code=yyyyyy,然后重定向回登录页面而不会将用户登录。
可能导致此问题的任何想法?
Facebook Index.js
var express = require('express');
var passport = require('passport');
var auth = require('../auth.service');
var router = express.Router();
router
.get('/', passport.authenticate('facebook', {
scope: ['email', 'user_about_me'],
failureRedirect: '/signup',
session: false
}))
.get('/callback', auth.addAuthHeaderFromCookie(), passport.authenticate('facebook', {
failureRedirect: '/signup',
session: false
}), auth.setTokenCookie)
;
module.exports = router;
passport.js
exports.setup = function (User, config) {
passport.use(new FacebookStrategy({
clientID: config.facebook.clientID,
clientSecret: config.facebook.clientSecret,
callbackURL: config.facebook.callbackURL,
profileFields: [
'displayName',
'emails',
'gender'
]
},
function(accessToken, refreshToken, profile, done) {
console.log(profile)
User.findOne({
'facebook.id': profile.id
},
function(err, user) {
if (err) {
return done(err);
}
if (!user) {
user = new User({
name: profile.displayName,
firstName: profile.displayName.substr(0, profile.displayName.indexOf(" ")),
nickname: profile.displayName.substr(0, profile.displayName.indexOf(" ")),
lastName: profile.displayName.split(' ').pop(),
gender: profile.gender,
email: profile.emails[0].value,
role: 'user',
username: profile.username,
provider: 'facebook',
facebook: profile._json
});
user.save(function(err) {
if (err) return done(err);
done(err, user);
});
} else {
return done(err, user);
}
})
}
));
};
auth.service.js
var mongoose = require('mongoose');
var passport = require('passport');
var config = require('../config/environment');
var jwt = require('jsonwebtoken');
var expressJwt = require('express-jwt');
var compose = require('composable-middleware');
var User = require('../api/user/user.model');
var validateJwt = expressJwt({ secret: config.secrets.session });
/**
* Attaches the user object to the request if authenticated
* Otherwise returns 403
*/
function isAuthenticated() {
return compose()
// Validate jwt
.use(function(req, res, next) {
// allow access_token to be passed through query parameter as well
if(req.query && req.query.hasOwnProperty('access_token')) {
req.headers.authorization = 'Bearer ' + req.query.access_token;
}
validateJwt(req, res, next);
})
// Attach user to request
.use(function(req, res, next) {
User.findById(req.user._id, function (err, user) {
if (err) return next(err);
if (!user) return res.status(401).send('Unauthorized');
req.user = user;
next();
});
});
}
/**
* Checks if the user role meets the minimum requirements of the route
*/
function hasRole(roleRequired) {
if (!roleRequired) throw new Error('Required role needs to be set');
return compose()
.use(isAuthenticated())
.use(function meetsRequirements(req, res, next) {
if (config.userRoles.indexOf(req.user.role) >= config.userRoles.indexOf(roleRequired)) {
next();
}
else {
res.status(403).send('Forbidden');
}
});
}
/**
* If there is a user, appends it to the req
* else req.user would be undefined
*/
function appendUser() {
return compose()
// Attach user to request
.use(function(req, res, next) {
validateJwt(req, res, function(val) {
if(_.isUndefined(val)) {
User.findById(req.user._id, function(err, user) {
if(err) {
return next(err);
} else if(!user) {
req.user = undefined;
return next();
} else {
req.user = user;
next();
}
});
} else {
req.user = undefined;
next();
}
});
});
}
/**
* Takes the token cookie and adds the header
* for it on the request
*/
function addAuthHeaderFromCookie() {
return compose()
.use(function(req, res, next) {
if(req.cookies.token) {
req.headers.authorization = 'Bearer ' + _.trim(req.cookies.token, '\"');
}
return next();
});
}
/**
* Returns a jwt token signed by the app secret
*/
function signToken(id, role) {
return jwt.sign({ _id: id, role: role }, config.secrets.session, { expiresIn: "5h" });
}
/**
* Set token cookie directly for oAuth strategies
*/
function setTokenCookie(req, res) {
console.log("setting Token Cookie");
if (!req.user) return res.status(404).json({ message: 'Something went wrong, please try again.'});
console.log(req.user);
var token = signToken(req.user._id, req.user.role);
res.cookie('token', JSON.stringify(token));
res.redirect('/');
}
exports.isAuthenticated = isAuthenticated;
exports.hasRole = hasRole;
exports.signToken = signToken;
exports.setTokenCookie = setTokenCookie;
exports.addAuthHeaderFromCookie = addAuthHeaderFromCookie;
exports.appendUser = appendUser;
config index.js
var path = require('path');
var _ = require('lodash');
function requiredProcessEnv(name) {
if(!process.env[name]) {
throw new Error('You must set the ' + name + ' environment variable');
}
return process.env[name];
}
// All configurations will extend these options
// ============================================
var all = {
env: process.env.NODE_ENV,
// Root path of server
root: path.normalize(__dirname + '/../../..'),
// Server port
port: process.env.PORT || 9000,
// Server IP
ip: process.env.IP || '0.0.0.0',
// Should we populate the DB with sample data?
seedDB: false,
// Secret for session, you will want to change this and make it an environment variable
secrets: {
session: process.env.Session_Secret || "xxxx"
},
// List of user roles
userRoles: ['guest', 'user', 'admin'],
// MongoDB connection options
mongo: {
options: {
db: {
safe: true
}
}
},
facebook: {
clientID: process.env.FACEBOOK_ID || 'id',
clientSecret: process.env.FACEBOOK_SECRET || 'secret',
callbackURL: (process.env.DOMAIN || '') + '/auth/facebook/callback'
},
twitter: {
clientID: process.env.TWITTER_ID || 'id',
clientSecret: process.env.TWITTER_SECRET || 'secret',
callbackURL: (process.env.DOMAIN || '') + '/auth/twitter/callback'
},
google: {
clientID: process.env.GOOGLE_ID || 'id',
clientSecret: process.env.GOOGLE_SECRET || 'secret',
callbackURL: (process.env.DOMAIN || '') + '/auth/google/callback'
}
};
// Export the config object based on the NODE_ENV
// ==============================================
module.exports = _.merge(
all,
require('./' + process.env.NODE_ENV + '.js') || {});
auth index.js
var express = require('express');
var passport = require('passport');
var config = require('../config/environment');
var User = require('../api/user/user.model');
// Passport Configuration
require('./local/passport').setup(User, config);
require('./facebook/passport').setup(User, config);
require('./google/passport').setup(User, config);
require('./twitter/passport').setup(User, config);
var router = express.Router();
router.use('/local', require('./local'));
router.use('/facebook', require('./facebook'));
router.use('/twitter', require('./twitter'));
router.use('/google', require('./google'));
module.exports = router;