I'm having trouble with Passport.JS inside my Express app, more specifically the successful redirect for the registration/login. The username/password is being stored in DB without problems but the redirect in both cases is not working.
I'm using: Express, Body-Parser,, Mongoose, Passport, Passport-local and Passport-local-mongoose.
Passport Config
app.use(require("express-session")({
secret: "This is a test app",
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser);
passport.deserializeUser(User.deserializeUser);
Sign Up Route
app.post("/register", function(req, res) {
var newUser = new User({username: req.body.username});
User.register(newUser, req.body.password, function (err, user) {
if (err) {
console.log(err);
return res.render("register");
}
passport.authenticate("local"),(req, res, function(){
res.redirect("/campgrounds");
});
});
});
Login Route
app.post("/login",
passport.authenticate("local", {
successRedirect: "/campgrounds",
failureRedirect: "/login"
}));
Write this in your passport config
and try to match variables names to yours in your application
passport.use('local-signup', new LocalStrategy({
// by default, local strategy uses username and password, we will override with email
usernameField : 'usernameFORM',
passwordField : 'passwordFORM',
passReqToCallback : true // allows us to pass back the entire request to the callback
},
function(req, usernameCB, passwordCB, done) {
// asynchronous
process.nextTick(function() {
// Whether we're signing up or connecting an account, we'll need
// to know if the email address is in use.
User.findOne({'username' : usernameCB}, function(err, existingUser) {
// if there are any errors, return the error
if (err)
return done(err);
// check to see if there's already a user with that email
if (existingUser)
return done(null, false);
// If we're logged in, we're connecting a new account.
if(req.user) {
console.log(req.user);
var user = req.user;
User.username = usernameCB;
User.password = user.generateHash(passwordCB);
User.save(function(err) {
if (err)
throw err;
return done(null, user);
});
}
// We're not logged in, so we're creating a brand new user.
else {
// create the user
var User = new User();
User.username = usernameCB;
User.password = User.generateHash(passwordCB);
User.save(function(err) {
if (err)
throw err;
return done(null, user);
});
}});
});
}));
and in your routes
app.post('/signup',passport.authenticate('local-signup',{
successRedirect:'/campgrounds',
failureRedirect:'/login'
}))
Related
When im logging in the req.user is displayed as it should, but after navigating to /test , the req.user is undefined.
Why is that?
server.js
var express = require('express'); // call express
var app = express(); // define our app using express
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var session = require('express-session');
var router = express.Router();
var Account = require('src/app/models/Users.js');
var Core = require('/src/app/gamemodels/core');
// Init passport authentication
var passport = require('passport');
var Strategy = require('passport-local').Strategy;
require('/src/config/passport')(passport);
var cookieParser = require('cookie-parser')
// required for passport session
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
mongoose.connect('DB');
app.use(cookieParser()) // required before session.
app.use(session({ secret: 'xxxx' }));
app.use(passport.initialize());
app.use(passport.session());
var port = process.env.PORT || 3000; // set our port
// test route to make sure everything is working (accessed at GET http://localhost:8080/api)
router.get('/', function(req, res) {
res.json({ text: 'hooray! welcome to our api!' });
});
router.get('/test', function(req,res) {
console.log(req);
console.log(req.user);
res.json(req.user);
});
router.post('/signup', passport.authenticate('local-signup', {
successRedirect : '/profile', // redirect to the secure profile section
failureRedirect : '/signup', // redirect back to the signup page if there is an error
}));
router.post('/login', passport.authenticate('local-login'), function(req, res) {
console.log("executed login!");
console.log(req.user);
req.session.user = req.user;
});
});
*/
// more routes for our API will happen here
// REGISTER OUR ROUTES -------------------------------
// all of our routes will be prefixed with /api
app.use('/api', router);
// START THE SERVER
// =============================================================================
app.listen(port);
console.log('Magic happens on port ' + port);
passport js:
// config/passport.js
// load all the things we need
var LocalStrategy = require('passport-local').Strategy;
// load up the user model
var Account = require('src/app/models/Users.js');
// expose this function to our app using module.exports
module.exports = function(passport) {
passport.serializeUser(function(user, done) {
done(null, user);
});
// used to deserialize the user
passport.deserializeUser(function(id, done) {
Account.findById(id, function(err, user) {
done(err, user);
});
});
passport.use('local-login', new LocalStrategy({
// by default, local strategy uses username and password, we will override with email
usernameField : 'username',
passwordField : 'password',
passReqToCallback : true // allows us to pass back the entire request to the callback
},
function(req, username, password, done) { // callback with email and password from our form
console.log("doing local login");
// find a user whose email is the same as the forms email
// we are checking to see if the user trying to login already exists
Account.findOne({ 'username' : username }, function(err, user) {
var thisuser = user;
console.log("query account is done");
// if there are any errors, return the error before anything else
if (err) {
console.log("error occured");
return done(err);
}
console.log("if user exist check");
// if no user is found, return the message
if (!user)
return done(null, false,'No user found.'); // req.flash is the way to set flashdata using connect-flash
console.log("checking password");
// if the user is found but the password is wrong
if (!user.validPassword(password)) {
console.log("password is not valid");
return done(null, false, 'Oops! Wrong password.'); // create the loginMessage and save it to session as flashdata
}
console.log("all good! logging in!");
req.login(thisuser, function(error) {
if (error) return next(error);
console.log("Request Login supossedly successful.");
});
// all is well, return successful user
return done(null, thisuser);
});
}));
passport.use('local-signup', new LocalStrategy({
// by default, local strategy uses username and password, we will override with email
usernameField : 'email',
passwordField : 'password',
passReqToCallback : true // allows us to pass back the entire request to the callback
},
function(req, username, password, done) {
process.nextTick(function() {
console.log("doing local signup");
// find a user whose email is the same as the forms email
// we are checking to see if the user trying to login already exists
Account.findOne({ 'username' : username }, function(err, user) {
// if there are any errors, return the error
if (err)
return done(err);
// check to see if theres already a user with that email
if (user) {
return done(null, false, 'That username is already taken.');
} else {
var newUser = new Account();
// set the user's local credentials
newUser.username = username;
newUser.password = newUser.encryptPassword(password);
// save the user
newUser.save(function(err) {
if (err)
throw err;
return done(null, newUser);
});
}
});
});
}));
};
EDIT1:
changed passport.js serialize function and deserialize function to the following:
passport.serializeUser(function(user, done) {
done(null, user.username);
});
// used to deserialize the user
passport.deserializeUser(function(username, done) {
Account.findOne({'username': username}, function(err, user) {
done(err, user);
});
});
still did not make any difference. Undefined still occur.
EDIT2:
value of user in serializing:
{ _id: 5909a6c0c5a41d13340ecf94,
password: '$2a$10$tuca/t4HJex8Ucx878ReOesICV6oJoS3AgYc.LxQqCwKSV8I3PenC',
username: 'admin',
__v: 0,
inFamily: false,
bank: 500,
cash: 2500,
xp: 0,
rank: 1,
bullets: 0,
location: 1,
permission: 0,
health: 100 }
edit3:
changed the login func to:
router.post('/login', passport.authenticate('local-login'), function(req, res) {
console.log("executed login!");
console.log(req.user);
req.session.user = req.user;
req.logIn(req.user, function (err) {
if (err) {
return next(err);
}
});
});
server log response:
doing local login
query account is done
if user exist check
checking password
all good! logging in!
serializing!
Request Login supossedly successful.
serializing!
executed login!
{ _id: 5909a6c0c5a41d13340ecf94,
password: '$2a$10$tuca/t4HJex8Ucx878ReOesICV6oJoS3AgYc.LxQqCwKSV8I3PenC',
username: 'admin',
__v: 0,
inFamily: false,
bank: 500,
cash: 2500,
xp: 0,
rank: 1,
bullets: 0,
location: 1,
permission: 0,
health: 100 }
serializing!
still no sign to unserialize log.
The reason is that you are missing on the deserialization part.
/**
* Each subsequent request will contain a unique
* cookie that identifies the session. In order to support login sessions,
* Passport will serialize and deserialize user instances to and from the session.
*/
passport.serializeUser(function (user, done) {
done(null, user.username);
});
passport.deserializeUser(function (username, done) {
/**
* Necessary to populate the express request object with
* the 'user' key
* Requires(*):
* - session support with express
* - call to logIn from passport.auth)enticate if using authenticate
* callback.
*/
// TODO: Verify if username exists
done(null, username);
});
So after the user is authenticated or when req.isAuthenticated() is true, the deserialization middleware function will be invoked and will update the request object with username or req.user in your case.
Reference:
passport js sessions
Since you are using a custom callback to handle success or failures, it becomes the application's responsibility to establish a session by calling req.logIn. So after the user is authenticated, add
req.logIn(user, function (err) {
if (err) { return next(err); }
return { // Do a redirect perhaps? }
});
Refer to section Custom Callbacks in the reference link, I gave you.
When defining methods and middleware on the passport object, order matters. Your code is pretty entangled. A little decoupling will go a long way here.
Move all of the strategy logic out of server.js and your passport.js. Put it in its own set of files. Also, you don't need to include the base Strategy in the server file.
Define an express router in a separate file and mount the routes in your server.js
passport.initialize() and passport.session() middlewares need to attach to your express app instance before you define serialize and deserialize.
No need to set req.session.user, which defeats the purpose of storing just the user id in the session. On each request to express, once you deserialize the user by reading the id in req.session.passport.user, you're loading the entire user account document into req.user and you can access all user data directly from req.user.
If you're using a pre-packaged passport Strategy constructor which calls done(), you don't need to call req.login anywhere.
server.js
//express, body parser, express session, etc
const app = express();
const passport = require('passport');
const user = require('./passport-serialize');
const routes = require('./routes');
//lots of middleware
//session middleware
app.use(passport.initialize());
app.use(passport.session());
passport.serializeUser(user.serialize);
passport.deserializeUser(user.deserialize);
app.use('/api', routes);
//actual server, more stuff
passport-serialize.js
//include Account model
const user = {
serialize: (user, done) => {
done(null, user.username)
},
deserialize: (username, done) => {
Account.findOne({'username': username}, function(err, user) {
done(err, user);
}
}
module.exports = user;
routes.js
const express = require('express');
const router = new express.Router();
const passport = require('./strategies');
//many routes
router.post('/login', passport.authenticate('local-login'), function(req, res) {
console.log("executed login!");
console.log(req.user);
});
router.get('/test', function(req, res) {
console.log(req.user);
res.json(req.user);
});
module.exports = router;
strategies.js
const passport = require('passport');
const LocalStrategy = require('whatever the package is');
//Account model
passport.use('local-login', new LocalStrategy({
// by default, local strategy uses username and password, we will override with email
usernameField : 'username',
passwordField : 'password',
passReqToCallback : true // allows us to pass back the entire request to the callback
}, function(req, username, password, done) { // callback with email and password from our form
console.log("doing local login");
// find a user whose email is the same as the forms email
// we are checking to see if the user trying to login already exists
Account.findOne({ 'username' : username }, function(err, user) {
var thisuser = user;
console.log("query account is done");
// if there are any errors, return the error before anything else
if (err) {
console.log("error occured");
return done(err);
}
console.log("if user exist check");
// if no user is found, return the message
if (!user)
return done(null, false,'No user found.');
// req.flash is the way to set flashdata using connect-flash
console.log("checking password");
// if the user is found but the password is wrong
} else if (!user.validPassword(password)) {
console.log("password is not valid");
return done(null, false, 'Oops! Wrong password.');
// create the loginMessage and save it to session as flashdata
}
console.log("all good! logging in!");
// all is well, return successful user
return done(null, thisuser);
});
}));
module.exports = passport;
I'm new to NodeJS and I try to build a login/registration system. Registration works fine but I'm currently unable to login.
I find a example app using passport and nodejs, so based on this example I build the registration form and the login form.
http://blog.robertonodi.me/node-authentication-series-email-and-password/
When I try to login I get an 'Unknown authentication strategy "local" error'. Can anybody explain what I'm doing wrong?
My code
(edit: added some changes from answers/comments and filenames)
Express config (config/express.config.js)
app.use(session({
store: new MongoStore({
url: 'mongodb://' + config.url + ':' + config.port + '/' + config.name
}),
secret: 'secretkey',
key: 'skey.sid',
resave: false,
saveUninitialized: false,
cookie : {
maxAge: 604800000 //7 days in miliseconds
}
}));
app.use(passport.initialize());
app.use(passport.session());
require(path.join(__dirname, 'auth.config'))(passport); //Load passport config
app.use(function(req, res, next) {
req.resources = req.resources || {};
// res.locals.app = config.app;
res.locals.currentUser = req.user;
res.locals._t = function (value) { return value; };
res.locals._s = function (obj) { return JSON.stringify(obj); };
next();
})
Passport config (config/auth.config.js)
var path = require('path');
var passport=require('passport');
var User = require(path.join(__dirname, '..', 'models', 'user.model'));
module.exports = function(passport) {
passport.serializeUser(function(user, done){
done(null, false);
});
passport.deserializeUser(function(id, done){
console.log("deserializeUser called", id);
User.findById(id, function (err, user) {
done(err, user);
});
});
//load strategy files
require(path.join(__dirname, 'strategies', 'local-strategy'));
//TODO: Facebook
//TODO: Twitter
//TODO: Google
}
Local strategy (/config/strategies/local-strategy.js)
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var mongoose = require('mongoose');
var User = mongoose.model('User');
module.exports = function () {
console.log("LocalStrategy called");
passport.use(new LocalStrategy({
usernameField : 'username',
passwordField : 'password'
},
function(username, password, done) {
User.authenticate(username, password, function(err, user) {
if (err) {
return done(err);
}
if(!user) {
return done(null, false, {message: 'Invalid username or password'});
}
return done(null, user);
})
}))
}
Auth Controller (login only) (/controllers/auth.controller.js)
module.exports.loginUser = function(req,res, next) {
console.log("Auth.config", path.join(__dirname, 'strategies', 'local-strategy'))
passport.authenticate('local', function (err, user, info) {
if (err || !user) {
console.log("Error", info);
return res.status(400).send(info);
}
req.logIn(user, function(err) {
if (err) {
return next(err);
// return res.status(404).send("Username or password incorrect");
}
})
res.status(200).json(user);
})(req, res, next);
}
You forgot to import passport config file in your app.js.
import passport config after initializing passport.
app.use(passport.initialize());
app.use(passport.session());
// Add the line below, which you're missing:
require('./path/to/passport/config/file')(passport);
i have done like this and it worked
$npm install passport-local
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy; /* this should be after passport*/
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);
});
}
));
this fix the error. need to use 'local' when you create a new LocalStrategy
passport.use('local', new LocalStrategy({
usernameField:'useName',
passwordField: 'password',
passReqToCallback: true
I'm getting an error in Node.js when I try to login or signup.
I'm using connect-mongodb-session, but when I setup an store, it happen.
serializing user:
{ _id: 57cf316758531915c8a93dd7,
email: 'a',
password: '$2a$10$1.qkrnLWLiG6zFXHTII1pOsHs0sWdFrmfgaGO.6ZY4q/TwZ7E0RTG',
username: 'a',
followers: [],
following: [],
likes: [],
orders: [],
__v: 0 }
POST /login 302 793.072 ms - 46
_http_outgoing.js:344
throw new Error('Can\'t set headers after they are sent.');
^
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:344:11)
at ServerResponse.header (C:\Users\Fabian Gutierrez\Documents\GitHub\maravillarte\node_modules\express\lib\response.js:718:10)
at ServerResponse.send (C:\Users\Fabian Gutierrez\Documents\GitHub\maravillarte\node_modules\express\lib\response.js:163:12)
at done (C:\Users\Fabian Gutierrez\Documents\GitHub\maravillarte\node_modules\express\lib\response.js:957:10)
at Immediate._onImmediate (C:\Users\Fabian Gutierrez\Documents\GitHub\maravillarte\node_modules\express-handlebars\lib\utils.js:26:13)
at processImmediate [as _immediateCallback] (timers.js:383:17)
Error: Can't set headers after they are sent.
I tried a lot of thing, but I don't understand what happens
this is my code, app.s:
var passport = require('passport');
var expressSession = require('express-session');
var MongoDBStore = require('connect-mongodb-session')(expressSession);//session for stores sessions
//MONTAR EL STORE DE SESSIONS
var mystore = new MongoDBStore(dbConfig.store,function(error) {
if (error){
console.log(error)
}
});
app.use(expressSession({
cookie:{ maxAge: 1000 * 60 * 60 * 24 * 7 },
httpOnly: true,
store: mystore,
secret: 'mifuckingkey',
resave: true,
saveUninitialized: false,
unset: 'destroy'
}));
app.use(passport.initialize());
app.use(passport.session());
// Using the flash middleware provided by connect-flash to store messages in session
// and displaying in templates
var flash = require('connect-flash');
app.use(flash());
// Inicializar Passport
var initPassport = require('./lib/passport/init');
initPassport(passport);
var routes = require('./routes/index')(passport);
app.use('/', routes);
init.js
var login = require('./login');
var signup = require('./signup');
var User = require('../../models/user');
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: ');console.log(user);
done(null, user._id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
console.log('deserializing user:',user);
done(err, user);
});
});
console.log("passport iniciado")
// Setting up Passport Strategies for Login and SignUp/Registration
login(passport);
signup(passport);
}
signup.js
var LocalStrategy = require('passport-local').Strategy;
var User = require('../models/user');
var bCrypt = require('bcrypt-nodejs');
module.exports = function(passport){
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, req.flash('message', 'User Not found.'));
}
// User exists but wrong password, log the error
if (!isValidPassword(user, password)){
console.log('Invalid Password');
return done(null, false, req.flash('message', 'Invalid Password')); // 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);
}
);
})
);
var isValidPassword = function(user, password){
return bCrypt.compareSync(password, user.password);
}
}
signup.js
var LocalStrategy = require('passport-local').Strategy;
var User = require('../../models/user');
var bCrypt = require('bcrypt-nodejs');
module.exports = function(passport){
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, req.flash('message', 'User Not found.'));
}
// User exists but wrong password, log the error
if (!isValidPassword(user, password)){
console.log('Invalid Password');
return done(null, false, req.flash('message', 'Invalid Password')); // 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);
}
);
})
);
var isValidPassword = function(user, password){
return bCrypt.compareSync(password, user.password);
}
}
and part of router
router.get('/', function(req, res, next) {
res.render('home', { title: 'Maravillarte',user:req.user});
});
router.get('/vender', function(req, res, next) {
res.render('register', { title: 'Express',layout:'register' });
});
/*///////////////////////////////////////
INICIO DE SESSION
///////////////////////////////////////*/
router.post('/login', passport.authenticate('login', {
successRedirect: '/',
failureRedirect: '/',
failureFlash: true,
}));
router.get('/login', function(req, res, next) {
res.render('pages/login', { title: 'Maravillarte',user:req.user});
});
/*///////////////////////////////////////
REGISTRARSE
///////////////////////////////////////*/
router.post('/signup', passport.authenticate('signup', {
successRedirect: '/',
failureRedirect: '/',
failureFlash: true
}));
in your init.js,
// Setting up Passport Strategies for Login and SignUp/Registration
login(passport);
signup(passport);
Both routes res.render send the response back to the client asynchronously. So, when second route tries to send the response with res.render response of the first route already been sent. That's why it throws error like can't set header after they are sent.
follow the given link below for the example.
First of all, I'm very new to Passport.js so maybe this ends up being a very naïve question. I have this as a strategy for the signup:
// Configuring Passport
var passport = require('passport');
var expressSession = require('express-session');
var LocalStrategy = require('passport-local').Strategy;
var FacebookStrategy = require('passport-facebook');
app.use(expressSession({secret: 'mySecretKey'}));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
//[...]
passport.use('signup', new LocalStrategy({
name : 'name',
password : 'password',
email : 'email',
passReqToCallback : true
},
function(req, username, password, done) {
findOrCreateUser = function(){
// find a user in Mongo with provided username
User.findOne({'name':username},function(err, user) {
// In case of any error return
if (err){
console.log('Error in SignUp: '+err);
return done(err);
}
// already exists
if (user) {
console.log('User already exists');
return done(null, false,
req.flash('message','User Already Exists'));
} else {
// if there is no user with that email
// create the user
var newUser = new User();
// set the user's local credentials
newUser.name = name;
newUser.password = createHash(password);
newUser.email = req.param('email');
/*newUser.firstName = req.param('firstName');
newUser.lastName = req.param('lastName');*/
// save the user
newUser.save(function(err) {
if (err){
console.log('Error in Saving user: '+err);
throw err;
}
console.log('User Registration succesful');
return done(null, newUser);
});
}
});
};
// Delay the execution of findOrCreateUser and execute
// the method in the next tick of the event loop
process.nextTick(findOrCreateUser);
})
);
And this is how I deal with a POST on /register:
/* Handle Registration POST */
app.post('/register', passport.authenticate('signup', {
successRedirect: '/',
failureRedirect: '/failure_registration',
failureFlash : true
}));
This always brings me to the failureRedirect link, instead of the success. The input data is correct, and I'm always using a different user and mail to register. I'm sorry if this is a stupid question, but I don't really understand why it never goes to the successRedirect.
Thanks.
EDIT: added the suggestion and corrections by #robertklep, still not working. I'd like to point out that no error is triggered, nor any log printed.
EDIT2: Serialization/deserialization functions:
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function (err, user) {
done(err, user);
});
});
I had this same problem, failureRedirect was always being executed
First to diagnose, I used the custom callback method
http://passportjs.org/docs/authenticate
app.post('/sign_in', function(req, res, next) {
console.log(req.url);
passport.authenticate('local-login', function(err, user, info) {
console.log("authenticate");
console.log(err);
console.log(user);
console.log(info);
})(req, res, next);
});
Then I could see what the hidden error was
authenticate
null
false
{ message: 'Missing credentials' }
Which then became easy for me to diagnoise, I was sending JSON in the request rather than FORM fields
Fixed by changing
app.use(bodyParser.urlencoded({ extended: true }));
To
app.use(bodyParser.json());
I know this is almost 4 years old, but in case someone runs into the same issue, I used the diagnose from djeeg
app.post('/sign_in', function(req, res, next) {
console.log(req.url);
passport.authenticate('local-login', function(err, user, info) {
console.log("authenticate");
console.log(err);
console.log(user);
console.log(info);
})(req, res, next);
});
and I got:
null
false
'missing credentials'
THE SOLUTION: It turns out I had not used the "name" in my HTML form which meant data wasn't read and that's where the error came from
<input name="email" type="email">
That fixed it for me
A couple of points:
the function function(req, name, password, email, done) is wrong. the verify function signature is function(req, username, password, verified) when the passReqToCallback flag is on.
you're not providing serialization/deserialization functions. This is probably not biting you at the moment but could later on.
passport.serializeUser(function(user, done){
done(null, user.id);
});
what I also find interesting is that you use the authenticate function to actually create a user. I'd probably create the user and then call passport.login to make them authenticated.
Just my 2 pence :-)
do you use http or https ? I had the same situation. I fixed it like this
app.use(expressSession({....
cookie: {
httpOnly: true,
secure: false // for http and true for https
}
}));
In my situation passport can't receive cookies.
Try checking method of your form, it must be method = post, in case i mistakenly wrote it as GET method, and took me 3 days to find this, because there was no error
Im using NodeJS, ExpressJS, Mongoose, passportJS & connect-ensure-login. Authenticating users works perfectly.
....
var passport = require('passport')
, LocalStrategy = require('passport-local').Strategy
, ensureLoggedIn = require('connect-ensure-login').ensureLoggedIn;
var app = express();
...
app.use(passport.initialize());
app.use(passport.session());
...
passport.use(new LocalStrategy({usernameField: 'email', passwordField: 'password'},
function(email, password, done) {
User.findOne({ 'email': email, 'password': password },
{'_id': 1, 'email':1}, function(err, user) {
if (err) { return done(err); }
if (!user) {
return done(null, false, { message: 'Incorrect username.' });
}
return done(null, user);
});
}));
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(user, done) {
done(null, user);
});
app.post('/login', passport.authenticate('local',
{ successReturnToOrRedirect: '/home', failureRedirect: '/login' }));
app.get('/logout', function(req, res){
req.logout();
res.redirect('/');
});
Now, I want to add restrictions to some routes to be accessible only by admin. How can I do that? e.g. /admin/*
var schema = new mongoose.Schema({
name: String,
email: String,
password: String,
isAdmin: { type: Boolean, default: false }
});
mongoose.model('User', schema);
Any hint? Thanks
You could attach a custom middleware to the /admin/* route that would check for admin status before passing the request on the any of the more specific /admin/ routes:
var ensureLoggedIn = require('connect-ensure-login').ensureLoggedIn;
...
var requiresAdmin = function() {
return [
ensureLoggedIn('/login'),
function(req, res, next) {
if (req.user && req.user.isAdmin === true)
next();
else
res.send(401, 'Unauthorized');
}
]
};
app.all('/admin/*', requiresAdmin());
app.get('/admin/', ...);
//Add following function to your app.js above **app.use(app.router)** call;
//This function will be called every time when the server receive request.
app.use(function (req, res, next) {
if (req.isAuthenticated || req.isAuthenticated())
{
var currentUrl = req.originalUrl || req.url;
//Check wheather req.user has access to the above URL
//If req.user don't have access then redirect the user
// to home page or login page
res.redirect('HOME PAGE URL');
}
next();
});
I have not tried it but i think it will work.