Search code examples
node.jsauthenticationpassport.jsejspassport-local-mongoose

While Login if password is wrong, want to render login.ejs instead of page that says "unauthorized" using passport-local-mongoose


I am trying to learn how to use passport, passport-local, passport-local-mongoose, express-session. What I want is when the password is incorrect, the login.ejs should be rendered. However, it is displaying a message, "unauthorized" instead rendering the login.ejs. I am not able to figure out where am I going wrong or where should I make changes so that the page renders login.ejs .

login.ejs (I have used bootstrap v5.0 for the form validation)

<%-include("partials/header.ejs")%>
<div class="sign-heading"><h1>Login</h1></div>
<div class="sign">
  <form action="/login" method="POST" class="needs-validation" novalidate>
    <div class="mb-3">
      <label for="InputUsername" class="form-label">Username</label>
      <% if (!exists) { %>
      <input type="text" class="form-control is-invalid" id="InputUsername" name="username" required>
      <div class="invalid-feedback">
        Wrong username and password.
      </div>
      <% }else{ %>
        <input type="text" class="form-control" id="InputUsername" name="username" required>
      <% } %> 
    </div>
    <div class="mb-3">
      <label for="InputPassword" class="form-label" >Password</label>
      <input type="password" class="form-control" id="InputPassword" name="password" required>
    </div>
    <div class="pb-3"></div>
    <button type="submit" class="btn btn-primary">Register</button>
  </form>
</div>
<%-include("partials/footer.ejs")%>

app.js

const bodyParser = require("body-parser");
const mongoose = require("mongoose");
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(express.static(__dirname+"/public"));
app.set('view engine', 'ejs');

app.use(session({
    secret: 'This is my personal diary.',
    resave: false,
    saveUninitialized: false,
  }));

app.use(passport.initialize());
app.use(passport.session());

  mongoose.connect("mongodb://localhost:27017/diaryDB",{useNewUrlParser:true, useUnifiedTopology: true });
  mongoose.set("useCreateIndex",true);

  const entrySchema=new mongoose.Schema({
      title: String,
      body: String
  });
  const diarySchema=new mongoose.Schema({
      username:String,
      password:String,
      entry: [entrySchema]
  });
  
  diarySchema.plugin(passportLocalMongoose);

  const Entry=mongoose.model("Entry",entrySchema);
  const Diary=mongoose.model("Diary",diarySchema); 

  passport.use(Diary.createStrategy());

  passport.serializeUser(Diary.serializeUser());
  passport.deserializeUser(Diary.deserializeUser());

app.get("/",function(req, res){
    res.render("home",{});
});

app.get("/register",function(req, res){
    res.render("register",{exists:false});
});
app.post("/register", function(req, res){
    let username=req.body.username;
    let password=req.body.password;

    Diary.register({username:username},password,function(err,diary){
        if(err){
            res.render("register",{exists:true});
        }
        else{
            passport.authenticate("local")(req,res,function(){
                res.redirect("/diary/"+username);
            });
        }
    });
});


app.get("/login",function(req, res){
    res.render("login",{exists:true});
});

app.post("/login",function(req,res){
    let username=req.body.username;
    let password=req.body.password;

    Diary.findOne({username:username},function(err,diary){
        if(diary){
            req.login(diary,function(err){
                if(err){
                    console.log(err);
                    res.redirect("login",{exists:false});
                }
                else{
                         passport.authenticate("local")(req,res,function(){
                        res.redirect("/diary/"+diary.username);
                    });
                }
            });
        }else{
            res.render("login",{exists:false});
        }
    });
});

app.get("/diary/:customName",function(req, res){
    let customName=req.params.customName;
    if(req.isAuthenticated()){ 
        res.render("diary",{username:customName});
    }else{
        res.redirect("/login");
    }
});

app.get("/write",function(req, res){
    res.render("write",{});
});
app.get("/entry",function(req, res){
    res.render("entry",{});
});
app.get("/delete",function(req, res){});

app.get("/logout",function(req,res){
    req.logout();
    res.redirect("/");
});

app.listen(3000,function(){
    console.log("Server has started.");
});

Just the "/login"

app.get("/login",function(req, res){
    res.render("login",{exists:true});
});

app.post("/login",function(req,res){
    let username=req.body.username;
    let password=req.body.password;

    Diary.findOne({username:username},function(err,diary){
        if(diary){
            req.login(diary,function(err){
                if(err){
                    console.log(err);
                    res.redirect("login",{exists:false});
                }
                else{
                         passport.authenticate("local")(req,res,function(){
                        res.redirect("/diary/"+diary.username);
                    });
                }
            });
        }else{
            res.render("login",{exists:false});
        }
    });
});

Solution

  • you need check if user credentials are correct if yes then proceed if not then re-render the login screen with appropriate message

    here is what i did in one of my project like practo

    router.post("/emailsignin", (req, res, next) => {
      let errors = [];
      USer.findOne({ email: req.body.email })
        .then((user) => {
          if (!user) {
            req.flash("error_msg", "email is not registered please signup");
            res.redirect("/users/signup");
          }
          if (user) {
            bcrypt.compare(req.body.password, user.password, function (err, res) {
              if (res) {
              } else {
                errors.push({ msg: "Wrong Password" });
              }
            });
    
            if (user.role === "doctor") {
              return passport.authenticate("local", {
                successRedirect: "/users/doctorDetails",
                failureRedirect: "/users/emailsignin",
                success_msg: req.flash("success_msg", "successfully logged in"),
                failureFlash: true,
                successFlash: true,
              })(req, res, next);
            }
            if (user.role === "admin") {
              return passport.authenticate("local", {
                successRedirect: "/users/admin",
                failureRedirect: "/users/emailsignin",
                success_msg: req.flash("success_msg", "successfully logged in"),
                failureFlash: true,
                successFlash: true,
              })(req, res, next);
            } else {
              req.session.name = user.name;
              return passport.authenticate("local", {
                successRedirect: "/",
                success_msg: req.flash("success_msg", "successfully logged in"),
                failureRedirect: "/users/emailsignin",
                error_msg: req.flash("error_msg", "password or email is wrong"),
                failureFlash: true,
    
                // successFlash: "Welcome!",
              })(req, res, next);
            }
          } else {
            console.log("error");
          }
        })
        .catch((err) => console.log(err));
    });
    

    here first check if email id exist in database

    if yes then check whether passwords are correct if not then simply push the error message using flash messages

    if everything goes well then login accordinghly