I am using Angular for my Front-End and ExpressJS for my Back-End. I am using Passport for login and registration using JWT. I would like to expand this to accept social logins/registrations.
I have the following (probably trivial and basic) PassportJS setup:
var bcrypt = require('bcrypt');
var ObjectId = require('mongodb').ObjectId;
const jwt = require('jsonwebtoken');
const passport = require('passport');
const ExtractJwt = require('passport-jwt').ExtractJwt;
const JwtStrategy = require('passport-jwt').Strategy;
var jwtOptions = {};
jwtOptions.jwtFromRequest = ExtractJwt.fromAuthHeader();
jwtOptions.secretOrKey = 'secret';
passport.use(new JwtStrategy(jwtOptions, function(jwt_payload, done) {
var collection = db.get().collection('users');
collection.findOne({
_id: new ObjectId(jwt_payload.sub)
}, function(err, user) {
if (err) {
return done(err, false);
}
if (user) {
return done(null, user);
} else {
return done(null, false);
// or you could create a new account
}
});
}));
router.get('/', (req, res) => {
res.send({});
});
router.post('/register', (req, res) => {
var collection = db.get().collection('users');
collection.findOne({'email': req.body.email},
function(err, exists) {
if (err) {
res.send('Error in SignUp: ' + err);
return done(err);
}
if (!_.isEmpty(exists)) {
var errors = [];
if (exists.email === req.body.email) {
errors.push('Your email is linked to another account.')
}
res.send({errors: errors});
} else {
collection.insert({
firstName: req.body.firstName,
lastName: req.body.lastName,
email: req.body.email,
phone: req.body.phone,
password: bcrypt.hashSync(req.body.passwords.password, 10),
address: req.body.address
})
res.send({
'success': 'You have successfully registered!'
});
}
});
});
router.post('/login', (req, res) => {
var collection = db.get().collection('users');
collection.findOne({ email: req.body.email}, function(err, user) {
if (err) {
res.send('Error in Login: ' + err);
return done(err);
} else if (user) {
bcrypt.compare(req.body.password, user.password, function(err, success) {
if (success) {
var payload = {
sub: user._id,
firstName: user.firstName,
lastName: user.lastName
};
res.send({
'token': jwt.sign(payload, jwtOptions.secretOrKey, {
expiresIn: '3d'
})
})
} else {
console.log(success);
res.send({'login': false});
}
})
} else if (!user) {
res.send({'login': false})
}
})
})
router.post('/', (req, res) => {
jwt.verify(req.body.token, jwtOptions.secretOrKey, (err, decoded) => {
if (err) {
res.send(false);
}
if (decoded) {
res.send(true);
}
})
})
module.exports = router;
I am trying to add "Facebook," "Twitter," and other social logins based on passportjs' support library. My issue is, I already have a local db setup "users" where a certain schema is:
{
_id: ObjectID
firstName: string
lastName: string
email: string
phone: number
password: string
address: {
street: string
city: string
state: string
zip: number
}
}
How can I change my user DB or rather, how can I modify my approach to accept multiple forms of login, but still maintain a "schematic" database? In other words:
-
How do I reason between registration/login type (local? Facebook? Twitter?)
-
How do I store multiple registrations in one user Object (one user logs in with facebook, then twitter, but already has a local registration)?
-
How do I handle missing data (I'm sure facebook/twitter will not allow me to just "scrape" their user's addresses from their API, so the address property will be blank in the database (not good!)?
[Note: this project is under heavy development and nothing is live, so if you have a recommendation that'll change the entire architecture of my auth.js file or my 'users' collection to reach my objective, I am all ears.]
via Moshe
No comments:
Post a Comment