I am trying to build a registration and login page using passport-local-mongoose.
When I click on submit signup button I get an error which says bad request.
I am getting "Bad Request" while registering, but the details are being stored in MongoDB. Not sure where I am making a mistake.
Please help me out.
Here is my register POST API.
let express = require('express');
let mongoose = require('mongoose');
const passport = require('passport');
const LocalStrategy = require('passport-local');
const passportLocalMongoose = require('passport-local-mongoose');
var expressValidator = require('express-validator');
const bodyParser = require('body-parser')
const { check, validationResult } = require('express-validator');
const Admin = require('../models/admin-model');
let router = express.Router();
const app = express();
//Creating a Secret Key to Hash Password
router.use(require('cookie-session')({
secret: 'jdkjhLGUL#^&%^%(*)&^%#!gkjh', // Encode/Decore Session
resave: false,
saveUninitialized: false
}));
passport.use(new LocalStrategy({
usernameField: 'email',
passwordField: 'password'
}, Admin.authenticate()));
//Encrypting and Decrypting the Password for Security
passport.serializeUser(Admin.serializeUser()); //session Encoding
passport.deserializeUser(Admin.deserializeUser());
// passport.use(new LocalStrategy(Admin.authenticate()));
//Setting the View Engine to take EJS Pages
app.set('view engine', "ejs");
app.set('views', "./views")
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(passport.initialize());
app.use(passport.session());
app.use(express.static(__dirname + '/public'));
mongoose.connect("mongodb://localhost:27017/node-auth-db", { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => console.log('Connected to node-auth-db successfully....!'))
.catch(err => console.log(err))
router.get('/', (req, res) => {
res.render('home');
});
router.get('/login', (req, res) => {
res.render('signin');
});
router.post('/login', passport.authenticate("local", {
successRedirect: '/admin/addnews',
failureRedirect: '/login'
}));
//Registration
router.get('/register', (req, res) => {
res.render('signup');
});
router.post('/register', (req, res) => {
Admin.findOne({ username: req.body.email }, (err, result) => {
if (err) throw err;
if (!result) {
Admin.register(new Admin({ name: req.body.name, username: req.body.email }),
req.body.password, function (err, admin) {
if (err) throw err;
passport.authenticate("local")(req, res, function () {
res.redirect('/admin/login');
})
}
)
}
else {
res.redirect('/admin/register');
}
});
});
//Add News
router.get('/addnews', isLoggedIn, (req, res) => {
res.render('addnews');
});
router.post('/addnews', (req, res) => {
News.create(req.body, (err, data) => {
if (err) throw err;
const htmlMsg = encodeURIComponent('Added News DONE !');
res.redirect('/admin/addnews');
})
});
//Creating a Authentication Token to secure the logging and Logout.
function isLoggedIn(req, res, next) {
if (req.isAuthenticated()) {
return next();
}
res.redirect('/admin/login');
}
router.get('/logout', (req, res) => {
req.logOut();
res.redirect('/admin');
});
module.exports = router;[]
Might be the issue is here you are passing req.body.password outside admin module
Admin.register(new Admin({ name: req.body.name, username: req.body.email, req.body.password}), function (err, admin) {
if (err) throw err;
passport.authenticate("local")(req, res, function () {
res.redirect('/admin/login');
})
}
)
Related
I am new to the Passport.js. Whenever I login or register through the routes, req.isAuthenticated() always returns false and the secrets view is never rendered. Here is my app.js:
`
require("dotenv").config();
const express = require("express");
const bodyParser = require("body-parser");
const session = require("express-session");
const passport = require("passport");
const LocalStrategy = require("passport-local")
const passportLocalMongoose = require("passport-local-mongoose");
const mongoose = require("mongoose");
mongoose.set("strictQuery", true);
uri = "mongodb://localhost:27017/usersDB";
const userSchema = new mongoose.Schema({
username: String,
password: String
});
userSchema.plugin(passportLocalMongoose);
const User = new mongoose.model("User", userSchema);
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
const app = express();
app.use(bodyParser.urlencoded({extended: true}));
app.use(express.static("public"));
app.set("view engine", "ejs");
app.use(session({
secret: "MyLittleSecret",
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
app.get("/", function(req, res) {
res.render("home");
});
app.get("/secrets", function(req, res) {
if(req.isAuthenticated) {
res.render("secrets");
} else {
res.redirect("/login");
}
});
app.route("/register")
.get(function(req, res) {
res.render("register");
})
.post(async function(req, res) {
await User.register({username: req.body.username}, req.body.password, function(err, user) {
console.log("In the User.register callback function");
if(err) {
console.log(err);
res.redirect("/register");
} else {
passport.authenticate("local")(req, res, function() {
res.redirect("/secrets");
});
}
});
});
app.route("/login")
.get(function(req, res) {
res.render("login",{
errorMessage: ""
});
})
.post(async function(req, res) {
const userInstance = new User({
username: req.body.username,
password: req.body.password
});
req.login(userInstance, function(err) {
if(err) {
console.log(err);
} else {
passport.authenticate("local")(req,res,function() {
res.redirect("/secrets");
});
}
});
});
app.listen(3000, function() {
console.log("Server started listening to port 3000");
});
I searched on the web and tried the various orders of middleware. I could not solve the problem.
I am practicing of using passport.js for authentication but there is a problem in login part. I've tried to solve the problem by different way but nothing was successful, the problem is even after changing the passport.serialize to (user, done) the code worked but if I enter any fake password and username, it authenticate me.
How do I solve it?
// npm i passport passport-local passport-local-mongoose express-session
const express = require("express");
const app = express();
const bodyParser = require("body-parser");
app.use(express.urlencoded({ extended: false }));
app.use(express.static("public"));
const session = require("express-session"); // session first
const passport = require("passport"); //then passport
const passportLocalMongoose = require("passport-local-mongoose"); // last passport-local-mongoose
// no need to passport-local
app.use(session({ // use the session first and set it up
secret: "this is our secrete",
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize()); // then use passport to initialize
app.use(passport.session()); // then use passport to deal with session
const mongoose = require("mongoose");
mongoose.connect("mongodb://localhost:27017/authentication", { useNewUrlParser: true, useUnifiedTopology: true })
mongoose.set("useCreateIndex", true); // to prevent the deprecation message
const authSchema = new mongoose.Schema({
email: String,
password: String
})
authSchema.plugin(passportLocalMongoose); //plug passportLocalMongoose in the schema
const Auth = new mongoose.model("Auth", authSchema);
passport.use(Auth.createStrategy());
passport.serializeUser(Auth.serializeUser()); // put a message in a cookie
passport.deserializeUser(Auth.deserializeUser()); // destroy the cookie and reveal the message
app.get("/", (req, res) => {
res.sendFile(__dirname + "/index.html");
})
app.get("/register", (req, res) => {
res.sendFile(__dirname + "/register.html");
})
app.get("/login", (req, res) => {
res.sendFile(__dirname + "/login.html");
})
app.get("/success", (req, res) => {
res.sendFile(__dirname + "/success.html");
})
app.get("/secret", (req, res) => {
console.log(req.isAuthenticated());
if (req.isAuthenticated()) {
res.sendFile(__dirname + "/secret.html")
} else {
res.sendFile(__dirname + "/login.html")
}
})
app.post("/register", (req, res) => {
var regEmail = req.body.email;
var regPassword1 = req.body.password1;
var regPassword2 = req.body.password2;
if (regPassword1 === regPassword2) {
Auth.register({ username: regEmail }, regPassword1, (err, user) => {
if (err) throw err;
passport.authenticate('local')
res.redirect("/success")
})
}
})
app.post("/login", (req, res) => {
const user = new Auth({
email: req.body.email,
password: req.body.password
});
req.login(user, (err) => {
if (err) throw err;
passport.authenticate("local")
res.redirect("/secret")
})
})
var port = 3000;
app.listen(port, () => {
console.log(`listening to ${port}`);
})
Currently the /login route is creating a new user by calling new Auth() and logging in with it regardless of if the password does not match the one being stored.
You should be able to use the passport.authenticate method on your route to verify that the user is registered in your Mongo database. This method also automatically calls req.login.
app.post("/login", passport.authenticate("local",{
successRedirect: "/secret",
failureRedirect: "/login"
}));
Here is a fully example that uses passport-local-mongoose for reference: https://gist.github.com/yukeehan/23fbbe53f1ca94be440161c1562b489a
I am using node.js express with sequelize and database postgreSql.the problem is in passport login failureRedirect works properly sucessRedirect does not redirect to the page that I want. It still loading and not responding anything and does not come any error.
when I submit login it will check for errors if errors it will work perfectly in failureRedirect but in Success it does not work like page has loading only not goes to the destination page and if I stop the project and restart the project it will be in destination page!! i dont know what is the problem help me.
mainController.js
const express = require("express");
const sessions = require("express-session");
require("../model/MasterUser.model");
const passport = require("passport");
var session = sessions;
const router = express.Router();
router.get("/dashboard", (req, res) => {
res.render('dashboard');
});
router.get("/login", (req, res) => {
res.render("login", { layout: "login.hbs" });
});
router.post(
"/login",
passport.authenticate("local", {
successRedirect: "/main/dashboard",
failureRedirect: "/main/login",
failureFlash: true,
})
);
module.exports = router;
passport.js
const LocalStrategy = require("passport-local").Strategy;
const bcrypt = require("bcryptjs");
const sequelize = require("sequelize");
const masterUser = require("../model/MasterUser.model");
module.exports = function (passport) {
passport.use(
new LocalStrategy(
{ usernameField: "user_name" },
(user_name, password, done) => {
// Match user
masterUser.findOne({ where: { user_name: user_name } }).then((user) => {
if (!user) {
return done(null, false, {
message: "This username 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((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
masterUser.findByPk(id, (err, user) => {
done(err, user);
});
});
};
index.js
const express = require("express");
const Handlebars = require("handlebars");
var flash = require("connect-flash");
const app = express();
const path = require("path");
const bodyparser = require("body-parser");
const expressHandlebars = require("express-handlebars");
const passport = require("passport");
const sessions = require("express-session");
var session = sessions;
const MainController = require("./controllers/MainController");
const db = require("./config/database");
//test db
db.authenticate()
.then(() => console.log("Database Connected..."))
.catch((err) => console.log("error" + err));
//for security purpose
const cors = require("cors");
app.use(
cors()
);
//Passport Config
require("./config/passport")(passport);
app.use(cookieParser());
//use body parser
app.use(bodyparser.json());
app.use(bodyparser.urlencoded({ extended: true }));
const {
allowInsecurePrototypeAccess,
} = require("#handlebars/allow-prototype-access");
app.use(
bodyparser.urlencoded({
urlencoded: true,
})
);
app.use(
sessions({
secret: "secret_key",
resave: false,
saveUninitialized: true,
cookie: { maxAge: 60000 },
})
);
// use flash for show messages
app.use(flash());
// Passport middleware
app.use(passport.initialize());
app.use(passport.session());
//flash messages
app.use((req, res, next) => {
res.locals.success_msg = req.flash("success_msg");
res.locals.error_msg = req.flash("error_msg");
res.locals.error = req.flash("error");
next();
});
//setting up view Engine
app.set("views", path.join(__dirname, "/views"));
//using the hbs
app.engine(
"hbs",
expressHandlebars({
extname: "hbs",
defaultLayout: "default",
layoutsDir: __dirname + "/views/layouts",
handlebars: allowInsecurePrototypeAccess(Handlebars),
})
);
app.set("view engine", "hbs");
//route for Main
app.use("/main", MainController);
//default
app.get("/", (req, res) => {
res.render("login");
});
app.listen(3000, () => {
console.log("App listening on port 3000!");
});
the problem has been solved guys I made done wrong code in deserializeUser.
passport.js before
passport.deserializeUser((id, done) => {
masterUser.findByPk(id, (err, user) => {
done(err, user);
});
});
};
passport.js after
passport.deserializeUser(function (id, done) {
masterUser.findOne({ where: { id: id } }).then((user) => {
done(null, user);
});
});
the problem is for sequelize get the user data is different so now its worked for me.this is useful for who using express with sequelize and passport with postgresql
I'm working through a learning module on authentication and security and I'm trying to get passport up and running but I seem to be having trouble. The code included below all works as you'd expect, except that when users are redirected from the /register post route to the /secrets route, they are not authenticated, in spite of .register() having worked (otherwise the logic in the route would have redirected me back to the /register get route instead of the login page via the secrets route).
require("dotenv").config();
const express = require("express");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const ejs = require("ejs");
const session = require("express-session");
const passport = require("passport");
const passportLocalMongoose = require("passport-local-mongoose");
const app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(express.static("public"));
app.set("view engine", "ejs");
app.use(
session({
secret: "Our little secret.",
resave: false,
saveUninitialized: false
})
);
app.use(passport.initialize());
app.use(passport.session());
mongoose.connect("mongodb://localhost:27017/userDB", { useNewUrlParser: true });
mongoose.set("useCreateIndex", true);
const userSchema = new mongoose.Schema({
username: String,
password: String
});
userSchema.plugin(passportLocalMongoose);
const Users = new mongoose.model("Users", userSchema);
passport.serializeUser(Users.serializeUser());
passport.deserializeUser(Users.deserializeUser());
app.listen(3000, (req, res) => {
console.log("Listening on port 3000.");
});
app.get("/", (req, res) => {
res.render("home");
});
app.get("/login", (req, res) => {
res.render("login");
});
app.get("/register", (req, res) => {
res.render("register");
});
app.get("/secrets", (req, res) => {
console.log(req.isAuthenticated())
if (req.isAuthenticated()) {
res.render("secrets");
} else {
res.redirect("/login");
}
});
app.post("/register", (req, res) => {
console.log(req.body.username)
console.log(req.body.password)
Users.register(
{ username: req.body.username },
req.body.password,
(error, user) => {
if (error) {
console.log('there was an error: ', error);
res.redirect("/register");
} else {
passport.authenticate("local")(req, res, () => { //////////////not authenticating
res.redirect("/secrets");
});
}
}
);
});
app.post("/login", (req, res) => {});
any help figuring out why isAuthenticaed() is returning false would be greatly appreciated. thank you :)
You have to define your local strategy :
var passport = require('passport')
, LocalStrategy = require('passport-local').Strategy;
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);
});
}
));
here it has queried User information from the database ( Mongodb for instance) in case of successful response it will pass.
I am using nodejs as backend server while my frontend is in angular. I need to call the register router and for that i am sending the data from frontend in json fromat which is perfect but since i am trying to passport authentication here, i took passport authentication code from another github repository in which node was also using an engine so that's why res.render was used in it. But now i am finding it difficult to remove this particular line from the register router and if i try to delete it or just use res.sendStatus(500) it still does not work and i get 500 error. What could be the solution of this problem?
var express = require('express');
var mongoose = require('mongoose');
var bodyparser = require('body-parser');
var cors = require('cors');
var session = require('cookie-session');
var flash = require('connect-flash');
var passport = require('passport');
var bcrypt = require('bcryptjs');
require('./config/passport')(passport);
var User = require('./models/User');
var app = express();
app.use(bodyparser.json());
app.use(cors());
var expiryDate = new Date(Date.now() + 60 * 60 * 1000) // 1 hour
app.use(session({
name: 'session',
keys: ['key1', 'key2'],
cookie: {
secure: true,
httpOnly: true,
domain: 'example.com',
path: 'foo/bar',
expires: expiryDate
}
}))
app.set('port', process.env.port || 3000);
app.use(passport.initialize());
app.use(passport.session());
// Connect flash
app.use(flash());
// Global variables
app.use(function(req, res, next) {
res.locals.success_msg = req.flash('success_msg');
res.locals.error_msg = req.flash('error_msg');
res.locals.error = req.flash('error');
next();
});
var db = mongoose.connect("mongodb://localhost:27017/server", {
useNewUrlParser: true
}, function(err, response) {
if (err) {
console.log('There is error in connecting with mongodb');
}
console.log('Connection has been established.');
});
app.get('/', (req, res) => {
res.send("hello");
});
//Trying registering with passport
app.post('/register', (req, res) => {
console.log(req.body);
const { firstname, lastname, email, password } = req.body;
let errors = [];
if (errors.length > 0) {
res.render('register', {
errors,
name,
email,
password,
password2
});
} else {
User.findOne({ email: email }).then(user => {
if (user) {
errors.push({ msg: 'Email already exists' });
res.render('register', {
errors,
firstname,
lastname,
email,
password
});
} else {
const newUser = new User({
firstname,
lastname,
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('/login');
})
.catch(err => console.log(err));
});
});
}
})
.catch(err => console.log(err))
}
});
//end
app.post('/login', (req, res, next) => {
console.log(req.body);
passport.authenticate('local', {
successRedirect: '/dashboard',
failureRedirect: '/login',
failureFlash: true
})(req, res, next);
});
app.listen(app.get('port'), function(err, response) {
console.log("Server is running");
});
You are using res.render() in the callback function in app.post('/register', callback). If res.render() is called it will look for a template (probably in a views directory). If you have not specified which engine to use you will get that error.