我有一个Express应用程序,它最初通过本地策略通过Passport管理身份验证。为此,我刚刚添加了Google登录/帐户创建功能,并且几乎所有文档都可以正常运行。
我遇到的问题是,用户可以使用Google策略创建帐户,但我无法完全做到这一点,因此经过身份验证的用户(通过本地策略)只能向其帐户添加其他Google详细信息,以便他们可以使用本地策略或Google策略。
在“ index.js”中,我定义了我的路线,定义了const passportGoogle = require('../handlers/google');
,其中包含了我的Google策略的详细信息。
在index.js
的更下方,我有authenticate
和authorise
路线:
/* GOOGLE ROUTES FOR AUTHENTICATION*/
router.get('/google',
passportGoogle.authenticate('google',
{ scope: ['profile', 'email'] }));
router.get('/google/callback',
passportGoogle.authenticate('google',
{
failureRedirect: '/',
failureFlash: 'Failed Login!',
successRedirect: '/account',
successFlash: 'You are logged in!'
}
));
/* GOOGLE ROUTES FOR AUTHORISATION - IE A USER IS ALREADY LOGGED IN AND WANTS TO CONNECT THEIR GOOGLE ACCOUNT*/
// send to google to do the authentication
router.get('/connect/google',
passportGoogle.authorize('google',
{ scope : ['profile', 'email'] }
));
// the callback after google has authorized the user
router.get('/connect/google/callback',
passportGoogle.authorize('google', {
successRedirect : '/profile',
failureRedirect : '/'
})
);
如上所述,我的Google策略是在google.js
中定义的:
var passport = require('passport');
var GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;
var User = require('../models/User');
passport.use(new GoogleStrategy({
clientID: process.env.GOOGLE_CLIENTID,
clientSecret: process.env.GOOGLE_CLIENTSECRET,
callbackURL: "http://127.0.0.1:7777/google/callback"
},
// google will send back the token and profile
function(req, token, refreshToken, profile, done) {
// console.log('here is res.locals.user'+ res.locals.user);
console.log('here is req.user'+ req.user);
// asynchronous
process.nextTick(function() {
// check if the user is already logged in
if (!req.user) {
console.log('THERE IS NO REQ.USR');
// find the user in the database based on their facebook id
User.findOne({ 'google.id': profile.id }, function(err, user) {
// if there is an error, stop everything and return that
// ie an error connecting to the database
if (err)
return done(err);
// if the user is found, then log them in
if (user) {
return done(null, user); // user found, return that user
} else {
// if there is no user found with that google id, create them
var newUser = new User();
// set all of the facebook information in our user model
newUser.google.id = profile.id;
newUser.google.token = token;
newUser.name = profile.displayName;
newUser.email = profile.emails[0].value;
// save our user to the database
newUser.save(function(err) {
if (err)
throw err;
// if successful, return the new user
return done(null, newUser);
});
}
});
} else {
const user = User.findOneAndUpdate(
{ _id: req.user._id },
{ $set: {"user.google.id":profile.id,
"user.google.token":accessToken,
"user.google.name":profile.displayName,
"user.google.email":profile.emails[0].value
}
},
{ new: true, runValidators: true, context: 'query' }
)
.exec();
return done(null, user);
req.flash('success', 'Google details have been added to your account');
res.redirect(`back`);
}
});
}));
module.exports = passport;
但是,当用户登录并跟随到/connect/google
的链接时,始终会创建一个新用户,而不是更新其详细信息。我的日志记录显示Google策略中的if (!req.user)
条件一直在触发,但是我不确定为什么会这样,因为用户确实已登录。
任何帮助,不胜感激!
答案 0 :(得分:0)
为了访问回调中的请求,您需要在GoogleStrategy配置对象中使用big
标志:
small
如果省略此标志,则预期的回调形式为
passReqToCallback: true
因此,您的代码正在Google寄回的accessToken上寻找passport.use(new GoogleStrategy({
clientID: process.env.GOOGLE_CLIENTID,
clientSecret: process.env.GOOGLE_CLIENTSECRET,
callbackURL: "http://127.0.0.1:7777/google/callback",
passReqToCallback: true
},
// google will send back the token and profile
function(req, token, refreshToken, profile, done) {
// console.log('here is res.locals.user'+ res.locals.user);
console.log('here is req.user'+ req.user);
....
})
属性,该属性应始终失败。我也提出这一点是因为,如果我是对的,那么您的功能的其他部分也应该行为不当。 (就像function(accessToken, refreshToken, profile, done){...}
应该总是失败,因为该函数是用user
作为其第四个参数而不是User.findOne({'google.id': profile.id})
来调用的。)