tracman-server/config/passport.js

252 lines
7.0 KiB
JavaScript
Raw Normal View History

2017-04-01 11:03:31 -06:00
'use strict';
2017-04-09 21:40:08 -06:00
const
2017-04-01 11:03:31 -06:00
LocalStrategy = require('passport-local').Strategy,
GoogleStrategy = require('passport-google-oauth20').Strategy,
FacebookStrategy = require('passport-facebook').Strategy,
2017-04-09 21:40:08 -06:00
TwitterStrategy = require('passport-twitter').Strategy,
2017-04-19 19:37:00 -06:00
GoogleTokenStrategy = require('passport-google-id-token'),
FacebookTokenStrategy = require('passport-facebook-token'),
TwitterTokenStrategy = require('passport-twitter-token'),
2017-05-08 11:47:53 -06:00
debug = require('debug')('tracman-passport'),
2017-04-26 21:13:14 -06:00
env = require('./env/env.js'),
2017-04-09 21:40:08 -06:00
mw = require('./middleware.js'),
User = require('./models.js').user;
2017-04-01 11:03:31 -06:00
module.exports = (passport)=>{
2017-04-01 11:03:31 -06:00
// Serialize/deserialize users
passport.serializeUser((user,done)=>{
2017-04-01 11:03:31 -06:00
done(null, user.id);
});
passport.deserializeUser((id,done)=>{
User.findById(id, (err,user)=>{
2017-04-01 11:03:31 -06:00
if(!err){ done(null, user); }
else { done(err, null); }
});
});
// Local
passport.use('local', new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
}, (req,email,password,done)=>{
2017-05-08 11:47:53 -06:00
debug(`Perfoming local login for ${email}`);
2017-04-20 21:07:35 -06:00
User.findOne({'email':email})
.then( (user)=>{
2017-04-01 11:03:31 -06:00
// No user with that email
2017-04-01 11:03:31 -06:00
if (!user) {
2017-04-16 19:00:39 -06:00
req.session.next = undefined;
2017-04-19 19:37:00 -06:00
return done( null, false, req.flash('warning','Incorrect email or password.') );
}
// User exists
else {
2017-04-01 11:03:31 -06:00
// Check password
user.validPassword( password, (err,res)=>{
if (err){ return done(err); }
// Password incorrect
if (!res) {
2017-04-16 19:00:39 -06:00
req.session.next = undefined;
2017-04-19 19:37:00 -06:00
return done( null, false, req.flash('warning','Incorrect email or password.') );
}
// Successful login
else {
2017-04-01 11:03:31 -06:00
user.lastLogin = Date.now();
user.save();
return done(null,user);
2017-04-01 11:03:31 -06:00
}
} );
2017-04-01 11:03:31 -06:00
}
2017-04-20 21:07:35 -06:00
})
.catch( (err)=>{
return done(err);
});
2017-04-01 11:03:31 -06:00
}
));
// Social login
function socialLogin(req, service, profileId, done) {
2017-07-14 16:12:06 -06:00
debug(`socialLogin() called for ${service} account ${profileId}`);
2017-04-19 19:37:00 -06:00
let query = {};
query['auth.'+service] = profileId;
2017-04-09 21:40:08 -06:00
2017-04-19 19:37:00 -06:00
// Intent to log in
2017-04-09 21:40:08 -06:00
if (!req.user) {
2017-07-14 16:12:06 -06:00
debug(`Searching for user with query ${query}...`);
2017-04-19 19:37:00 -06:00
User.findOne(query)
.then( (user)=>{
// Can't find user
2017-04-19 19:37:00 -06:00
if (!user){
2017-04-09 21:40:08 -06:00
// Lazy update from old googleId field
if (service==='google') {
2017-07-14 16:12:06 -06:00
User.findOne({ 'googleID': parseInt(profileId,10) })
2017-04-19 19:37:00 -06:00
.then( (user)=>{
// User exists with old schema
2017-04-09 21:40:08 -06:00
if (user) {
2017-07-14 16:12:06 -06:00
debug(`User ${user.id} exists with old schema. Lazily updating...`);
2017-04-09 21:40:08 -06:00
user.auth.google = profileId;
2017-04-19 19:37:00 -06:00
user.googleId = undefined;
user.save()
.then( ()=>{
2017-07-14 16:12:06 -06:00
debug(`Lazily updated ${user.id}...`);
2017-04-19 20:03:45 -06:00
req.session.flashType = 'success';
req.session.flashMessage = "You have been logged in. ";
2017-04-09 21:40:08 -06:00
return done(null, user);
2017-04-19 19:37:00 -06:00
})
.catch( (err)=>{
2017-05-19 01:16:52 -06:00
debug(`Failed to save user that exists with old googleId schema!`);
2017-04-19 19:37:00 -06:00
mw.throwErr(err,req);
return done(err);
});
}
// No such user
else {
2017-07-14 16:12:06 -06:00
debug(`User with ${service} account of ${profileId} not found.`);
2017-05-07 00:11:35 -06:00
req.flash('warning', `There's no user for that ${service} account. `);
2017-04-09 21:40:08 -06:00
return done();
}
2017-04-19 19:37:00 -06:00
})
.catch ( (err)=>{
2017-07-14 16:12:06 -06:00
debug(`Failed to search for user with old googleID of ${profileId}. `);
2017-04-19 19:37:00 -06:00
mw.throwErr(err,req);
return done(err);
});
}
// No googleId either
else {
2017-07-14 16:12:06 -06:00
debug(`Couldn't find ${service} user with profileID ${profileId}.`);
2017-05-07 00:11:35 -06:00
req.flash('warning', `There's no user for that ${service} account. `);
2017-04-09 21:40:08 -06:00
return done();
}
}
// Successfull social login
2017-04-09 21:40:08 -06:00
else {
2017-07-14 16:12:06 -06:00
debug(`Found user: ${user.id}; logging in...`);
2017-04-19 20:03:45 -06:00
req.session.flashType = 'success';
req.session.flashMessage = "You have been logged in.";
2017-04-09 21:40:08 -06:00
return done(null, user);
}
2017-04-19 19:37:00 -06:00
})
.catch( (err)=>{
2017-05-19 01:16:52 -06:00
debug(`Failed to find user with query: ${query}`);
2017-04-19 19:37:00 -06:00
mw.throwErr(err,req);
return done(err);
2017-04-01 11:03:31 -06:00
});
2017-04-09 21:40:08 -06:00
}
2017-04-19 19:37:00 -06:00
// Intent to connect account
2017-04-09 21:40:08 -06:00
else {
2017-07-14 16:12:06 -06:00
debug(`Attempting to connect ${service} account to ${req.user.id}...`);
2017-04-19 19:37:00 -06:00
// Check for unique profileId
2017-07-14 16:12:06 -06:00
debug(`Checking for unique account with query ${query}...`);
2017-04-19 19:37:00 -06:00
User.findOne(query)
.then( (existingUser)=>{
// Social account already in use
if (existingUser) {
2017-07-14 16:12:06 -06:00
debug(`${service} account already in use with user ${existingUser.id}`);
2017-04-19 20:03:45 -06:00
req.session.flashType = 'warning';
req.session.flashMessage = `Another user is already connected to that ${service} account. `;
2017-04-19 19:37:00 -06:00
return done();
}
// Connect to account
else {
2017-07-14 16:12:06 -06:00
debug(`${service} account (${profileId}) is unique; Connecting to ${req.user.id}...`);
2017-04-19 19:37:00 -06:00
req.user.auth[service] = profileId;
req.user.save()
.then( ()=>{
2017-07-14 16:12:06 -06:00
debug(`Successfully connected ${service} account to ${req.user.id}`);
2017-04-19 20:03:45 -06:00
req.session.flashType = 'success';
req.session.flashMessage = `${mw.capitalize(service)} account connected. `;
2017-04-19 19:37:00 -06:00
return done(null,req.user);
} )
.catch( (err)=>{
2017-07-14 16:12:06 -06:00
debug(`Failed to connect ${service} account to ${req.user.id}!`);
2017-04-19 19:37:00 -06:00
return done(err);
} );
}
})
.catch( (err)=>{
2017-07-14 16:12:06 -06:00
debug(`Failed to check for unique ${service} profileId of ${profileId}!`);
2017-04-19 19:37:00 -06:00
mw.throwErr(err,req);
return done(err);
2017-04-19 20:03:45 -06:00
});
2017-04-19 19:37:00 -06:00
2017-04-01 11:03:31 -06:00
}
2017-04-09 21:40:08 -06:00
2017-04-01 11:03:31 -06:00
}
// Google
passport.use('google', new GoogleStrategy({
2017-04-09 21:40:08 -06:00
clientID: env.googleClientId,
clientSecret: env.googleClientSecret,
callbackURL: env.url+'/login/google/cb',
2017-04-01 11:03:31 -06:00
passReqToCallback: true
}, (req, accessToken, refreshToken, profile, done)=>{
2017-04-01 11:03:31 -06:00
socialLogin(req, 'google', profile.id, done);
}
2017-04-19 19:37:00 -06:00
)).use('google-token', new GoogleTokenStrategy({
clientID: env.googleClientId,
passReqToCallback: true
}, (req, parsedToken, googleId, done)=>{
socialLogin(req,'google', googleId, done);
}
2017-04-01 11:03:31 -06:00
));
// Facebook
passport.use('facebook', new FacebookStrategy({
2017-04-09 21:40:08 -06:00
clientID: env.facebookAppId,
clientSecret: env.facebookAppSecret,
callbackURL: env.url+'/login/facebook/cb',
2017-04-01 11:03:31 -06:00
passReqToCallback: true
}, (req, accessToken, refreshToken, profile, done)=>{
2017-04-01 11:03:31 -06:00
socialLogin(req, 'facebook', profile.id, done);
}
2017-04-19 19:37:00 -06:00
)).use('facebook-token', new FacebookTokenStrategy({
clientID: env.facebookAppId,
clientSecret: env.facebookAppSecret,
passReqToCallback: true
}, (req, accessToken, refreshToken, profile, done)=>{
socialLogin(req,'facebook', profile.id, done);
}
2017-04-01 11:03:31 -06:00
));
// Twitter
passport.use(new TwitterStrategy({
2017-04-09 21:40:08 -06:00
consumerKey: env.twitterConsumerKey,
consumerSecret: env.twitterConsumerSecret,
callbackURL: env.url+'/login/twitter/cb',
2017-04-01 11:03:31 -06:00
passReqToCallback: true
}, (req, token, tokenSecret, profile, done)=>{
2017-04-01 11:03:31 -06:00
socialLogin(req, 'twitter', profile.id, done);
}
2017-04-19 19:37:00 -06:00
)).use('twitter-token', new TwitterTokenStrategy({
consumerKey: env.twitterConsumerKey,
consumerSecret: env.twitterConsumerSecret,
passReqToCallback: true
}, (req, token, tokenSecret, profile, done)=>{
socialLogin(req,'twitter', profile.id, done);
}
2017-04-01 11:03:31 -06:00
));
return passport;
};