I am trying to develop a small project where I am using passport js for authentication, I am facing challenges in passport.authenticate method in both login and signup pages, it doesn't goes inside the method and does not redirect or render desired destination.
home.ejs
file
<!DOCTYPE html>
<html>
<head>
<title></title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css2?family=Mitr:wght@500&display=swap" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="css/biodata.css">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<a class="navbar-brand justify-content-around" id="navbar-home" href="/">Home</a>
<div class="ml-auto" id="navbar-joint">
<a class="navbar-brand" href="/signup">Sign Up</a>
<a class="navbar-brand" href="/logout">Logout</a>
</div>
</nav>
<div class="card">
<div class="card-body">
<form action="/bioform" method="POST">
<h2 class="d-flex justify-content-center">LOGIN</h2>
<div class="form-group">
<input type="text" class="form-control form-control-lg" id="username" name="username" placeholder="Username">
</div>
<div class="form-group">
<input type="password" class="form-control form-control-lg" id="inputPassword" name="inputPassword" placeholder="Password">
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary btn-lg btn-block">Submit</button>
</div>
<a href="/signup" class="d-flex justify-content-end">New User</a>
</form>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
</body>
</html>
signup.ejs
file
<!DOCTYPE html>
<html>
<head>
<title></title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css2?family=Mitr:wght@500&display=swap" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="css/biodata.css">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<a class="navbar-brand justify-content-around" id="navbar-home" href="/">Home</a>
<div class="ml-auto" id="navbar-joint">
<a class="navbar-brand" href="/signup">Sign Up</a>
<a class="navbar-brand" href="/logout">Logout</a>
</div>
</nav>
<div class="card" id="signup-card">
<div class="card-body" id="signup-card-body">
<form action="/register" method="POST">
<h3 class="d-flex justify-content-center">SIGN UP</h3>
<div class="form-group">
<input type="text" class="form-control form-control-lg" id="username" name="username" placeholder="Username">
</div>
<div class="form-group">
<input type="email" class="form-control" id="email" name="email" placeholder="Email">
</div>
<div class="form-group">
<input type="password" class="form-control form-control-lg" id="inputPassword" name="inputPassword" placeholder="Password">
</div>
<div class="form-group">
<input type="password" class="form-control form-control-lg" id="confirminputPassword" name="confirminputPassword" placeholder="Confirm Password">
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" id="exampleCheck1" name="exampleCheck1">
<label class="form-check-label" for="exampleCheck1">I agree</label>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary btn-lg btn-block">Submit</button>
</div>
</form>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
</body>
</html>
User.js
file
var mongoose = require("mongoose");
var passportLocalMongoose = require("passport-local-mongoose");
var usersSchema = new mongoose.Schema({
username:String,
password:String,
email:String
});
usersSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("User",usersSchema);
app.js
file
var express = require("express");
var app = express();
var mongoose = require("mongoose");
var passport = require("passport"),
localStrategy = require("passport-local");
const User = require("./models/User");
var expressSession = require("express-session");
mongoose.connect('mongodb://localhost/users', {useNewUrlParser: true, useUnifiedTopology: true}).catch(function(reason){
console.log('Unable to connect to the mongodb instance. Error: ', reason);
});
app.set('view engine', 'ejs');
var bod = require("body-parser");
app.use(bod.urlencoded({extended:true}));
app.use(passport.initialize());
app.use(passport.session());
app.use(expressSession({
secret:"Test Key",
resave:false,
saveUninitialized:false
}));
passport.use(new localStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
app.use(express.static(__dirname + '/resources'));
app.get("/", function(req, res) {
res.render("home");
});
app.get("/home", function(req, res) {
res.render("home");
});
app.post("/bioform",passport.authenticate("local",{
failureRedirect:"/home"
}),function(req,res){
console.log(req.body);
res.render('bioform', {userName:req.body.username})
});
app.post("/register",function(req,res){
var userName = req.body.username;
var inputPassword = req.body.inputPassword;
var email = req.body.email;
var exampleCheck1 = req.body.exampleCheck1;
var confirminputPassword = req.body.confirminputPassword;
if(exampleCheck1==="on"){
if(inputPassword===confirminputPassword){
User.register( new User({username:userName,email:email}),inputPassword, function(err,user){
console.log("Inside first");
if(err){
console.log(err);
return res.render("signup");
}
passport.authenticate("local",function(err,user,info){
//the control doesn't reach this point.
console.log("Inside second");
if(err){
return console.log(err);
}
if (!user) { return res.redirect('/home'); }
req.logIn(user, function(err) {
if (err) { console.log(err); }
return res.redirect('bioform', {userName:userName});
});
});
/*
//this startegy didn't work either
passport.authenticate("local")(req,res,function(){
console.log("Reached here ");
res.render("bioform",{userName:userName});
});
*/
});
}else{
console.log("Passwords doesn't match!!!");
res.render("signup");
}
}else{
console.log("Agree to Terms!!!");
res.render("signup");
}
});
function isLoggedIn(req,resp,next){
if(req.isAuthenticated()){
return next();
}else{
res.redirect("/home");
}
}
app.get("/signup", function(req, res) {
res.render("signup");
});
app.listen(3000,function(){
console.log("Server started");
});
passport.authenticate() seems to be the problem here, either it will display a Bad Request message or just does nothing and tries to load the requested page without success. Will deeply appreciate your help in this issue. Thanks
Update: Here is what worked for me, I wrote a new post method
app.post("/register",function(req,res){
var username = req.body.username;
var password = req.body.password;
var email = req.body.email;
User.register({username:username,email:email},password,function(err,user){
console.log("post here")
if(err){
return console.log(err);
}
if(!user){
return res.redirect('/signup');
}
req.login(user, function(err){
if(err){
return console.log(err);
}
console.log("post");
res.render("bioform",{currentUser:req.user});
});
});
});
Reverse the order of your middleware - your express sessions should be declared before passport sessions, otherwise passport will be unable to use them:
app.use(expressSession({
secret:"Test Key",
resave:false,
saveUninitialized:false
}));
app.use(passport.initialize());
app.use(passport.session());
You have some other issues as well - passport.authenticate()
should not be called in your /register
route. You are currently calling req.login()
inside of passport.authenticate
when it should be called on its own; see this StackOverflow answer as well as Passport Login Docs. You will want to do something like this:
User.register(/* ... */, function(err, user) {
if (err) {
return res.redirect('/signup');
} else {
req.login(user, function(err) {
if (!err) {
return res.redirect('/home');
} else {
// handle error
}
});
}
});
Take a closer look at passport-local-mongoose which has some simplified configuration starting with their 0.2.1 version, passport docs, and this Express LocalStrategy example. Manually register a user in your Mongoose database and test the authentication strategy with that user. Once you have that working you can move on to your /register
route, assuming you are attempting to auto-login after registration