How do i test postman when i have passport authentication - node.js

Im trying to test using postman but i have a passport authentication which is blocking me from testing as it will redirect me to the login screen it is not authenticated.
How i can get a token or authenticate myself in postman to be able to test
I have tried to use /auth/local in postman but it just returns that i cant get the route
Passport.js
var LocalStrategy = require('passport-local').Strategy;
var { User } = require('../model/user.js');
var bcrypt = require('bcrypt');
module.exports = function (passport) {
passport.use(new LocalStrategy(function (username, password, done) {
let query = { username: username };
User.findOne(query, function (err, user) {
if (err) throw err;
if (!user) {
return done(null, false,{ message: 'No user found' });
}
bcrypt.compare(password, user.password, function (err, isMatch) {
if (err) throw err;
if (isMatch) {
return done(null, user);
} else {
return done(null, false,{ message: 'Wrong password' });
}
});
});
}));
passport.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(function (id, done) {
User.findById(id, function (err, user) {
done(err, user);
});
});
}
Route.js
router.get('/register', function (req, res) {
res.sendFile(__dirname + "/views/register.html");
});
router.post('/register', async (req, res) => {
var data = req.body;
var salt = await bcrypt.genSalt(10)
var hashedpw = await bcrypt.hash(data.password, salt)
const newUser = await User.create({
name: data.name,
email: data.email,
username: data.username,
password: hashedpw,
});
newUser.save();
req.flash('success', 'You are now registered and can log in');
res.redirect('/');
});
router.get('/login', function (req, res) {
res.locals.success = req.flash('success');
res.locals.error = req.flash('message');
res.render(__dirname + "/views/login.ejs");
});
router.post('/login', async (req, res, next) => {
passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/login',
failureFlash: true
})(req, res, next);
});
router.get('/logout', async (req, res) => {
req.logout(function (err) {
if (err) { return next(err); }
req.flash('success', 'You are logged out');
res.redirect("/")
});
});
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next();
} else {
res.redirect('/login');
}
}

Following this guide:
https://mevelix.com/articles/postman-auth-for-laravel,4
you have to create the Command:
php artisan make:command DevPostman
then in the newly created class, copy the content it is showed in the link,
inside the class namespace App\Console\Commands\DevPostmanCommand
Then you can execute the command:
php artisan dev:postman web
in this way you are creating a simulated session.
This is my ouput, for example:
you paste this output directly in PostMan, inside the Tab Pre-Request Scripts:
In this way you are allowed to avoid the login inside Postman, because you are simulating a session.
See the first link to have the complete code of the DevPostmanCommand class.

Related

Passport req.logIn never call serializeUser

I am trying to signUp and login with passport for my project but i am new in passport and i have some isuues, i have a sequelize database that have (name,password,email), when i post /users it it never go to serializeUser and it load forever.
here is my post request for signUp:
router.post('/', async function(req, res, next) {
console.log(req.body, 'create new user');
const user = await User.create(
{ Name: req.body.Name, Password: req.body.Password, Email: req.body.Email }
);
const userss = await User.findOne({ where: { Email: req.body.Email } });
console.log(user, userss);
console.log('1');
try {
console.log('inserting');
await user.save(function(err) {
console.log(user.dataValues.id);
req.logIn(user.dataValues.id, function(err) { // here is the problem!
console.log('logIn');
console.log('inserted');
return res.redirect('/');
});
console.log('inserted?');
});
} catch (err) {
console.log(err);
return res.render('users/new', { user, error: req.flash('error') });
}
});
and here is my passport:
passport.serializeUser(function(user, done) {
console.log(user);
console.log('serialized1');
done(null, user);
console.log('serialized2');
return;
});
passport.deserializeUser(async function(id, done) {
console.log('here0');
const user = await User.findByPk(id);
console.log('here2');
done(null, user);
console.log('here4');
});
and here is the login rout:
router.post('/',
passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/sessions',
failureFlash: true
}),
function(req, res, next) {
console.log('new user connected');
socketio.io.sockets.emit('msg', `New user connected: ${req.user}`);
}
);
It appears that you have both two routes pointing to the same path.
I would recommend updating the login routes path.
router.post('/login',
passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/sessions',
failureFlash: true
}),
The issue described in the title also happens with Passport v0.6.0 due to this issue in the library. So req.login() silently does nothing, serializeUser() never gets called, and moving back to Passport v0.5.3 solves the issue.

After Login req.user is Undefined(Passportjs + Nodejs)

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

Passport ReferenceError: err is not defined

I want to do a login Form and I did nearly everything fixed but if I registered successfully and I want to log in, it throws either if the password is correct or incorrect:
UnhandledPromiseRejectionWarning: ReferenceError: err is not defined
So i looked up and the errormessage is this: bcrypt.compare(password, user.password, (err, isMatch => {
If the username is wrong or doesnt exist it just redirect me with an error message, like I programmed it.
Full controller/passport.js file
module.exports = function (passport) {
passport.use(
new LocalStrategy({ usernameField: 'username' }, (username, password, done) => {
// Matching
User.findOne({ username: username })
.then(user => {
if (!user) {
return done(null, false)
}
bcrypt.compare(password, user.password, (err, isMatch => {
if (err) throw err;
if (isMatch) {
return done(null, user);
} else {
return done(null, flase, { message: 'Passwort nicht korrekt' })
}
}))
})
})
)
passport.serializeUser( function (user, done) {
done(null, user.id);
});
passport.deserializeUser( function (id, done) {
User.findById(id,function (err, user) {
done(err, user);
});
});
}
I include this module into my routes.js
// Login
router.get('/', forwardAuthenticated, (req, res) => {
res.render('login/index');
})
router.post('/', (req, res, next) => {
passport.authenticate('local', {
successRedirect: '../admin',
failureRedirect: '/login'
})(req, res, next)
})
app.js
require('./controller/passport')(passport);
app.use(passport.initialize());
app.use(passport.session());
I tried to remove the err but then false wouldnt be defined, I looked up the passport docu but I havnt found anything, any ideas?
I use express, passport, passport-local, mongoose

How to redirect based on user role with PassportJS?

I need to redirect 3 types of users (based on a single user model schema). How can I do this within my router.post() call in the users route? I understand that passport.authenticate takes in certain parameters but I am wondering if there is any way around it to have multiple redirects based on the user type (role in the schema)? Many thanks!
here is how I am doing it for one type of users:
//////this is my passport.js file//////
const LocalStrategy = require('passport-local').Strategy;
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
// Load User model
const User = require('../models/User');
module.exports = function(passport) {
passport.use(
new LocalStrategy({ usernameField: 'email' }, (email, password, done) => {
// Match user
User.findOne({
email: email
}).then(user => {
if (!user) {
return done(null, false, { message: 'That email is not registered' });
}
// Match password
bcrypt.compare(password, user.password, (err, isMatch) => {
if (err) throw err;
if (isMatch) {
return done(null, user);
} else {
return done(null, false, { message: 'Password incorrect' });
}
});
});
})
);
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
};
/////////auth.js file/////////
module.exports = {
ensureAuthenticated: function(req, res, next) {
if (req.isAuthenticated()) {
return next();
}
req.flash('error_msg', 'Please log in to view that resource');
res.redirect('/users/login');
},
forwardAuthenticated: function(req, res, next) {
if (!req.isAuthenticated()) {
return next();
}
}
};
//////users.js route bellow/////////
const express = require('express');
const router = express.Router();
const bcrypt = require('bcryptjs');
const passport = require('passport');
// Load User model
const User = require('../models/User');
const { forwardAuthenticated } = require('../config/auth');
const mongoose = require('mongoose');
// Login Page
router.get('/login', forwardAuthenticated, (req, res) => res.render('login'));
// Register Page
router.get('/register', forwardAuthenticated, (req, res) => res.render('register'));
// Register
router.post('/register', (req, res) => {
const { role, name, email, password, password2 } = req.body;
let errors = [];
if (!role || !name || !email || !password || !password2) {
errors.push({ msg: 'Please enter all fields' });
}
if (password != password2) {
errors.push({ msg: 'Passwords do not match' });
}
if (password.length < 6) {
errors.push({ msg: 'Password must be at least 6 characters' });
}
if (errors.length > 0) {
res.render('register', {
errors,
role,
name,
email,
password,
password2
});
} else {
User.findOne({ email: email }).then(user => {
if (user) {
errors.push({ msg: 'Email already exists' });
res.render('register', {
errors,
role: role,
name,
email,
password,
password2
});
} else {
const newUser = new User({
role,
name,
email,
password
});
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(newUser.password, salt, (err, hash) => {
if (err) throw err;
newUser.password = hash;
newUser
.save()
.then(user => {
req.flash(
'success_msg',
'You are now registered and can log in'
);
res.redirect('/users/login');
})
.catch(err => console.log(err));
});
});
}
});
}
});
// Login
router.post('/login', (req, res, next) => {
passport.authenticate('local', {
successRedirect: '/aboutus',
failureRedirect: '/users/login',
failureFlash: true
})(req, res, next);
});
// Logout
router.get('/logout', (req, res) => {
req.logout();
req.flash('success_msg', 'You are logged out');
res.redirect('/users/login');
});
module.exports = router;
I am pretty sure that on post you can do something like this :
app.post('/login', (req, res) => {
if (req.body.role === 'normalUser') {
res.redirect('/normalUserPage')
} else if (req.body.role === 'administrator') {
res.redirect('/administratorPage');
} else if (req.body.role === 'receptionist') {
res.redirect('/receptionistPage');
}
});
I am pretty sure that this should do, make sure that these conditions come after trying to
sign in with the email and password provided.
What you pretty much have to do is set a condition for the three users, and based on the user type you can redirect them to their specific page.
another solution is to log in with the provided information and display the same page. However, based on the users' role, you can specify the content they are viewing.
example :
if the user type is admin, expose a div that allows them to view all the data with the ability to edit or delete.
if the user is normal, expose a div that allows them to view only the content specified for them. For instance only the names without any other information.
if the user is a receptionist expose a div that allows them to view all the content but without the ability to edit any information.
I really hope this helps you. let me know if this does help you.
If it does not help you I can try to figure out another solution.
This is an old thread, but for those that stumble across it...I had the same issue and this is how I addressed it:
In users.js route, include
router.get('/redirectLogin', (req, res) => {
if(req.user.role === role){ //replace role with whatever you're checking
res.render('dashboardOne.ejs')
} else {
res.render('dashboardTwo.ejs')
}
})
Then in the login POST method, change successRedirect to:
// Login
router.post('/login', (req, res, next) => {
passport.authenticate('local', {
successRedirect: '/users/redirectLogin',
failureRedirect: '/users/login',
failureFlash: true
})(req, res, next);
});
Remember that passport.deserializeUser() attaches the user object to req.user, which allows you to access any attributes of that object.

Express & Passport login request does not close/finish

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);

Resources