Authentication 如何使用护照后的承诺登录。通过社会服务验证。KeystoneJS+;护照
除了我需要在这里发表,可能有人会帮助我,我会很感激的 我需要获得解锁应用程序中代码的帮助 我有两个服务,它们在得到回调后在会话中存储用户信息,并重定向到名为/auth/confirm/的页面 这是twitter auth的例子,对我来说非常适合Authentication 如何使用护照后的承诺登录。通过社会服务验证。KeystoneJS+;护照,authentication,express,mongoose,keystonejs,passport.js,Authentication,Express,Mongoose,Keystonejs,Passport.js,除了我需要在这里发表,可能有人会帮助我,我会很感激的 我需要获得解锁应用程序中代码的帮助 我有两个服务,它们在得到回调后在会话中存储用户信息,并重定向到名为/auth/confirm/的页面 这是twitter auth的例子,对我来说非常适合 const keystone = require('keystone'); const passport = require('passport'); const passportTwitterStrategy = require('passport-t
const keystone = require('keystone');
const passport = require('passport');
const passportTwitterStrategy = require('passport-twitter').Strategy;
const User = keystone.list('User');
const credentials = {
consumerKey: process.env.TWITTER_CONSUMER_KEY,
consumerSecret: process.env.TWITTER_CONSUMER_SECRET,
callbackURL: process.env.TWITTER_CALLBACK_URL,
includeEmail: true
};
exports.authenticateUser = function(req, res, next) {
const redirect = '/auth/confirm';
const twitterStrategy = new passportTwitterStrategy(credentials, function(accessToken, refreshToken, profile, done) {
done(null, {
accessToken: accessToken,
refreshToken: refreshToken,
profile: profile
});
});
// Pass through authentication to passport
passport.use(twitterStrategy);
// Save user data once returning from Twitter
if (req.query.hasOwnProperty('cb')) {
passport.authenticate('twitter', { session: false }, function(err, data, info) {
if (err || !data) {
return res.redirect('/signin');
}
const name = data.profile && data.profile.displayName ? data.profile.displayName.split(' ') : [];
req.session.auth = {
type: 'twitter',
name: {
first: name.length ? name[0] : '',
last: name.length > 1 ? name[1] : ''
},
email: data.profile._json.email,
profileId: data.profile.id,
username: data.profile.username,
avatar: data.profile._json.profile_image_url.replace('_normal', ''),
accessToken: data.accessToken,
refreshToken: data.refreshToken
};
return res.redirect(redirect);
})(req, res, next);
// Perform initial authentication request to Twitter
} else {
passport.authenticate('twitter')(req, res, next);
}
};
现在,如果从用户处获得访问权限,我们将twitter用户存储在req.session.auth中。但是现在我有一个大问题。据我所知,Mongoose用户模型也是异步工作的,当我试图通过twitter profileID检查现有用户时,我无法得到正确的结果,因为它首先进入,然后回调,不等待检查结果。我不想让这个库成为异步库,但要避免异步库,因为对于一个特性来说,它太大了。我更喜欢使用新版本中的本机承诺。我不确定这一切,也不知道如何以最好的表现,非常期待有人会帮助我。无论如何-谢谢你的阅读
const keystone = require('keystone');
const User = keystone.list('User');
module.exports = (req, res, next) => {
const locals = res.locals;
locals.authUser = req.session.auth;
// Set existing user if already logged in
locals.existingUser = req.user || false;
// Reject request if no auth data is stored in session
if (!locals.authUser) {
console.log('[auth.confirm] - No auth data detected, redirecting to signin.');
console.log('------------------------------------------------------------');
return res.redirect('/');
}
const authenticateUser = new Promise((resolve, reject) => {
if (locals.existingUser) resolve(true);
console.log('[auth.confirm] - Searching for existing users via [' + locals.authUser.type + '] profile id...');
console.log('------------------------------------------------------------');
User.model.findOne()
.where('services.' + locals.authUser.type + '.profileId', locals.authUser.profileId)
.exec((err, user) => {
if (err) {
console.log('[auth.confirm] - Error finding existing user via profile id.', err);
console.log('------------------------------------------------------------');
reject(err);
}
if (user) {
console.log('[auth.confirm] - Found existing user via [' + locals.authUser.type + '] profile id...');
console.log('------------------------------------------------------------');
locals.existingUser = user;
resolve(true);
}
resolve(false);
});
});
authenticateUser
.then(result => {
if (result) return result;
User.model.findOne()
.where('email', locals.authUser.email)
.exec((err, user) => {
if (err) {
throw err;
}
if (user) {
locals.existingUser = user;
}
return false;
});
})
.then(result => {
if (result) return result;
if (locals.existingUser) {
const userData = {
email: locals.authUser.email,
services: locals.existingUser.services || {}
};
userData.services[locals.authUser.type] = {
isConfigured: true,
profileId: locals.authUser.profileId,
username: locals.authUser.username,
avatar: locals.authUser.avatar,
accessToken: locals.authUser.accessToken,
refreshToken: locals.authUser.refreshToken
};
locals.existingUser.set(userData);
locals.existingUser.save(err => {
if (err) throw err;
return true;
});
} else {
const userData = {
name: {
first: locals.authUser.name.first,
last: locals.authUser.name.last
},
email: locals.authUser.email,
password: Math.random().toString(36).slice(-8),
services: {}
};
userData.services[locals.authUser.type] = {
isConfigured: true,
profileId: locals.authUser.profileId,
username: locals.authUser.username,
avatar: locals.authUser.avatar,
accessToken: locals.authUser.accessToken,
refreshToken: locals.authUser.refreshToken
};
locals.existingUser = new User.model(userData);
locals.existingUser.save(err => {
if (err) throw err;
return true;
});
}
})
.then(result => {
console.log('[auth.confirm] - Signing in user...');
console.log('------------------------------------------------------------');
const onSuccess = user => {
console.log('[auth.confirm] - Successfully signed in.');
console.log('------------------------------------------------------------');
return res.redirect(req.cookies.target || '/keystone');
};
const onFail = err => {
console.log('[auth.confirm] - Failed signing in.', err);
console.log('------------------------------------------------------------');
if (err) throw err;
return res.redirect('/');
};
keystone.session.signin(String(locals.existingUser._id), req, res, onSuccess, onFail);
});
return authenticateUser;
};
现在我的代码如下。它的工作和异步,但无论如何,我会很高兴得到别人的审查
const keystone = require('keystone');
const User = keystone.list('User');
module.exports = (req, res, next) => {
const authUser = req.session.auth;
// Reject request if no auth data is stored in session
if (!authUser) {
return res.redirect('/');
}
// Set existing user if already logged in
if (req.user) return doSignIn(req.user);
User.model.findOne()
.where('services.' + authUser.type + '.profileId', authUser.profileId)
.exec()
.then(user => {
if (user) return doSignIn(user);
User.model.findOne()
.where('email', authUser.email)
.exec()
.then(user => {
return createOrUpdateUser(user);
}, err => {
if (err) {
throw err;
}
});
}, err => {
throw err;
});
function doSignIn(user) {
const onSuccess = user => {
return res.redirect(req.cookies.target || '/keystone');
};
const onFail = err => {
if (err) throw err;
return res.redirect('/');
};
keystone.session.signin(String(user._id), req, res, onSuccess, onFail);
}
function createOrUpdateUser(user) {
if (user) {
const userData = {
email: authUser.email,
services: user.services || {}
};
userData.services[authUser.type] = {
isConfigured: true,
profileId: authUser.profileId,
username: authUser.username,
avatar: authUser.avatar,
accessToken: authUser.accessToken,
refreshToken: authUser.refreshToken
};
user.set(userData);
user.save((err, user) => {
if (err) throw err;
return doSignIn(user);
});
} else {
const userData = {
name: {
first: authUser.name.first,
last: authUser.name.last
},
email: authUser.email,
password: Math.random().toString(36).slice(-8),
services: {}
};
userData.services[authUser.type] = {
isConfigured: true,
profileId: authUser.profileId,
username: authUser.username,
avatar: authUser.avatar,
accessToken: authUser.accessToken,
refreshToken: authUser.refreshToken
};
const newUser = new User.model(userData);
newUser.save((err, user) => {
if (err) throw err;
return doSignIn(user);
});
}
}
};