From facebook token to jwt token - angularjs

I'm using the passport module to authenticate a user and generate a jwt token.
Now I want to make facebook login possible. I'm in the phase that I get a fb token and facebook id.
What am I supposed to do with this info? Currently I make a new user that has a variable with facebook id but without a password.
Without a password I can't generate a jwt token, thus I cannot login.
How does this work?
My front end is angular and my API is written with nodejs, express & mongoose.
Passport code:
passport.use(new LocalStrategy(
function(username, password, done) {
User.findOne({ username: username }, function (err, user) {
if (err) { return done(err); }
if (!user) {
return done(null, false, { message: 'Incorrect username.' });
}
if (!user.validPassword(password)) {
return done(null, false, { message: 'Incorrect password.' });
}
return done(null, user);
});
}
));
generatejwt code:
UserSchema.methods.generateJWT = function() {
// set expiration to 60 days
var today = new Date();
var exp = new Date(today);
exp.setDate(today.getDate() + 60);
return jwt.sign({
_id: this._id,
username: this.username,
exp: parseInt(exp.getTime() / 1000),
}, 'SECRET');
};

You need to create 2 routes :
1) This will be called to login to facebook.
2)Callback route if the user authentication is successful.(This callback route needs to be registered in the facebook developer portal.
//Facebook Login
app.route('/auth/facebook')
.get(passport.authenticate('facebook', { scope: 'email' }));
// Callback
app.route('/auth/facebook/callback')
.get(passport.authenticate('facebook'),users.generateJWT);
Define a facebook strategy that will store the user details (id, token, email) in your database
var facebookStrategy = new FacebookStrategy({
clientID: cfg.facebook.clientID,
clientSecret: cfg.facebook.clientSecret,
callbackURL: cfg.facebook.callbackURL,
profileFields: ['id', 'email', 'first_name', 'last_name']
},
function(token, refreshToken, profile, done) {
console.log("Token: "+ token);
console.log("RefreshToken: "+ refreshToken);
console.log("profile: "+ profile);
process.nextTick(function() {
User.findOne({ 'facebook.id': profile.id }, function(err, user) {
if (err)
return done(err);
if (user) {
console.log("User Found");
return done(null, user);
} else {
console.log("Creating user");
var newUser = new User();
console.log("Token: "+ token);
newUser.facebook.id = profile.id;
newUser.facebook.token = token;
newUser.facebook.name = profile.name.givenName + ' ' + profile.name.familyName;
newUser.facebook.email = (profile.emails[0].value || '').toLowerCase();
newUser.save(function(err) {
if (err)
throw err;
return done(null, newUser);
});
}
});
});
});
In the controller, write the below code for callback route:
/**
* Generate JWT Token
*/
exports.generateJWT = function(req, res) {
var token;
token = req.user.generateJwt();
res.status(200);
res.json({
"token" : token
});
};

Related

How to get access token? vk

How I can get access token which vk.com sends to me when I login on website?
I want to get this token and save this to my DB,after this I want to use methods to get info about the user(like city,hobbies,groups) etc. There are list of objects https://vk.com/dev/objects/user It says Note — all fields that use current user information require passing access_token in the request. I don't have any ideas what to do after auth complete,there are relly zero info in the Internet and youtube to get info about.
const passport = require('passport');
const GoogleStrategy = require('passport-google-oauth20').Strategy;
const keys = require('./key');
const User = require('../models/user-model');
const VKontakteStrategy = require('passport-vkontakte').Strategy;
const vktoken = require('vk-token');
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.findById(id).then((user) => {
done(null, user);
});
});
passport.use(
new GoogleStrategy({
// options for google strategy
clientID: keys.google.clientID,
clientSecret: keys.google.clientSecret,
callbackURL: '/auth/google/redirect'
}, (accessToken, refreshToken, profile, done) => {
// check if user already exists in our own db
User.findOne({googleid: profile.id}).then((currentUser) => {
if(currentUser){
// already have this user
console.log('user is: ', currentUser);
done(null, currentUser);
} else {
// if not, create user in our db
new User({
googleid: profile.id,
username: profile.displayName,
thumbnail: profile._json.image.url
}).save().then((newUser) => {
console.log('created new user: ', newUser);
done(null, newUser);
});
}
});
})
);
passport.use(
new VKontakteStrategy({
clientID: keys.vk.clientID,
clientSecret: keys.vk.clientSecret,
callbackURL: '/auth/vk/redirect'
}, (accessToken, refreshToken, params, profile, done) => {
User.findOne({vkid: profile.id}).then((currentUser)=>{
if(currentUser){
console.log('user is:' ,currentUser);
done(null, currentUser);
} else{
new User({
vkid: profile.id,
username: profile.displayName,
}).save().then((newUser) => {
console.log('created new user: ', newUser);
done(null, newUser);
});
}
});
})
)

node.js code that works in Windows is not working on Mac

I have an app that uses Passport to login users through FB, Twitter and Google. It works fine on Windows. Now I had to move to Mac (Sierra).
The logins are not working. I get a "Error at Strategy.parseErrorResponse."
Does anyone know what could be the reason?
// This is the Facebook strategy...
=========================================================================
// FACEBOOK ================================================================
// =========================================================================
passport.use(new FacebookStrategy({
clientID : configAuth.facebookAuth.clientID,
clientSecret : configAuth.facebookAuth.clientSecret,
callbackURL : configAuth.facebookAuth.callbackURL,
passReqToCallback : true // allows us to pass in the req from our route (lets us check if a user is logged in or not)
},
function(req, token, refreshToken, profile, done) {
// asynchronous
process.nextTick(function() {
// check if the user is already logged in
if (!req.user) {
User.findOne({ 'facebook.id' : profile.id }, function(err, user) {
if (err)
return done(err);
if (user) {
// if there is a user id already but no token (user was linked at one point and then removed)
if (!user.facebook.token) {
user.facebook.token = token;
user.facebook.name = profile.name.givenName + ' ' + profile.name.familyName;
// user.facebook.email = profile.emails[0].value;
user.save(function(err) {
if (err)
throw err;
return done(null, user);
});
}
return done(null, user); // user found, return that user
} else {
// if there is no user, create them
var newUser = new User();
newUser.facebook.id = profile.id;
newUser.facebook.token = token;
newUser.facebook.name = profile.name.givenName + ' ' + profile.name.familyName;
// newUser.facebook.email = profile.emails[0].value;
newUser.save(function(err) {
if (err)
throw err;
return done(null, newUser);
});
}
});
} else {
// user already exists and is logged in, we have to link accounts
var user = req.user; // pull the user out of the session
user.facebook.id = profile.id;
user.facebook.token = token;
user.facebook.name = profile.name.givenName + ' ' + profile.name.familyName;
// user.facebook.email = profile.emails[0].value;
user.save(function(err) {
if (err)
throw err;
return done(null, user);
});
}
});
}));
This problem was solved by changing the versions of the dependencies to latest versions.

User Authentication on MEAN stack application

I am building an API using the MEAN stack and am working on the login and signup functions.
And I want to respond with a json string as follows
{
success: 0,
message: ""
}
success:1 for successful login and 0 otherwise.
My authenticate.js is as follows
module.exports = function(passport){
//log in
router.post('/login', passport.authenticate('login', {
//success
//failure
}));
//sign up
router.post('/signup', passport.authenticate('signup', {
//success
//failure
}));
//log out
router.get('/signout', function(req, res) {
req.logout();
res.redirect('/');
});
return router;
}
My passport.init.js middleware is as follows
var mongoose = require('mongoose');
var User = mongoose.model('User');
var LocalStrategy = require('passport-local').Strategy;
var bCrypt = require('bcrypt-nodejs');
module.exports = function(passport){
// Passport needs to be able to serialize and deserialize users to support persistent login sessions
passport.serializeUser(function(user, done) {
console.log('serializing user:',user.username);
done(null, user._id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
console.log('deserializing user:',user.username);
done(err, user);
});
});
passport.use('login', new LocalStrategy({
passReqToCallback : true
},
function(req, username, password, done) {
// check in mongo if a user with username exists or not
User.findOne({ 'username' : username },
function(err, user) {
// In case of any error, return using the done method
if (err)
return done(err);
// Username does not exist, log the error and redirect back
if (!user){
console.log('User Not Found with username '+username);
return done(null, false);
}
// User exists but wrong password, log the error
if (!isValidPassword(user, password)){
console.log('Invalid Password');
return done(null, false); // redirect back to login page
}
// User and password both match, return user from done method
// which will be treated like success
return done(null, user);
}
);
}
));
passport.use('signup', new LocalStrategy({
passReqToCallback : true // allows us to pass back the entire request to the callback
},
function(req, username, password, done) {
// find a user in mongo with provided username
User.findOne({ 'username' : username }, function(err, user) {
// In case of any error, return using the done method
if (err){
console.log('Error in SignUp: '+err);
return done(err);
}
// already exists
if (user) {
console.log('User already exists with username: '+username);
return done(null, false);
} else {
// if there is no user, create the user
var newUser = new User();
// set the user's local credentials
newUser.username = username;
newUser.password = createHash(password);
// save the user
newUser.save(function(err) {
if (err){
console.log('Error in Saving user: '+err);
throw err;
}
console.log(newUser.username + ' Registration succesful');
return done(null, newUser);
});
}
});
})
);
var isValidPassword = function(user, password){
return bCrypt.compareSync(password, user.password);
};
// Generates hash using bCrypt
var createHash = function(password){
return bCrypt.hashSync(password, bCrypt.genSaltSync(10), null);
};
};
Please help me out in passing the JSON string accordingly
Using Express, all you have to do is to execute res.json inside any controller, passing it any JavaScript object. Express will automatically convert it to JSON and return it to the user.
return res.json({ success: 0, message: '' }

Passportjs Google Authentication Failing

I am trying to debug where in my Google OAuth2 setup is failing to even render the OAuth login window to sign in with my credentials. Despite following the documentation, it appears that my code is failing right when passport.authorize('google', { scope : ['profile'] }) is called as the route is triggered and then has an endless loop until it timesout with an error GET http://localhost:3000/auth/google net::ERR_CONNECTION_REFUSED.
I tried to look through my passport setup, but nothing seems to be different between the code examples in the documentation and not sure where the error would come from as nothing is being logged in my terminal for my console logs outside of Google Auth triggered
Here is the PassportJS setup:
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var GoogleStrategy = require('passport-google-oauth20').Strategy;
var models = require('../app/models/db-index');
var configAuth = require('./auth');
var bcrypt = require('bcrypt-nodejs');
/*==== Passport Configuration ====*/
// Serialize sessions
passport.serializeUser(function(user, done) {
console.log("User ID: " + user.userId + " is serializing");
done(null, user.userId);
});
passport.deserializeUser(function(userId, done) {
models.User.find({
where: {
userId: userId
}
}).then(function(user) {
console.log("User ID: " + user.userId + " is deserializing");
done(null, user);
}).error(function(err) {
done(err, null);
});
});
/*==== Local Configuration ====*/
//Login logic
passport.use('local', new LocalStrategy({
passReqToCallback: true,
usernameField: 'email'
}, function(req, email, password, done) {
//Find user by email
models.User.findOne({
where: {
email: req.body.email
}
}).then(function(user) {
if (!user) {
done(null, false, {
message: 'The email you entered is incorrect'
}, console.log("Unknown User"));
} else if (!user.validPassword(password)) {
done(null, false, console.log("Incorrect Password"));
} else {
console.log("User match");
done(null, user);
}
}).catch(function(err) {
console.log("Server Error");
return done(null, false);
});
}));
//Sign Up Logic
passport.use('local-signup', new LocalStrategy({
passReqToCallback: true,
usernameField: 'email'
}, function(req, email, password, done) {
models.User.findOne({
where: {
email: email
}
}).then(function(existingUser) {
if (existingUser)
return done(null, false, req.flash('error', 'Email already exists.'));
if (req.user && password === confirmPassword) {
var user = req.user;
user.firstName = firstName;
user.lastName = lastName;
user.email = email;
user.password = models.User.generateHash(password);
user.save().catch(function(err) {
throw err;
}).then(function() {
done(null, user, req.flash('error', 'All fields need to be filled in'));
});
} else {
var newUser = models.User.build({
firstName: req.body.firstName,
lastName: req.body.lastName,
email: req.body.email,
password: models.User.generateHash(password)
});
newUser.save().then(function() {
done(null, newUser);
}).catch(function(err) {
done(null, false, console.log(err));
});
}
}).catch(function(e) {
done(null, false, req.flash('error', 'All fields need to be filled in'), console.log(e.email + e.message));
})
}));
/*==== Google Configuration ====*/
passport.use(new GoogleStrategy({
clientID: 'client-id-hash.apps.googleusercontent.com',
clientSecret: 'secret-hash',
callbackURL: 'http://localhost:3000/auth/google/callback'
}, function(accessToken, refreshToken, profile, cb) {
console.log('First Google Config fired');
models.ExternalAccount.findOrCreate({
externalSourceId: profile.id
}).then(function(err, externalAccount){
console.log('Sequelize Google query fired without issues');
return cb(err, externalAccount)
});
}));
module.exports = passport;
Here are my routes:
var express = require('express');
var siteRoutes = express.Router();
var path = require('path');
var passport = require(path.resolve(__dirname, '..', '..', './config/passport.js'));
/*==== /AUTH/GOOGLE ====*/
siteRoutes.route('/auth/google')
.get(function(req, res){
console.log('Google Auth triggered');
passport.authorize('google', { scope : ['profile'] })
});
/*==== /AUTH/GOOGLE/CALLBACK ====*/
siteRoutes.route('/auth/google/callback')
.get(function(req, res){
passport.authorize('google', {
successRedirect : '/app',
failureRedirect : '/login',
failureFlash: 'Invalid Google credentials.'
});
});
The authenticate call is itself a middleware. And as far as I can tell from the documentation, there is no authorize call at all. Your callback route should therefore look something like this:
/*==== /AUTH/GOOGLE/CALLBACK ====*/
siteRoutes.route('/auth/google/callback')
.get(passport.authenticate('google', {
successRedirect : '/app',
failureRedirect : '/login',
failureFlash: 'Invalid Google credentials.'
}));

Node.js passport-jwt how to send token in a cookie?

1) Once user is authenticated, How can I set the token in a cookie so that user does not send username password in each request?
2) What is the ideal way of sending token to the client side?
apiRoutes.post('/authenticate', function (req, res) {
User.findOne({
email: req.body.email
}, function (err, user) {
if (err) throw err;
if (!user) {
res.send({ success: false, message: 'Authentication failed. User not found.' });
} else {
// Check if password matches
user.comparePassword(req.body.password, function (err, isMatch) {
if (isMatch && !err) {
// Create token if the password matched and no error was thrown
var claims = {
sub: user._id,
email:user.email,
iss: 'https://NodeLogin.com',
permissions: user.role
};
var token = jwt.sign(claims, config.secret, {
expiresIn: 60 // in seconds
});
res.json({ success: true, token: 'JWT ' + token });
} else {
res.send({ success: false, message: 'Authentication failed. Passwords did not match.' });
}
});
}
});
});
apiRoutes.get('/dashboard',
passport.authenticate('jwt', { session: false }), function (req, res) {
res.send('Worked' + req.user._id + '.');
});
you should follow code:
user.comparePassword(req.body.password, function (err, isMatch) {
if (isMatch && !err) {
// Create token if the password matched and no error was thrown
var claims = {
sub: user._id,
email:user.email,
iss: 'https://NodeLogin.com',
permissions: user.role
};
var token = jwt.sign(claims, config.secret, {
expiresIn: 60 // in seconds
});
res.cookie('jwt',token); // add cookie here
res.json({ success: true, token: 'JWT ' + token });
} else {
res.send({ success: false, message: 'Authentication failed. Passwords did not match.' });
}
});
and passport config:
var cookieExtractor = function(req) {
var token = null;
if (req && req.cookies) token = req.cookies['jwt'];
return token;
};
module.exports = function(passport) {
var opts = {};
opts.jwtFromRequest = cookieExtractor; // check token in cookie
opts.secretOrKey = config.secret;
passport.use(new JwtStrategy(opts, function(jwt_payload, done) {
User.findOne({id: jwt_payload.id}, function(err, user) {
if (err) {
return done(err, false);
}
if (user) {
done(null, user);
} else {
done(null, false);
}
});
}));
};
it's working for me :)

Resources