I'm new to node and am trying to get a simple local login up and running using passport.js. It looks to me that the strategy that I have set up is not being run when the authenticate function is called.
module.exports = function(app) {
var mongo = require('./mongoose-db.js');
var brands = require('./app/brands.js');
// brand admin page //
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
passport.use(new LocalStrategy( {//this is a strategy but why is it not being run?
usernameField: 'admin_username',
passwordField: 'admin_password'
},
function(username, password, done) {console.log('here 7');
process.nextTick(function () {
console.log('here 8');
// Find the user by username. If there is no user with the given
// username, or the password is not correct, set the user to `false` to
// indicate failure and set a flash message. Otherwise, return the
// authenticated `user`.
mongo.findAdminByUsername(username, function(err, user) { console.log('here 9');
if (err) { return done(err); }
if (!user) { return done(null, false, { message: 'Unknown Admin ' + username }); }
if (user.password != password) { return done(null, false, { message: 'Invalid password' }); }
return done(null, user);
})
});
}
));
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
findById(id, function (err, user) {
done(err, user);
});
});
app.get('/brand_admin', function(req, res){
console.log('here 1');
res.render('admin_login', { user: req.user, message: req.session.messages });
});
app.post('/brand_admin', function(req, res, next) {
console.log('USER: ');
console.log(req.user);
res.send('ok');
passport.authenticate('local', function(err, user, info) {
console.log(user);
if (err) { return next(err) }
if (!user) {console.log(req.session.messages);
req.session.messages = [info.message];
console.log('here 4');
console.log(req.session.messages);
return res.redirect('/brand_admin')
}
console.log('here 5');
req.logIn(user, function(err) {
if (err) { return next(err); console.log('here 6');}
return res.redirect('/');
});
})(req, res, next);
});
the ejs is:
<body>
<head> Admin Login </head>
<form id="brand_edit" action="/brand_admin" method="post" >
<fieldset>
Login: <input type="text" name="admin_login" > <br>
Password: <input type="password" name="admin_password" >
<input type="submit" name="action" value="Login"/>
</fieldset>
Forgotten your password?
</form>
</body>
The output i'm getting from form submission is:
Steve
agrgegerfe
{ id: 1,
username: 'Steve',
password: 'agrgegerfe',
email: 'bob#example.com' }
false
undefined
here 4
[ 'Missing credentials' ]
here 1
The strategy is not running but I can't figure out why? Can anyone help? One thing that could be affecting this is that I am using passport for Facebook login in another section of the application..
I think you are not calling passport properly. It needs to be in the route chain. Try this:
// configure passport with the correct fields
passport.use(new LocalStrategy({
usernameField: 'admin_login',
passwordField: 'admin_password'
}, function (username, password, done) {
...
});
app.post('/brand_admin', passport.authenticate('local'), function (req, res) {
// req.user is now defined
console.log(req.user);
res.send('ok');
});
Related
I have made a user register and login but I couldnt understand why req.user shows undefined.
I couldnt understand why it shows undefined.
I have middleware of :
app.use(passport.initialize());
app.use(passport.session());
And also I have middleware of body-parser
This is my register(post):
app.post('/register',[
// username must be an email
check('kullanici_adi').notEmpty(),
// email must be at least 5 chars long
check('email').isEmail(),
// email must be at least 5 chars long
check('sifre').notEmpty(),
], async (req, res) => {
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(req.body.sifre, salt);
let kullanici = new Kullanici({
kullanici_adi: req.body.kullanici_adi,
email: req.body.email,
sifre: hashedPassword,
});
const errors = validationResult(req);
if (!errors.isEmpty()) {
req.flash('danger', 'Bütün Alanların Doldurulması Zorunludur');
res.render('kayit', {
});
}
kullanici.save(function(err) {
if (err) {
console.log(err);
} else {
res.redirect('/');
}
});
});
This is my login parts:
app.get('/login', function(req, res){
res.render('login');
});
app.post('/login', (req, res, next) => {
passport.authenticate('local', {
failureRedirect: '/login',
successRedirect: '/',
failureFlash: true,
}) (req, res, next);
});
app.get('/logout', function(req, res){
req.logout();
req.flash('success', 'You are logged out');
res.redirect('/login');
});
And this is passportjs configure part:
passport.use(new LocalStrategy({
usernameField: 'kullanici_adi',
passwordField: 'sifre'
},
function(username, password, done) {
Kullanici.findOne({ kullanici_adi: username }, function (err, kullanici) {
if (err) { return done(err); }
if (!kullanici) {
return done(null, false, { message: 'Incorrect username.' });
}
bcrypt.compare(password, kullanici.sifre, function(err, isMatch){
if(err) throw err;
if(isMatch){
return done(null, kullanici);
} else {
return done(null, false, {message: 'Wrong password'});
}
});
});
}
));
passport.serializeUser(function(kullanici, done) { done(null, kullanici.id); });
passport.deserializeUser(function(id, done) { Kullanici.findById(id, function(err, kullanici) { done(err, kullanici); }); });
When I console.log(req.kullanici) in my index or post routes then it says undefined. But at the same time this undefined user can pass through ensureAuthenticated parts of my website.
Note: Some words meaning in English:
Kullanici = User,
kullanici = user,
kullanici_adi = username,
sifre = password,
email = email,
Can someone help met? Why it is being happened and how to solve this issue?
Full code:https://github.com/michelson/dante2/issues/229
I am trying to add authentication to my express app using passport, passport-local and passport-jwt. This is what I have for the login code, I have logged the output of the generated token and I try to send it back via the response object, but when I try to login using postman, the request never finished.
passport.use('login', localStrategyLogin);
passport.serializeUser(function (user, done) {
done(null, user._id)
});
app.use(passport.initialize());
app.post('/login', (req, res, next) => {
passport.authenticate('login', {session: false}, (err, user, info) => {
if (err) {
return next(err);
}
if (!user) {
return next(new Error("Could not find user"));
}
req.login(user, {session: false}, (error) => {
if (error) return next(error);
const token = jwt.sign({_id: user._id, email: user.email}, JWT_SECRET, {expiresIn: JWT_EXPIRES});
res.send({token});
});
})(req, res, next);
});
Login Strategy:
import { Strategy as LocalStrategy } from 'passport-local';
import User from "../models/User";
export const localStrategyLogin = new LocalStrategy({usernameField: 'email', passwordField: 'password'}, async function (email, password, done) {
try {
const user = await User.findByLogin({email, password});
if (user) return done(null, user);
} catch (e) {
console.log(e.message);
}
return done(null, false, {message: 'Incorrect email or password.'});
});
The problem is you are using next instead of sending a response back.
return next(err);
Next is used to pass control to the next middleware function. If not the request will be left hanging or open.
modify it to
return res.status(500).send(err);
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'});
}
});
}
});
}));
};
I'm trying to confirm users email addresses by sending an activator code to their email address. when user clicked on activator URL (GET method), server will compare activator code + username and try to handle it.
I'm using GET method like this:
router.get('/activator/:username/:activator', function(req, res, next){
passport.authenticate('activator', function(err, user, info){
if (err) {console.log('Error info: ', info);}
else if (!user) {console.log('User not found: ' , info)}
else {console.log('User activated')}
res.redirect('/');
})(req, res, next)
});
And activator.js is:
var LocalStrategy = require('passport-local').Strategy;
var User = require('../models/user');
module.exports = function(passport){
passport.use('activator', new LocalStrategy({
usernameField: 'username',
passwordField: 'activator'
},
function(username, password, done) {
User.findOne({username: username , activator: password},
function(err, user){
if (err){
return done(null, false, 'User not found.');
}
user.activate = true;
user.save(function (err) {
if (err) return handleError(err);
return done(null, user, 'Persistence Registration successful');
});
});
})
);
};
But server response is: { message: 'Missing credentials'}
It seems passport js and GET method params has some conflicts.
Am i right? what should i do for that?
Problem solved!
As I said, problem was for GET method & passport connection.
passport function only read from req.query which is only on POST method but GET method is using req.params.
So I changed my application code to :
router.get('/activator/:username/:activator', function(req, res, next){
req.query = req.params; // GET to POST simulator!
passport.authenticate('activator', function(err, user, info){
if (err) {console.log('Error info: ', info);}
else if (!user) {console.log('User not found: ' , info)}
else {console.log('User activated')}
res.redirect('/');
})(req, res, next)
});
your Strategy fields are not valid, replace it with email and password and send same parameters from client side
module.exports = function(passport) {
passport.use('activator', new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
},
function(username, password, done) {
User.findOne({
username: username,
activator: password
},
function(err, user) {
if (err) {
return done(null, false, 'User not found.');
}
user.activate = true;
user.save(function(err) {
if (err) return handleError(err);
return done(null, user, 'Persistence Registration successful');
});
});
}));
};
I am using passport-local and passport-facebook strategies for authentication in sails.js. Authentication with email is working fine. But when user authenticates using facebook, I am getting this error message [Error: Failed to serialize user into session].
Then I tested serializeUser method and it turns out user param is empty in case of facebook. While I also tried to see if verifyHandler is called or not and it is not being called.
Here is my code for the facebook authentication action:
facebook: function (req, res) {
passport.authenticate('facebook', {failureRedirect: '/login', scope: ['email']}, function (err, user) {
if ((err) || (!user)) {
req.session.flash = {
errMsg: 'Email or password mismatch.'
}
return res.redirect('/login');
}
req.logIn(user, function (err) {
if (err) {
console.log(err);
res.view('500');
return;
}
res.redirect('/');
return;
});
})(req, res);
}
And this is the code of passport.js service (api/services/passport.js)
var passport = require('passport'),
LocalStrategy = require('passport-local').Strategy,
FacebookStrategy = require('passport-facebook').Strategy,
bcrypt = require('bcrypt');
var verifyHandler = function (token, tokenSecret, profile, done) {
console.log('in verifyHandler'); // this line is not being executed.
console.log(profile);
process.nextTick(function () {
User.findOne({uid: profile.id}, function (err, user) {
if (err) {
return done(err);
}
if (user) {
return done(null, user);
} else {
var data = {
provider: profile.provider,
uid: profile.id,
name: profile.displayName
};
if (profile.emails && profile.emails[0] && profile.emails[0].value) {
data.email = profile.emails[0].value;
}
User.create(data, function (err, user) {
return done(err, user);
});
}
});
});
};
passport.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(function (id, done) {
User.findById(id, function (err, user) {
done(err, user);
});
});
passport.use(new LocalStrategy({
usernameField: 'email',
passwordField: 'password'
},
function (email, password, done) {
User.findOne({email: email}).exec(function (err, user) {
if (err) {
return done(err);
}
if (!user) {
return done(null, false, {message: 'Unknown user ' + email});
}
bcrypt.compare(password, user.password, function (err, res) {
if (!res) return done(null, false, {message: 'Invalid Password'});
return done(null, user);
});
});
}
));
passport.use(new FacebookStrategy({
clientID: sails.config.facebook.clientID,
clientSecret: sails.config.facebook.clientSecret,
callbackURL: sails.config.facebook.callbackURL
}, verifyHandler));
And finally (config/passport.js)
var passport = require('passport'),
LocalStrategy = require('passport-local').Strategy,
FacebookStrategy = require('passport-facebook').Strategy;
module.exports = {
http: {
customMiddleware: function (app) {
app.use(passport.initialize());
app.use(passport.session());
}
}
};
Any thoughts?
Check if user.id is defined and it is string but not ObjectId().
in
passport.serializeUser(function (user, done) {
done(null, user.id);
});