Passing parameters in POST in Express with Passport - javascript

I have made a small login application using Express and Passport. But it seems I can't direct the user into a specific userprofile. What has to happen is, the user fills up an HTML form, and he has to get redirected to his own profile page (For the sake of simplicity, lets say that page differs from other user pages only in terms of the title). I have this in my user routes. (i.e. routes/users.js)
router.get('/userprofile', authenticationMiddleware(), function (req,
res, next) {
res.render('userprofile');
});
router.post('/login', passport.authenticate('local-login', {
successRedirect: '/users/userprofile',
failureRedirect: '/users/login',
failureFlash: true
}));
In my passport.js config file I have this.
passport.use('local-login', new LocalStrategy({
usernameField: 'username',
passwordField: 'password',
passReqToCallback: true
}, function (req, username, password, done) {
db.pool.getConnection(function (err, connection) {
if(err) throw err;
var query = connection.query('SELECT * from users WHERE username = ?', username, function (err, rows) {
if(err) return done(err);
if(!rows.length) {
return done(null, false, req.flash('loginMessage', 'No User Found'));
}
//Comparing passwords using bcrypt
bcrypt.compare(password, rows[0].password, function(error, res){
if(res){
return done(null, rows[0]);
} else {
return done(null, false, req.flash('loginMessage', 'Oops! Wrong password.'));
}
});
});
});
}));
What I need to do is get the username from the form, and pass it to the successRedirect attribute in passport.authenticate, and then I can modify the get method adding a route parameter like '/users/:username' and render 'username' view.
How can I do this?
EDIT:
I did something like this.
router.get('/userprofile/:username', authenticationMiddleware(), function (req, res, next) {
res.render('userprofile', {
username: req.params.username,
title: 'Welcome, '+ req.params.username
});
});
router.post('/login', function (req, res, next) { //Testing callback.
console.log("Username is: " + req.body.username);
passport.authenticate('local-login', {
successRedirect: '/users/userprofile/' + req.body.username,
failureRedirect: '/users/login',
failureFlash: true
})(req, res);
next();
});
This works on some attempts. However, it returns this error sometimes.
POST /users/login 404 43.741 ms - 5226 /home/dasun/WebstormProjects/schoolentry/node_modules/passport/lib/middleware/authenticate.js:249
if (err) { return next(err)};
How can I get rid of this error?
Thanks.

Found the answer. I have missed next in POST method in /login route.
i.e. I should write
router.post('/login', function (req, res, next) { //Testing callback.
console.log("Username is: " + req.body.username);
passport.authenticate('local-login', {
successRedirect: '/users/userprofile/' + req.body.username,
failureRedirect: '/users/login',
failureFlash: true
})(req, res, next);
});

Related

Express only redirect to desired page when successRedirect exists in passport.authenticate

I got some issues with a Node Express app. It will not redirect when I removed successRedirect property in auth method by passport.
The code below will not redirect to the desired page if I removed the successRedirect, and replacing it with a callback funtction.
The default code from defaultController.js
// passport local strategy
passport.use(new LocalStrategy({
usernameField: 'email',
passReqToCallback: true,
}, (req, email, password, done)=>{
User.findOne({ email:email }).then(user=>{
if(!user){
return done(null, false, req.flash('error-message', 'User not found with this email.'));
}
bcrypt.compare(password, user.password, (err, passwordMatched)=>{
if(err){
return err;
}
if(!passwordMatched){
return done(null, false, req.flash('error-message', 'Invalid username or password.'));
}
return done(null, user, req.flash('success-message', 'Login successful'));
});
});
}));
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
router.route('/login')
.get(defaultController.login)
.post(passport.authenticate('local', {
successRedirect: '/admin',
failureRedirect: '/login',
failureFlash: true,
successFlash: true,
session:true,
}), defaultController.loginPost);
And this is what I would like to apply, but it seems it won't work and stuck in a infinite loading on chrome, however on console, it can receive an output:
here’s the output from the console
router.route('/login')
.get(defaultController.login)
.post(passport.authenticate('local', {
// successRedirect: '/admin',
failureRedirect: '/login',
failureFlash: true,
successFlash: true,
session:true,
}), (user)=>{
console.log(user.user.role);
if(user.user.role === 'admin'){
defaultController.loginPost;
}else{
console.log('hi');
}
});
As additional information, here is snippets defaultController that is responsible for handling the request:
login: (req,res)=>{
console.log();
res.render('default/login')
},
loginPost: (req,res)=>{
console.log(req.body.username);
res.render('/admin')
},
Any help?
you should use redirect instead of render so do like this:
login: (req,res)=>{
console.log();
res.redirect('default/login')
},
loginPost: (req,res)=>{
console.log(req.body.username);
res.redirect('/admin')
},

req.user not defined when calling from android application

I am making an android app in partnership with a colleague, he is an Android developer and I know very little about android dev. I do the backend stuff, I made the login and auth using node.js, express, and passport.js.
I hosted the server locally and used postman to check the auth and registration processes, all were working fine. I am getting the status codes my friend wanted for his Front-end. In the authentication part using passport.js when success I am passing req.user which should return the user body, so that my friend on the Front-end can use the field user.firstName from user object to display a welcome message.
Through Postman, the user body is getting defined and I am getting a user object with all fields in the Postman window, but through the app it is giving an error.
firstName is undefined property.
Passport.js logic:
const LocalStrategy = require('passport-local').Strategy;
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
//load user model
const User = require('../models/UserSchema');
module.exports = function(passport){
passport.use(
new LocalStrategy({usernameField: 'roll'}, (roll, password, done) => {
//find user
User.findOne({roll: roll})
.then(user =>{
if(!user){
return done(null, false, {message: 'Roll number 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'});
}
})
})
.catch(err => console.log(err));
})
);
/*passport.serializeUser( function(id, done) {
done(null, User.roll);
});
passport.deserializeUser(function(id, done){
User.findById(roll, function(err, user){
done(err, user);
});
});*/
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser((_id, done) => {
User.findById( _id, (err, user) => {
if(err){
done(null, false, {error:err});
} else {
done(null, user);
}
});
});
}
Login Route:
//Login Handle
router.post('/login', (req, res, next) =>{
console.log('/user/login')
passport.authenticate('local', {
successRedirect: '/success',
failureRedirect: '/failure',
session: true,
failureFlash: false
})(req, res, next);
//res.json(pass.user.name);
});
/success route:
router.get('/success', (req, res) => {
console.log(req);
let message = 'Login Succesful';
//let user = req.user.firstName
res.status(200).json({'message':message, 'user': req.user.firstName});
})
I guess you are also using body-parser or express.json() to parse the incoming body request to JSON. If this is the case you should send the response back like this:
req.body.user.firstName
For POST requests: req.body
For GET parameters: req.params
For GET query strings: req.query

Redirecting users if they aren't using specific domain

I'm trying to redirect users to a route using res.redirect, or send a file using res.send if they attempt to login using a domain other than the one specified. The condition checking is working, but I'm trying to use res.sendFile/res.redirect but it doesn't seem to be working within the scope of this function. It's clear that there isn't a res in this function, but that's all that I've come up with. Had a really good search online but I'm yet to resolve the problem.
Any help is appreciated.
passport.use(
new GoogleStrategy({
callbackURL: '/google/redirect',
clientID: keys.google.clientID,
clientSecret: keys.google.clientSecret
}, function (accessToken, refreshToken, profile, done){
if (profile._json.hd === "HIDDEN-DOMAIN.COM") {
User.findOne({googleId : profile.id})
.then(function(currentUser){
if(currentUser){
console.log('User with ID' + currentUser.googleId +' already exists. No new entry was made');
done(null, currentUser);
} else {
new User({
username: profile.displayName,
googleId: profile.id
})
.save()
.then(function(newUser){
console.log('New user created: ' + newUser);
done(null, newUser);
});
}
})
} else {
console.log(__dirname);
res.sendFile('../login.html');
};
}));
Use a middleware to perform the check, and next() if it passes.
Checkout: https://expressjs.com/en/guide/using-middleware.html
This example shows a middleware function mounted on the / path. The function is executed for any type of HTTP request on the / path.
This example shows a route and its handler function (middleware system). The function handles GET requests.
app.use('/', function (req, res, next) {
// Check 1
console.log('Request URL:', req.originalUrl)
next()
}, function (req, res, next) {
// Check 2: Pass first check
console.log('Request Type:', req.method)
next()
})
app.get('/', (req, res) => {
// Final Route
});
Example:
app.use('/first', function (req, res, next) {
passport.use(
new GoogleStrategy({
callbackURL: '/google/redirect',
clientID: keys.google.clientID,
clientSecret: keys.google.clientSecret
}, function (accessToken, refreshToken, profile, done){
if (profile._json.hd === "HIDDEN-DOMAIN.COM") {
User.findOne({googleId : profile.id})
.then(function(currentUser){
if(currentUser){
console.log('User with ID' + currentUser.googleId +' already exists. No new entry was made');
done(null, currentUser);
} else {
new User({
username: profile.displayName,
googleId: profile.id
})
.save()
.then(function(newUser){
console.log('New user created: ' + newUser);
done(null, newUser);
next(); // next();
});
}
})
} else {
console.log(__dirname);
next(); // next();
}
}));
}, function (req, res, next) {
// More checks
next()
});
app('/', (req, res) => {
// final route here
res.sendFile('../login.html');
})

Passport js redirects not working

Okay so I have implemented passportjs EXACTLY like my other projects which work perfectly, but for some reason in my current project I just cant get it to success/failure redirect.
Here's my code
route
app.post('/login', passport.authenticate('login', {
successRedirect: '/#1',
failureRedirect: '/#2',
failureFlash: true
}));
app.post('/login',
passport.authenticate('login', {failureRedirect: '/login'}),
function (req, res) {
console.log("logged");
res.redirect('/#1');
});
^ I tried it two different ways,in the second way, the 'logged' did not get logged..
Passport
//SIGN IN
passport.use('login', new LocalStrategy({
usernameField: 'username',
passwordField: 'password',
passReqToCallback: true
},
function (req, username, password, done) {
User.findOne({'username': username}, function (err, user) {
console.log("found: " + user);
if (err) {
console.log(err);
}
if (!user) {
return done(null, false, req.flash('message', 'Username not in DB'));
}
if (!user.checkPass(password)) {
return done(null, false, req.flash('message', 'Incorrect Password'));
}
//return user if all of the above pass
return done(null, user);
});
}));
EDIT: the passport code does work well, meaning it goes right towards the end and I can console.log the correct user.

Passport callback isn't called

I build an application using Passport lib using this tutorial (part of it).
Note, I don't need a registration, only login form.
One of the issues is that my LocalStrategy callback is never called. For storing I use mongo:
mongoose.connect(dbConfig.url, {
useMongoClient: true
});
//dbConfig
module.exports = {
'url' : 'mongodb://localhost/passport'
}
Login route looks like this:
module.exports = function(app, passport) {
app.get('/login', function(req, res) {
res.render('login', {
message: req.flash('loginMessage')
});
});
app.post('/login', passport.authenticate('login', {
successRedirect: '/', // redirect to the secure profile section
failureRedirect: '/login', // redirect back to the signup page if there is an error
failureFlash: true // allow flash messages
}));
}
Passport logic is:
module.exports = function(passport) {
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('login', new LocalStrategy({
passReqToCallback: true
}, function(req, username, password, done) {
console.log('start'); // never called
User.findOne({
'local.email': email
}, function(err, user) {
if (err) {
return done(err);
}
if (!user) {
return done(null, false, req.flash('loginMessage', 'No user found.'));
}
if (!user.validPassword(password)) {
return done(null, false, req.flash('loginMessage', 'Oops! Wrong password.'));
}
return done(null, user);
});
}));
};
console.log('start'); is never called, although passport.authenticate('login' ...) is called.
What can be an issue?
I finally fixed it and everything works. In case anyone face the same issues I'm posting here several problems and solutions.
The req.body was empty in my app.post, because I didn't add body parser. Fixed it with:
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
Username field was empty all the time because I named it as email and passport expected username. Fixed with:
new LocalStrategy({
usernameField: 'email', // this parameter
passReqToCallback: true
}

Categories