Node JS + Passport login - javascript

I'm trying to configure my first node js app to login using passport.
So first things first. I create a /app/config/express.js file to configure express stuff. So my app.js is simpler:
var app = require('./app/config/express')();
app.listen(3001, function(){
console.log("Servidor rodando");
});
Ok... that's cool. BUT! My express.js file is too big. Maybe you can give me some tips on how to refactor this?
I added some comments with some questions that I would love to make this code better.
var express = require('express');
var load = require('express-load');
var expressValidator = require('express-validator');
var bodyParser = require('body-parser');
var passport = require('passport');
var Strategy = require('passport-local').Strategy;
var session = require('express-session');
var flash = require("connect-flash");
module.exports = function() {
// PLEASE READ 1
//
//
// Functions to organize code better.
// PS: if this functions are outside "module.exports", then Express
// doesnt 'inject' the 'app.infra' variable ....
// Is there a workaround to move these functions outta here?
//
//
function configureAuth(){
passport.use(new Strategy({
passReqToCallback : true
},
function(req, username, password, cb) {
var connection = app.infra.connectionFactory();
var userDao = new app.infra.dao.UserDao(connection);
userDao.login(username, password, function(err, user){
if (err) {
return cb(err);
}
if (!user) {
return cb(null, false);
}
return cb(null, user);
});
connection.end();
}));
//
//
// HERE IT IS!
//
//
passport.serializeUser(function(user, cb) {
cb(null, user.id);
});
passport.deserializeUser(function(id, cb) {
cb(null, user);
});
}
function configureExpressLibs(app){
app.set('view engine', 'ejs');
app.set('views','./app/views');
app.use('/static', express.static('./app/public'));
app.use(flash());
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.use(expressValidator());
app.use(session({
secret: '086this 54is 23unkowned 67',
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
}
function configureErrors(app){
app.use(function(err, req, res, next) {
console.error(err.stack)
next(err)
});
app.use(function(req,res,next){
res.status(404).render('errors/404');
next();
});
app.use(function(error, req,res,next){
res.status(500).render('errors/500');
next();
});
}
// PLEASE READ 2
//
//
// I've moved this to 'LoginController.js' in my routes folder but
// I didnt work... So I moved it here. Is there a work around?
//
//
function configureLoginRoutes(app){
function redirectToIndexIfLoggedIn(req, res, next) {
if (req.isAuthenticated())
res.redirect('/');
return next();
}
app.get('/login', redirectToIndexIfLoggedIn, function(req, res){
res.render('login/login');
});
app.post('/login', passport.authenticate('local', {
successRedirect : '/',
failureRedirect : '/login',
failureFlash : 'Invalid username or password.'
}));
app.get('/logout', function(req, res){
req.logout();
req.session.destroy();
res.redirect('/');
});
}
var app = express();
configureExpressLibs(app);
configureAuth();
configureLoginRoutes(app);
load('routes',{cwd: 'app'})
.then('infra')
.into(app);
configureErrors(app);
return app;
}
So the problem now is, when I login (it doesnt matter if the user is correct or wrong), I get a:
Error: Failed to serialize user into session
I googled it and saw the the reason for this is because people forgot to implement "serializeUser". But I did. Please check the comment with "HERE IT IS" on the code above.
Thanks guys.
Sorry for the big code. But I'm learning and I hope to make things better with your help.
EDIT My deserialize method was wrong. I fixed it using:
passport.deserializeUser(function(id, cb) {
var connection = app.infra.connectionFactory();
var userDao = new app.infra.dao.UserDao(connection);
userDao.findById(id, function(err, user) {
done(err, user);
});
connection.end();
});
but the application still fails. Same error.
EDIT SOLUTION
Turns out my implementation was wrong. You see, mysql always returns an array. Thus I corrected my code like this:
function(req, username, password, cb) {
var connection = app.infra.connectionFactory();
var userDao = new app.infra.dao.UserDao(connection);
userDao.login(username, password, function(err, user){
if (err) {
return cb(err);
}
if (!user) {
return cb(null, false);
}
// HERE
return cb(null, user[0]);
});
connection.end();
}));
And here:
passport.deserializeUser(function(id, cb) {
var connection = app.infra.connectionFactory();
var userDao = new app.infra.dao.UserDao(connection);
userDao.findById(id, function(err, user) {
// HERE
cb(err, user[0]);
});
connection.end();
});
}

I think your this.user is not setting inside deserializeUser when you call cb(null,user) so create your own middleware after app.use(passport.session()) to put it in this.user like so:
app.use(function * setUserInContext (next) {
this.user = this.req.user
yield next
})
Cheers :)

Related

Passportjs Local authetication is not working properly

After implementing using passport-local not able to open profile page
I'm getting this below error
This page isn’t workinglocalhost redirected you too many times.
Try clearing your cookies.
ERR_TOO_MANY_REDIRECTS
passport-local-strategy.js
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const User = require('../models/user');
passport.use(new LocalStrategy({
usernameField: 'email'
},
function(email, password, done){
User.findOne({email: email}, function(err, user){
if(err){
console.log('Error in finding user --> Passport');
return done(err);
}
if(!user || user.password!=password){
console.log("Invalid username/password");
return done(null, false);
}
return done(null, user);
});
}
));
// serialize user function
passport.serializeUser(function(user, done){
done(null, user.id);
});
//deserialize the user fn
passport.deserializeUser(function(id, done){
User.findById(id, function(err, user){
if(err){
console.log("Error in finding user --> passport");
return done(err);
}
return done(null, user);
});
});
// check if user is authenticated
passport.checkAuthenticated = function(req, res, next){
if(req.isAuthenticated()){
return next();
}
// if the user is not signed in
return res.redirect('/users/sign-in');
}
passport.setAuthenticatedUser = function(req, res, next){
if(req.isAuthenticated()){
// req.user contains current signed in user data from the login page
res.locals.user = req.user;
}
next();
}
module.exports = passport;
users_controller.js
const User = require('../models/user')
module.exports.profile = function(req, res){
if(req.cookies.user_id){
User.findById(req.cookies.user_id, function(err, user){
if(user){
return res.render('profile',{
title:"Profile",
user:user
});
}
else{
return res.redirect('/users/sign-in')
}
})
}
else{
return res.redirect('/users/sign-in');
}
}
// render the sign up and in page
module.exports.signUp = function(req, res){
if(req.isAuthenticated()){
return res.redirect('/users/profile')
}
return res.render('user_sign_up', {
title: "Codeial | Sign Up"
})
}
module.exports.signIn = function(req, res){
if(req.isAuthenticated()){
return res.redirect('/users/profile')
}
return res.render('user_sign_in', {
title: "Codeial | Sign In"
})
}
// get the sign up data
module.exports.create = function(req, res){
if(req.body.password != req.body.confirm_password){
return res.redirect('back')
}
User.findOne({email:req.body.email}, function(err, user){
if(err){console.log('error in finding user in signing up'); return;}
if(!user){
User.create(req.body, function(err, user){
if(err){console.log('error in finding user in signing up'); return;}
return res.redirect('/users/sign-in')
})
}
else{
return res.redirect('back')
}
})
}
module.exports.createSession = function(req, res){
return res.redirect('/');
}
users.js
const express = require('express')
const router = express.Router();
const passport = require('passport');
const usersController = require('../controllers/users_controller');
router.get('/profile',passport.checkAuthenticated,usersController.profile)
router.get('/sign-up', usersController.signUp);
router.get('/sign-in', usersController.signIn);
// in above all codes after get('/sign-up') means when we type the keyword sign-up in the browser we need to render the folllowing page which is userController.signUp
// we are using users_controller.js file by importing
router.post('/create', usersController.create);
router.post('/create-session',passport.authenticate(
'local',
{failureRedirect: '/users/sign-in'},
),usersController.createSession);
// above line post create-session is forms action in user_sign_in.ejs file - when we submit the data of the form the post method is invoked
module.exports = router;
mongoose.js
const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost/codeial_development')
const db = mongoose.connection;
db.on('error', console.error.bind(console, "Error connecting to MongoDb"));
db.once('open', function(){
console.log('connected to the database :: MongoDB ')
})
module.exports = db;
index.js
const express = require('express');
const cookieParser = require('cookie-parser');
const app = express();
const port = 8000;
const expressLayouts = require('express-ejs-layouts');
const db = require('./config/mongoose')
const session = require('express-session');
const passport = require('passport');
const passportLocal = require('./config/passport-local-strategy')
const MongoStore = require('connect-mongodb-session')(session)
app.use(express.urlencoded());
/* is a method inbuilt in express to recognize the incoming
Request Object as strings or arrays. This method is called as a
middleware in your application using the code*/
app.use(cookieParser());
app.use(express.static('./assets'));
app.use(expressLayouts);
// extact style and scripts from subpages into the layout
app.set('layout extractStyles', true)
app.set('layout extractScripts', true)
app.set('view engine', 'ejs');
app.set('views','./views')
app.use(session({
name: 'codeial',
secret:'blahsomeone',
saveUninitialized:false,
resave:false,
cookie:{
maxAge: (1000 * 60 * 100)
},
store: new MongoStore({
// mongooseConnection:db
mongoUrl: db._connectionString,
autoRemove: 'disabled'
}, function(err){
console.log(err || 'connect-mongo setup ok')
})
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(passport.setAuthenticatedUser);
// use express router
app.use('/', require('./routes'));
app.listen(port, function(err){
if(err){console.log(`Error running the server: ${err}`)};
console.log(`Server is running on port: ${port}`);
})
I'm not able to view profile page, its redirecting or getting this error
This page isn’t workinglocalhost redirected you too many times.
Try clearing your cookies.
ERR_TOO_MANY_REDIRECTS

Restricting page access with passport.js and express middleware

I have a server set up to authenticate user login, so far I was able to successfully authenticate user and redirect them to the success page (as well as redirect them back to the login page if failed). However, I can't use my own express middleware to restrict user if they are not logged in, for some reason my req.isAuthenticate() check in the middleware is always false. I feel like my session info is not stored when logging in, but I'm not sure.
Here's my setup (note that I use express-flash-2 instead of connect-flash therefore the req.flash())
In server.js
// ...
var flash = require('express-flash-2');
var session = require('express-session');
var passport = require('passport');
// ...
server.use(session({
secret: 'keyboard cat',
resave: true,
saveUninitialized: true
}));
server.use(flash());
server.use(passport.initialize());
server.use(passport.session());
passport.use(auth_controller.authStrategy);
passport.serializeUser(auth_controller.authSerializer);
passport.deserializeUser(auth_controller.authDeserializer);
server.get('/maintenance_login', (req, res) => {
res.render('login');
});
server.post('/maintenance_login', passport.authenticate('local', {
successRedirect: '/maintenance',
failureRedirect: '/maintenance_login',
failureFlash: true
}));
// This does basically the same as above
// server.post('/maintenance_login', (req, res, next) => {
// passport.authenticate('local', function(err, user, info) {
// if (err) { return next(err); }
// if (!user) { return res.redirect('/maintenance_login'); }
//
// req.logIn(user, function(err) {
// if (err) { return next(err); }
// console.log('is authenticated?: ' + req.user); // this returns true
// return res.redirect('/maintenance');
// });
// })(req, res, next);
// });
server.get('/maintenance:query?', auth_controller.restrict, maintenance_controller.maintenance_list);
In auth_controller.js
var passport = require('passport');
var LocalStrategy = require('passport-local');
var User = require('../models/user');
exports.authStrategy = new LocalStrategy({
usernameField: 'email',
passwordField: 'password'
}, function (email, password, done) {
User.authenticate(email, password, function(err, user) {
// success message
// error message
done(err, user, err ? { message: err.message } : null);
});
});
exports.authSerializer = function(user, done) {
done(null, user.id);
};
exports.authDeserializer = function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
};
exports.restrict = function (req, res, next) {
console.log('is authenticated?: ' + req.isAuthenticated()); // This always returns false
if (req.isUnauthenticated()) {
res.flash('error', 'Access denied, please log in.');
return res.redirect('/maintenance_login');
}
return next();
}
Again, my issue is that whenever I was successfully logged in, I got kicked back to /maintenance_login and the flash showing "Access denied, please log in.". Which means that req.isUnauthenticated() in the restrict middleware returns true.
Any ideas?
Well, it turns out that missing the .Strategy is crucial. Changing var LocalStrategy = require('passport-local'); to var LocalStrategy = require('passport-local').Strategy; fixes this issue. Incase anyone else is having the same problem.

Trouble with authentication

I´m facing a confusion issue while implementing the authentication for my restful api using passport local strategy.
Note:
I got the authentication working successfully when I´m doing it all in my index.js. But I want to use in Classes for better Code separation.
I have a passport.js Module
// config/passport.js
// load all the things we need
var LocalStrategy = require('passport-local').Strategy;
// load up the user model
var mysql = require('mysql');
var dbconfig = require('./database');
var connection = mysql.createConnection(dbconfig.connection);
module.exports = function(passport) {
// passport needs ability to serialize and unserialize users out of session
passport.serializeUser(function (user, done) {
//console.log("SER");
console.log(user),
done(null, user);
});
passport.deserializeUser(function (user, done) {
console.log("XXXX");
console.log(user);
connection.query("SELECT * FROM users WHERE name = ? ",user.name, function(err, rows){
console.log("DER");
console.log(rows);
done(err, rows[0]);
});
});
// passport local strategy for local-login, local refers to this app
passport.use('local-login', new LocalStrategy(
function (username, password, done) {
console.log("hhh");
console.log(username);
connection.query("SELECT * FROM users WHERE name = ? ",username, function(err, rows){
console.log(rows);
return done(err, rows[0]);
});
})
);
// route middleware to ensure user is logged in
function isLoggedIn(req, res, next) {
if (req.isAuthenticated())
return next();
res.sendStatus(401);
}
};
This is my Controller Class:
class AuthenticateController {
constructor(router, passport) {
this.router = router;
this.registerRoutes();
this.passport = passport;
}
registerRoutes() {
this.router.post('/login/:username/:password', this.login.bind(this));
//this.router.get('/logout', this.logout.bind(this));
this.router.get('/content', this.content.bind(this));
}
login(req, res) {
this.passport.authenticate("local-login", { failureRedirect: "/login"}),
res.redirect("/content");
}
content(req, res ) {
console.log(req.user);
if (req.isAuthenticated()) {
res.send("Congratulations! you've successfully logged in.")
} else {
res.sendStatus(401);
}
}
isLoggedIn(req, res, next) {
console.log(req.user);
if (req.isAuthenticated())
return next();
res.sendStatus(401);
}
}
module.exports = AuthenticateController;
The Controller gets the router and passport fully configured as parameters from my index.js.
//index.js
var express = require('express')
, cors = require('cors')
, app = express()
, passport = require('passport')
, morgan = require('morgan');
require('./config/passport')(passport); // pass passport for configuration
var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(require('express-session')({secret: 'vidyapathaisalwaysrunning',
resave: true,
saveUninitialized: true }));
app.use(passport.initialize());
app.use(passport.session());
app.use(cors());
var apiRouter = express.Router();
app.use('/api', apiRouter);
//
var apiV1 = express.Router();
apiRouter.use('/v1', apiV1);
var authenticateApiV1 = express.Router();
apiV1.use('/auth', authenticateApiV1);
var AuthenticateController = require('./controllers/authenticate');
var ac = new AuthenticateController(authenticateApiV1, passport); //pass in our fully configured passport
//If I call this /login instead of the /auth/login/ in the Controller Class it works!
//app.post("/login",
// passport.authenticate("local-login", { failureRedirect: "/login"}),
// function (req, res) {
// res.redirect("/content");
// });
What is working and what is not working
The Authentication in general is working. In my posted index.js you see app.post("/login", .... If I call this one the authentication is successfully and if I try to reach the restricted content in /auth/content/ req.user has a value (the user object) and I can successfully call req.isAuthenticated() .
BUT, If I use the authentication from /auth/login/username/password the req.user is undefined when trying to reach the restricted Content.
I get no error and the response of /auth/login/username/password/ HTTP Code 301 - 'redirecting to /content.
I have currently no idea what I´m doing wrong here and I´m pretty new to the topic of Node/express/ passport ..
Hope someone has an Idea. If you need something else to help me, just mention it in the comments and I will do my best to provide you everything you need.
Thanks
EDIT:
I recently tried to read the req.user in the login function and even there it is undefined
login(req, res) {
this.passport.authenticate("local-login", { failureRedirect: "/login"}),
console.log(req.user) //undefined
res.redirect("/content");
}
I guess it could be some async problem and I should use some callback functions, but I don´t know how to apply this in my login()
EDIT 2:
Another Issue I´m facing is the integration of the isLoggedIn() request.
If I do this:
registerRoutes() {
this.router.get('/', this.isLoggedIn, this.getUsers.bind(this));
this.router.get('/:id', this.getSingleUser.bind(this));
}
it results in 401 - Unauthorized
A console.log(req.user); in the isLoggedIn() results in undefined.
But if I call the first route without calling isLoggedIn() and do console.log(req.user); the user object exists.
The correct use of callback with passport authentication for local strategy can be as below:
function(req, res, next){
passport.authenticate('local-login', function(err, user, info){
if(err)
return logger.log('error', err);
if(user)
req.login(user, function(err){
if(err) return next(err);
return res.json({'success': true});
});
if(!user)
return res.json({'error':true, 'message': info.message, 'type': info.type});
})(req, res, next);
}
Please note the use of req.login() to explicitly set user in session.
The only thing I'm finding strange is that your route declarations are different.
In the AuthenticateController the route is declared as:
this.router.post('/login/:username/:password', ...
While in index.js, the route is simply declared as
app.post("/login", ...
How is your client submitting the login credentials to the server? If it is by form, like the tutorial, could it be that having :username and :password declared as route params but being sent by form messes with passport?
Try registering the route exactly like index.js
this.router.post('/login', ...
EDIT:
I've found another dicrepancy. In AuthenticateController the res.redirect("/content"); is not wrapped inside a callback. So it is being executed before Authenticate finishes running.
In the index.js example, passport is being used as a route middleware:
app.post("/login",
passport.authenticate("local-login", { failureRedirect: "/login"}),
function (req, res) {
res.redirect("/content");
});
While in the passport.js it is inside the callback. Consider declaring it in the route:
registerRoutes() {
this.router.post('/login', this.passport.authenticate("local-login", { failureRedirect: "/login"}), this.login.bind(this));
(...)
}
login(req, res) {
res.redirect("/content");
}
O, better yet, why not use passport's option to declare both success and failure redirects, since that seems to be all that you are doing:
login(req, res) {
this.passport.authenticate("local-login", { successRedirect: "/content", failureRedirect: "/login" });
}
You are passing this.login.bind(this) as a middleware to this.router.post('/login/:username/:password', this.login.bind(this)); but login(req, res) only responds to the request with res.redirect("/content"); i.e. redirecting to /content
So like you said, you need to supply a callback that does something with the user that is returned from passports middleware verify callback.
app.post("/login",
passport.authenticate("local-login", { failureRedirect: "/login"}),
function (req, res) {
console.log(req.user); // log user in console
res.json({user: req.user}); // send user as json response
});
The custom callback mentioned by #divsingh is if you want to explicitly have control of setting the session, error messages and redirecting the request. Any other information can be found under http://passportjs.org/docs

"TypeError: req.flash is not a function" using passport with nodejs, username and password auth

Heres console output when running and entering an incorrect password ..
info: Listening on 127.0.0.1:3000
debug: GET /
debug: Incorrect password
/home/bob/git/authenticate-nodejs-prototype/node_modules/mongodb/lib/utils.js:98
process.nextTick(function() { throw err; });
^
TypeError: req.flash is not a function
at allFailed (/home/bob/git/authenticate-nodejs-prototype/node_modules/passport/lib/middleware/authenticate.js:118:15)
Heres the actual code. Any ideas what might be causing this? ..
var express = require('express'),
app = express(),
http = require('http').Server(app),
winston = require('winston'),
passport = require('passport'),
LocalStrategy = require('passport-local').Strategy,
ipaddress = '127.0.0.1',
port = 3000,
MongoClient = require('mongodb').MongoClient,
ObjectId = require('mongodb').ObjectID,
assert = require('assert'),
mongoUrl = 'mongodb://' + ipaddress + ':27017/authenticate-nodejs-prototype',
flash = require('connect-flash');
// during dev
winston.level = 'debug';
/*
* Database query
* Searches db for user that matches provided username
*/
var findUser = function (db, id, callback) {
var cursor = db.collection('userInfo').find({username: id.username});
var result = [];
cursor.each(function (err, doc) {
assert.equal(err, null);
if (doc !== null) {
result.push(doc);
} else {
callback(result);
}
});
};
// configure passport to use username and password authentication
passport.use(new LocalStrategy(
function(username, password, done) {
MongoClient.connect(mongoUrl, function (err, db) {
assert.equal(null, err);
findUser(db, {username:username, password:password}, function (result) {
db.close();
if (err) {
return done(err);
}else if (result === []) {
winston.debug('Incorrect username');
return done(null, false, { message: 'Incorrect username.' });
}else if (password !== result.password) {
winston.debug('Incorrect password');
return done(null, false, { message: 'Incorrect password.' }); // this is the line that causes error
}
return done(null, result);
});
});
}
));
passport.serializeUser(function(user, done) {
return done(null, user);
});
passport.deserializeUser(function(id, done) {
MongoClient.connect(mongoUrl, function (err, db) {
assert.equal(null, err);
findUser(db, id, function (result) {
db.close();
return done(null, result);
});
});
});
app.configure(function() {
app.use(express.static('public'));
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.session({ secret: 'keyboard cat' }));
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
app.use(flash());
});
/*
* setup endpoints
*/
app.get('/', function(req, res){
winston.debug('GET /');
res.sendfile('views/index.html');
});
app.get('/success', function(req, res){
winston.debug('GET /success');
res.sendfile('views/success.html');
});
app.post('/login',
passport.authenticate('local', { successRedirect: '/success',
failureRedirect: '/',
failureFlash: true })
);
// start server
http.listen(port, ipaddress, function(){
winston.info('Listening on ' + ipaddress + ':' + port);
});
You need to add flash to express, so that it can be used as middleware.
var flash = require('connect-flash');
...
app.use(flash());
Edit: the reason for this is that flash isn't actually built into Passport or Express, it's a separate package provided by connect-flash. So you need to install it with npm and then include it as shown above.

passportjs local strategy not getting called

I am using express and passport to build a rest api backend and it seems that my localStrategy is not getting called on request.
The entry point of my application looks like the following:
app.js
var fs = require('fs');
var express = require('express');
var mongoose = require('mongoose');
var passport = require('passport');
var config = require('./config/config');
var morgan = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var app = express();
app.use(morgan('dev')); // log every request to the console
app.use(cookieParser()); // read cookies (needed for auth)
app.use(bodyParser.urlencoded({extended:true}));
app.use(passport.initialize());
//connect to mongodb
mongoose.connect(config.db, options);
//load models (shorten forEach)
...
require(__dirname + '/models/' + file)(mongoose);
//load passport config
require('./config/passport')(mongoose, passport);
//load routes
require('./config/routes')(app, passport);
//start server
var server = app.listen(3000, ....
routes.js
...
app.post('/auth', function(req, res){
console.log("reached auth endpoint");
console.log(req.body);
passport.authenticate('local', { session: false}, function(err, user, info){
console.log("Test:"+user);
if(err) {
console.log("Error1");
return next(err)}
if(!user){
console.log("Error2");
return res.json(401, {error: 'Auth Error!'});
}
console.log("Error3");
var token = jwt.encode({ username: user.email }, "hanswurst");
res.json({token: token});
}),
function(req, res){
console.log("passport user", req.user);
};
});
passport.js
...
passport.use(new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
},
function(email, password, done){
console.log("TEST");
User.findOne({'email': email}, function(err, user){
if(err){
console.log("Unknown error");
return done(err);
}
if(!user){
console.log("No User found");
return done(null, false);
}
if(!user.validPassword(password)){
console.log("Password was incorrect");
return done(null, false);
}
console.log("User was found");
return done(null, user);
});
}
));
The only result i get on form request is
reached auth endpoint
{ email: 'test#mail.com', password: 'secret' }
POST /auth - - ms - -
For me the request body looks fine and it should enter my LocalStrategy. I am bit helpless as i am not getting any other console output from this point.
First off, you have some basic javascript syntax errors in routes.js. This part right here (lots of code removed for clarity) is broken:
passport.authenticate(/*...*/), function(req, res) {/*..*/};
It might have been that you just added some console.log calls in the wrong place. To clear up the confusion, passport.authenticate() does not perform the authentication right away, what it does is return a middleware for you. You would use it like this for example :
var middleware = passport.authenticate(...);
app.post('/auth', middleware);
So to fix your problem, try invoking the middleware returned by authenticate right away, like this:
app.post('/auth', function(req, res, next) {
console.log("reached auth endpoint");
console.log(req.body);
passport.authenticate('local', {
session: false
}, function(err, user, info) {
console.log("Test:" + user);
if (err) {
console.log("Error1");
return next(err);
}
if (!user) {
console.log("Error2");
return res.json(401, {
error: 'Auth Error!'
});
}
console.log("Error3");
var token = jwt.encode({
username: user.email
}, "hanswurst");
res.json({
token: token
});
})(req, res, next);
});
Also, I have to tell you that require caches modules. To make config/passport.js aware of mongoose and passport, you should not feed them as parameters like this:
require('./config/passport')(mongoose, passport);
Simply require them again inside config/passport.js like so:
// (in config/passport.js)
// Both of these vars point to the same thing you require'd in app.js
var mongoose = require('mongoose');
var passport = require('passport');
[Edit] I Found the problem. Because Express is no longer supporting subpackages like body-parser etc, you need to set those separately. All would be well had I done that in the first place, but I only activated:
app.use(bodyParser.urlencoded({extended:true}));
You also need to set
app.use(bodyParser.json());
To get it to work properly. Stupid oversight but still, got me stumped for 3 days.
I Have the same problem, but nothing seems to work for me though.
I'll drop the code from the top down in execution order
jade template
.navbar-right(ng-controller="mvNavBarLoginCtrl")
form.navbar-form
.form-group
input.form-control(placeholder='Email', ng-model='username')
.form-group
input.form-control(type='password', placeholder='password', ng-model='password')
button.btn.btn-primary(ng-click="signIn(username,password)") Sign In
Next step Login controller
angular.module('app').controller('mvNavBarLoginCtrl',function($scope, $http){
$scope.signIn = function (username, password){
console.log('un = ' + username); // Prints fine in the console
console.log('pw = ' + password); // Prints fine in the console
$http.post('/login', {username: username, password: password}).then(function(response){
if(response.data.success){
console.log('Logged in!!');
}
else{
console.log('Failed to log in!!');
}
});
}
});
Next step Route handler
app.post('/login', function(req, res, next){
console.log(req.username); // Already empty
console.log(req.password); // Already empty
console.log(req.body); // Already empty
// Because of the use of AngularJS we can not call passport directly,
// missing req and res will break the code
var auth = passport.authenticate('local', function(err, user){
console.log(user); // prints undefined
if(err){return next(err);}
if(!user){res.send({success:false});}
req.logIn(user, function(err){
if(err){return next(err);}
res.send({success: true, user: user});
});
});
// call the auth function to start authenticate
auth(req, res, next);
});
Next step passport authentication handler
var User = mongoose.model('User');
passport.use(new LocalStrategy({
username: 'username',
password: 'password'
},
function(username, password, done){
console.log("called"); // never printed
// find user based in mongoose schema see 'var User'
User.findOne({userName:username}).exec(function (err,user){
console.log(user) // never printed
if(err){return done(err);}
if(user){
return done(null, user);
}
else{
return done(null, false);
}
});
}
));
passport.serializeUser(function(user, done){
if(user) {
done(null, user._id);
}
});
passport.deserializeUser(function(id, done){
user.findOne({_id:id}).exec(function(err, user){
if(user) {
done(null, user);
}
else{
done(null, false);
}
});
});
There are no errors not in the console and not as node output. I am stumped and read about 5 or so other thread with similar issues, nothing worked.
If somebody could give me the golden tip, I would be eternally gratefull.

Categories

Resources