I am using Sails version 0.11 and trying to configure app with jwt authentication.
config/passport.js
var passport = require('passport');
var jwt = require('express-jwt');
module.exports = {
http: {
customMiddleware: function(app) {
console.log('express midleware for passport');
app.use(jwt({ secret: sails.config.session.secret, credentialsRequired: false}).unless({path: ['/login']}));
app.use(passport.initialize());
app.use(passport.session());
}
}
};
services/passport.js
/* other code */
passport.serializeUser(function(user, done) {
console.log(user);
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
console.log(id);
findById(id, function(err, user) {
if (err)
done(err);
else if (!user) {
done(null, false);
}
else
done(null, user);
});
});
AuthController.js
module.exports = {
login: function(req, res) {
passport.authenticate('local', function(err, info, user) {
if (err) {
return res.send(err);
}
else if (!user) {
return res.send(info);
}
else {
var token = jwt.sign(user, sails.config.session.secret, {
expiresInMinutes: 5 // expires in 5 minutes
});
res.json({
success: true,
message: 'Enjoy your token!',
token: token
});
}
})(req, res);
},
me: function(req, res) {
res.send(req.user);
}
}
Why is my desesializedUser function never called? What is wrong in my code?
Do you configure the strategy for passport?
In the passport doc, the below is mentioned.
Before authenticating requests, the strategy (or strategies) used by an application must be configured.
Related
I'm trying to use passportJS to authenticate with the github-strategy. I've previously used passportJS with success, but not with the github-strategy, though I don't figure it should be much different. /viewData is the route in which I'm testing for authentication.
The strategy authenticates successfully and puts the data in the DB and when I serialize and deserialize the user data is in fact there. The problem comes when I try to check in any route after if the req.isAuthenticated() or even if req.session.passport.user exists and it returns false and undefined respectively. The weird thing the same check in app.js after I've redirected through /testAuth the authentication logs correctly with the true and id#. So I feel like its some issue with express-session or the passport integration with that that's breaking it, but I can't find it. I've been on this for a long time so hopefully someone can help me.
app.use(cookieParser('test'));
app.use(session({
secret: 'test',
resave: false,
saveUninitialized: true
}));
//pasport setup
app.use(passport.initialize());
app.use(passport.session());
// Passport init
passport.use(new GithubStrategy({
clientID: config.github.clientID,
clientSecret: config.github.clientSecret,
callbackURL: config.github.callbackURL },
function(accessToken, refreshToken, profile, done) {
User.findOne({ oauthID: profile.id }, function(err, user) {
if(err) {
console.log(err); // handle errors!
}
if (!err && user !== null) {
done(null, user);
} else {
user = new User({
oauthID: profile.id,
name: profile.displayName,
created: Date.now()
});
user.save(function(err) {
if(err) {
console.log(err); // handle errors!
} else {
console.log("saving user ...");
done(null, user);
}
});
}
});
}
));
// test authentication
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) { return next(); }
console.log("Not Authenticated", req.user);
res.redirect('/');
}
app.get('/testAuth', ensureAuthenticated, function(req, res){
User.findById(req.session.passport.user, function(err, user) {
if(err) {
console.log(err); // handle errors
} else {
res.redirect('/viewData');
}
});
});
//auth pages
app.get('/auth/github',
passport.authenticate('github'),
function(req, res){});
app.get('/auth/github/callback',
passport.authenticate('github', { failureRedirect: '/' }),
function(req, res) {
res.redirect('/testAuth');
});
// serialize and deserialize for session
passport.serializeUser(function(user, done) {
console.log('serializeUser: ' + user);
done(null, user._id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user){
console.log('deserializeUser: ' + user);
if(!err) done(null, user);
else done(err, null);
});
});
So this is a weird one, but I was fixing something else that was weird and in doing so solved this problem. I just moved my
app.use('/', index);
app.use('/viewData', viewData);
To below all the passport code and it works now.
I'm trying to get a handle on user authentication with PassportJS, and I cannot get it to work my database setup.
I'm using MongoDB without Mongoose, and I can't get the LocalStrategy module to work.
Hopefully my database queries aren't too cumbersome to read.
Local Strategy:
passport.use(new LocalStrategy(
function(username, password, done) {
//Fire up database
mongo.connect("mongodb://localhost:27017/formulas", function(e, db) {
if (e) {return next(e);}
var col = db.collection("users");
//Do a database query to find a record by username
col.findOne({"username": username}, function(err, user){
if (err) { return done(err);}
if(!user) {
return done(null, false, { message: "Please check your log in credentials." });
}
//if it exists call done() object with user information
bcrypt.compare(password, user.password, function(err, res){
if (err) throw err;
if (res == true) {
return done(null, {username: username, password: password});
} else {
return done(null, false, { message: "Invalid password."});
}
});
});
});
}));
I call passport.authenticate() like this:
router.post('/login',
passport.authenticate('local', {successRedirect:'/', failureRedirect:'/about',failureFlash: false}),
function(req, res){
console.log(req.body);
console.log(req.user);
console.log("The user was logged");
});
SerializeUser and deserializeUser look like this:
passport.serializeUser(function(user, done) {
done(null, user.username);
});
passport.deserializeUser(function(id, done) {
mongo.connect("mongodb://localhost:27017/formulas", function(e, db){
if (e) {return next(e);}
var col = db.collection("users");
col.findOne({"username": id}, function(err, user){
done(err, {"username": id});
});
});
});
When I call app.post(/login) I'm taken directly to /about and nothing is logged to the console so I'm not quite sure what's going wrong.
Advice on what to fix or how to troubleshoot is greatly appreciated.
Firstly when u serialize user object , then in deserialize also whole user object must be passed.
Consider the example below.
For routes :
router.post('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err); }
if (!user) { return res.redirect('/login'); }
req.logIn(user, function(err) {
if (err) { return next(err); }
req.session.user = req.user;
return res.redirect('/home');
});
})(req, res, next);
});
For passport.js , place the localstrategy and passport in same folder
var passport = require('passport'),
session = require('express-session');
var local = require('./localstrategy.js');
module.exports = function (app) {
app.use(session({
secret: 'Site visit',
resave: true,
saveUninitialized: true,
cookie: { secure: false }
}));
app.use(passport.initialize());
app.use(passport.session());
passport.serializeUser(function(user, done){
done(null, user);
});
passport.deserializeUser(function(user, done){
done(null, user);
});
local();
};
For local strategy :
'use strict';
var passport = require('passport'),
local = require('passport-local').Strategy;
var user;
// path where the db.js is placed
var db = require('./../db.js');
var ObjectId = db.getObjectID();
var bcrypt = require('bcrypt');
module.exports = function(){
passport.use(new local({
usernameField : 'username',
passwordField : 'password'
}, function(username, password, done){
var collection = db.getDb().collection('users');
collection.findOne({
username: username,
}, function (err, result) {
if(result == null){
cb(null, false);
}else {
bcrypt.compare(password, result.password, function (err, passRes) {
if (passRes == true) {
user = user;
done(err, user);
}else{
done(null, false, { message : 'Invalid Password'});
}
});
}
});
}));
};
After I login to my application, passport(local strategy) middleware matches the password to the one stored in database and routes me to the user page but it does not starts the session, due to which I am not able to authenticate post and get request for that user.
After playing around with code I found out that, passport.serializeUser and passport.deserializeUser are never called, I used console.log() to check the same.
I read the passport control flow from this link and found out that after password is matched and user is passed, the middleware calls req.login which further calls passport.serializeUser, I think in my case the req.login is never called because of which session is not maintained.
I have tried everything but am not able to figure out where I am going wrong.
This is my password Config :-
var LocalStrategy = require('passport-local').Strategy;
var User = require('../models/userModel');
module.exports = function(passport){
passport.serializeUser(function(user, done) {
console.log("serialize");
done(null, user._id);
});
passport.deserializeUser(function(id, done) {
console.log("deserialize");
User.getUserById(id, function(err, user) {
done(err, user);
});
});
passport.use(new LocalStrategy(function(username, password, done){
User.getUserByUsername(username, function(err, user){
if(err) throw err;
if(!user){
console.log("not user");
return done(null, false);
}
User.comparePassword(password, user.password, function(err, isMatch){
if(err) return done(err);
if(isMatch){
console.log("pass match");
return done(null, user);
} else {
console.log("invalid pass ");
return done(null, false);
}
});
});
}));
}
I always get the response "pass match" if I submit the correct user info in the login page.
This is login page where I have setup Authentication request
var LocalStrategy = require('passport-local').Strategy;
var passportAuth = require('../config/passport');
module.exports = function(app,bodyParser,passport){
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:true}));
app.post('/api/loginAuth', (req,res,next)=> {
passport.authenticate('local', function(err, user, info ) {
if (err) {
console.log("inside error");
return next(err);
}
if (!user) {
console.log("No user");
res.status(401).send("not user");
} else {
console.log("verified user");
res.json(user);
}
})(req, res, next);
});
passportAuth(passport);
}
Passport and session setup in my app.js
var session = require('express-session');
var passport = require('passport');
// Handle Sessions
app.use(session({
secret:'secret',
saveUninitialized: true,
resave: true,
}));
// Passport
app.use(passport.initialize());
app.use(passport.session());
This is my angularjs Post request for authentication
$http({
method: 'POST',
url: '/api/loginAuth',
data: $scope.userinfo,
withCredentials: true
}).success (
function(response){
var message = '<strong>'+response.name+'</strong> Successfully logged in!! ';
sharedDataService.setMessage(message);
sharedDataService.setProperty(response.name);
$state.go('todo', {username: response.username});
});
Add this code to else part of app.post
req.logIn(user, function(err) {
if (err) { return res.send(err); }
res.json(user);
});
Like this
app.post('/api/loginAuth', (req,res,next)=> {
passport.authenticate('local', function(err, user, info ) {
if (err) {
console.log("inside error");
return next(err);
}
if (!user) {
console.log("No user");
res.status(401).send("not user");
} else {
req.logIn(user, function(err) {
if (err) { return res.send(err); }
res.json(user);
});
}
})(req, res, next);
});
I have a Node.js Express App and I am trying to use MongoStore to save the sessions and Passport-local for authentication. The app is not storing sessions in db.sessions
app.js
var session = require("express-session");
var MongoStore = require("connect-mongo/es5")(session);
var passport = require('passport');
app.use(session({
secret: 'secret',
resave: false,
saveUninitialized: false,
duration: 30 * 60 * 1000,
activeDuration: 5 * 60 * 1000,
store: new MongoStore({
url: MongoDB.MONGODB_URL
})
}));
app.use(passport.initialize());
passport.serializeUser(function(user, done) {
done(null, user._id);
});
passport.deserializeUser(function(id, done) {
db.users.findById(id, function(err, user){
if(!err) done(null, user);
else done(err, null);
});
});
localstrategy is implemented as follows. MongoDB is my own module which interacts with MongoDB.
passport.use('local', new LocalStrategy({
usernameField: 'email',
passwordField: 'password'
},
function (email, password, done) {
process.nextTick(function () {
MongoDB.collection("users").findOne({
email: email
}, function (error, doc) {
if (error) {
return done(error);
}
if (doc) {
if (doc.password === PasswordManager.encryptPassword(password)) {
return done(null, doc);
} else {
return done("Invalid Password", false);
}
}
});
});
}
));
Authentication Request.
As I am trying to use MongoStore sessions, I have passed the option - {session: false} to the req.LogIn function.
router.post('/login', function (req, res, next) {
passport.authenticate('local', function (err, user) {
if (err) {
return next(err);
}
if (!user) {
return res.status(401).send({
success: false,
error: "User not found!",
data: null
});
}
req.logIn(user, {session: false}, function (err) {
if (err) {
return next(err);
}
req.session.user = user;
return res.send({
success: true,
error: null,
data: user
});
})
})(req, res, next);
});
I am using express 4 with passport js to handle authentication of users.
The front end is Angular JS.
I am basically facing two problems:
1- sign in is lengthy, it takes up to 15 seconds to sign in.
2- once logged in, if i restart the node js server and refresh the page I am back to the signin page even though a cookie is set in the browser.
This is what i have in the backend
passport.serializeUser(function (user, done) {
done(null, user._id);
});
passport.deserializeUser(function (id, done) {
User.findById(id, function (err, user) {
user.password = undefined;
done(err, user);
});
});
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: messages['116']});
}
user.comparePassword(password, function (err, isMatch) {
if (err) {
return done(err);
}
if (isMatch) {
return done(null, user);
} else {
return done(null, false, { message: messages['116']});
}
});
});
}));
app.use(favicon());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(express.static(path.join(__dirname, 'public')));
app.use(cookieParser('a very hard to guess string'));
app.use(session({
secret: 'a very hard to guess string'
}
));
app.use(passport.initialize());
app.use(passport.session());
The following is the login route:
router.post('/signin', function (req, res, next) {
var result = _.cloneDeep(SwissArmyKnife.resultObjSkel);
var username = req.body.username;
var password = req.body.password;
if (_.isEmpty(username)) {
result.error.reasons.push(SwissArmyKnife.messages['118']);
}
if (_.isEmpty(password)) {
result.error.reasons.push(SwissArmyKnife.messages['119']);
}
if (!_.isEmpty(result.error.reasons)) {
return res.json(200, result);
}
passport.authenticate('local', function (err, user, info) {
if (err) {
return next(err);
}
if (user) {
req.login(user, function (err) {
if (err) {
return next(err);
}
result.result = true;
return res.json(200, result);
})
}
if (info) {
result.error.reasons.push(info.message);
return res.json(200, result);
}
})(req, res, next);
});
when debugging the above code i notice a huge delay when the code reaches
passport.authenticate('local', function (err, user, info) {
what could be the problem???
what am i doing wrong?
Thanks in advance.
The reason you're seeing the sign-in page after restarting your server is because you are using the memory store for your sessions. As you've noticed this only has so much usefulness and you should use some persistent store instead (e.g. redis).