When ever I submit a from to login in or get registered I get 400 bad request. But in register route the user get registered but it also gives bad request. When we go to login route same as register route I get BAD REQUEST. 0
I am using the following dependencies:
express session
passport
passport-local
passport-local-mongoose
Is there something wrong with the implementation of the passport-local-mongoose or its passport side or serialize or deserialize the user. Can anybody help me with this problem I am stuck on this for three days. Here is some code.
//-----------------------//Require---------------------
const express = require("express");
const app = express();
const bodyParser = require("body-parser");
const ejs = require("ejs");
const session = require("express-session");
const passport = require("passport");
const LocalStrategy= require("passport-local").Strategy;
const passportLocalMongoose = require("passport-local-mongoose");
const mongoose = require("mongoose");
//-----------------------//App.use---------------------
app.use(express.static("public"));
app.set("view engine", "ejs");
app.use(bodyParser.urlencoded({extended: true}));
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true
}));
//-----------------------//Passport---------------------
app.use(passport.initialize());
app.use(passport.session());
//-----------------------//Mongoose---------------------
mongoose.connect('mongodb://localhost/Twitter', {useNewUrlParser: true, useUnifiedTopology: true});
mongoose.set('useCreateIndex', true);
const tweetschema = new mongoose.Schema({
username: String,
password: String,
tweets: String
});
//-----------------------//Schema Plgin---------------------
tweetschema.plugin(passportLocalMongoose);
//-----------------------//New Model---------------------
const Tweet = new mongoose.model("Tweet", tweetschema);
//-----------------------//Local Strategy-------------------
passport.use(new LocalStrategy(Tweet.authenticate()));
//-----------------------//Seralize Passport---------------------
passport.serializeUser(Tweet.serializeUser());
passport.deserializeUser(Tweet.deserializeUser());
//-----------------------//Get Routes---------------------
app.get("/" ,(req, res)=>{
Tweet.find({}, function(err, founItems){
res.render("home", {founItems:founItems});
});
});
app.get("/tweets", (req, res)=>{
if(req.isAuthenticated()){
res.render("Tweets");
}else{
res.redirect("/login");
}
});
//-----------------------//Post Routes---------------------
app.post("/login", (req, res)=>{
const user = new Tweet({
username: req.body.email,
password: req.body.password
});
req.logIn(user, (err)=>{
if(err){
res.send(err);
}
passport.authenticate("local")(req, res, ()=>{
console.log("Successfull.");
})
})
});
app.post("/reg", (req, res)=>{
Tweet.register({username: req.body.email}, req.body.password, (err, user)=>{
if(err){
console.log(err);
res.redirect("/reg");
}else{
if(user){
passport.authenticate("local")(req, res, ()=>{
res.redirect("/tweets");
console.log("Successfully Regsitered The User!");
})
}
}
})
})
You redirect user to /login route, but you don't have get request for this.
If you have it but not uploaded try this in Seralize Passport
passport.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(function (id, done) {
User.findById(id, function (err, user) {
done(err, user);
});
});
What about this:
app.post("/login", (req, res) => {
const email = req.body.email;
User.findOne({ username: email }, function (err, u) {
if (err) {
console.log(err);
} else {
if (u) {
u.authenticate(req.body.password, (err, model, info) => {
if (info) {
res.send("Wrong email or password!");
}
if (err) {
console.log(err);
} else if (model) {
req.login(u, (err) => {
if (err) {
console.log(err);
} else {
passport.authenticate("local");
req.session.save((error) => {
if (err) {
console.log(err);
} else {
res.redirect("/");
}
});
}
});
}
});
} else {
res.send("Wrong email or password!");
}
}
});
});
So you first search user in the database with email: User.findOne({ username: email }, function (err, u){} I suggest to make username unique username: { type: String, unique: true} in tweetSchema.
After that you check for err. If u exists, you authenticate it with password. According to passport-local-mongoose- u.authenticate(password, (err, model, info)=>{}) has two arguments: password and callback function. In callback we check for info which is "an instance of AuthenticationError describing the reason the password failed, else undefined." After that we check for err and it is "null unless the hashing algorithm throws an error." And finally, we check for model that is "the model getting authenticated if authentication was successful otherwise false."
So, model is authenticated. After that we must use the user with req.login(u,(err)). Check for errors and if everything is alright, we authenticate user locally passport.authenticate("local");. If you want to save session, write:
req.session.save((error) => {
if (err) {
console.log(err);
} else {
res.redirect("/");
}
});
That's all.
For registration :
app.post("/register", (req, res) => {
const email = req.body.email;
const password = req.body.password
User.find({ email: email }, function (err, docs) {
if (docs.length === 0) {
User.register(
{
username: email,
},
password,
function (err, user) {
if (err) {
console.log(err);
} else {
req.login(user, (err) => {
if (err) {
console.log(err);
} else {
passport.authenticate("local");
req.session.save((error) => {
if (err) {
console.log(err);
} else {
res.redirect("/");
}
});
}
});
}
}
);
} else {
res.send("The accout already exists!");
}
});
});
Related
a user login successfully and redirected to profile was implemented with success.but, when i try to access a new route by requesting http://localhost:5000/user/admin/request/newAdmin route the authentication middleware responses with You are not authorized to view this page after login why is that???
server.js
require("dotenv").config();
const express = require("express");
const app = express();
// const flash = require("connect-flash");
const session = require("express-session");
const passport = require("passport");
const mongoose = require("mongoose");
const MongoStore = require("connect-mongo");
const cors = require("cors");
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cors());
// app.use(flash());
app.use(
session({
secret: process.env.SESSION_SECRET,
resave: true,
saveUninitialized: true,
store: MongoStore.create({
mongoUrl: process.env.DB,
collection: "sessions",
}),
cookie: { secure: false, maxAge: 1000 * 60 * 60 * 24 * 3 },
})
);
app.use(passport.initialize());
app.use(passport.session());
mongoose
.connect(process.env.DB)
.then(() => {
console.log("DB connection successful");
})
.catch((err) => {
console.log(`DB connection Error: ${err}`);
});
const userRouter = require("./routes/userRoutes");
app.use("/user", userRouter);
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
console.log(`server is running on port ${PORT}`);
});
module.exports = app;
userRoutes.js
const router = require("express").Router();
const passport = require("passport");
const { ObjectID } = require("mongodb");
const LocalStrategy = require("passport-local");
const bcrypt = require("bcrypt");
const crypto = require("crypto");
const Token = require("../models/token");
const sendEmail = require("../utils/sendEmail");
const User = require("../models/userModel.js");
router.route("/register").post(
(req, res, next) => {
User.findOne({ fullName: req.body.fullName }, (err, user) => {
if (err) {
next(err);
} else if (user) {
res.json({ user: "user with that name already exists!" });
} else {
const {
fullName,
email,
userType,
department,
stream,
id,
batch,
phoneNumber,
password,
} = req.body;
const hash = bcrypt.hashSync(password, 12);
console.log(hash);
if(userType === "Admin"){
User.find({ userType: "Admin" }, (err, users) => {
if (err) console.log(err);
if(users.length === 0 ){
const newUser = new User({
fullName,
email,
userType,
department,
stream,
id,
batch,
phoneNumber,
password: hash,
});
newUser.save((err, data) => {
if (err) console.log(err);
next(null, data);
});
}else{
const newUser = new User({
fullName,
email,
userType,
department,
stream,
id,
batch,
phoneNumber,
password: hash,
approved: false
});
newUser.save((err, data) => {
if (err) console.log(err);
next(null, data);
})
}
})
}else{
const newUser = new User({
fullName,
email,
userType,
department,
stream,
id,
batch,
phoneNumber,
password: hash,
});
newUser.save((err, data) => {
if (err) console.log(err);
next(null, data);
});
}
}
});
},
passport.authenticate("local", { failureRedirect: "/" }),
(req, res, next) => {
const userAuth = req.user.fullName;
if (userAuth) {
User.findOne({ fullName: userAuth }, (err, user) => {
if (err) console.log(err);
const userPriv = user.userType;
if(userPriv === "Student"){
return res.json({ user: user.fullName ,identity: {id: "Student"}});
}
else if(userPriv === "Admin"){
if(user.approved){
return res.json({ user: user.fullName , identity: {id: "Admin",approved: true} });
}
return res.json({ user: user.fullName , identity: {id: "Admin",approved: false} });
}else{
return res.json({ user: user.fullName , identity: {id: "Teacher"} });
}
});
} else {
res.sendStatus(401).json({ user: "Incorrect password or email" });
}
}
);
router.route("/login").post(passport.authenticate("local"), (req, res) => {
const userAuth = req.user.fullName;
console.log(req.user);
if (userAuth) {
User.findOne({ fullName: userAuth }, (err, user) => {
if (err) console.log(err);
const userPriv = user.userType;
if(userPriv === "Student"){
return res.json({ user: user.fullName ,identity: {id: "Student"}});
}
else if(userPriv === "Admin"){
if(user.approved){
return res.json({ user: user.fullName , identity: {id: "Admin",approved: true} });
}
return res.json({ user: user.fullName , identity: {id: "Admin",approved: false} });
}else{
return res.json({ user: user.fullName , identity: {id: "Teacher"} });
}
});
} else {
res.sendStatus(401).json({ user: "Incorrect password or email" });
}
});
router.route("/admin/request/newAdmin").get(ensureAuthenticated,(req, res) => {
User.find({userType: "Admin", approved: false},(err,users) => {
if (err) console.log(err);
res.json({users});
})
});
router.route("/logout").get((req, res, next) => {
req.logout(function (err) {
if (err) {
return next(err);
}
console.log("the user has logged out!");
res.json({ user: "logout success!" });
});
});
passport.serializeUser((user, done) => {
done(null, user._id);
});
passport.deserializeUser((id, done) => {
User.findOne({ _id: new ObjectID(id) }, (err, doc) => {
done(null, doc);
});
});
const customFields = {
usernameField: "email",
};
passport.use(
new LocalStrategy(customFields, (email, password, done) => {
User.findOne({ email }, (err, user) => {
console.log(`User ${user.email} attempted to log in.`);
if (err) return done(err);
if (!user) return done(null, false);
if (!bcrypt.compareSync(password, user.password)) {
return done(null, false);
}
return done(null, user);
});
})
);
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next();
}
console.log(req.isAuthenticated());
console.log(req.user);
res.redirect("/user/err");
}
router.route("/err").get((req,res) => {
res.status(401).json({ msg: "You are not authorized to view this page" });
})
module.exports = router;
i was expecting for the ensureAuthenticated middleware to respond with authenticated because the user is logged in.but one thing i noticed is when i console logged req.user in the login route it set it to the current user object but in the ensureAuthenticated middleware it is undefined even if the user has not logged out.why is that?may be am i wrong when initializing the session and passport in server.js?
I am a beginner in Reactjs and nodejs trying to make my first full stack app. In my postjob schema I want the username of the current logged in user in the publisher field. Passport has a req.user command to get details of the current user but whenever I try to use this it gives the type error.If you guys need any other file let me know
postjob schema
const mongoose=require('mongoose')
const postjobtemplate= new mongoose.Schema({
jobtitle:{
type:String,
required:true
},
company:{
type:String,
required:true
},
officelocation:{
type:String,
required:true
},
jobtype:{
type:String,
required:true
},
publisher:{ ///<=HERE
type:String,
required:true
},
date:{
type:Date,
default:Date.now
}
})
module.exports=mongoose.model("postjobtable",postjobtemplate)
routes js
router.post('/postjob',async(request,response,next)=>{
const postjob=new postjobtemplatecopy({
jobtitle:request.body.jobtitle,
company:request.body.company,
officelocation:request.body.officelocation,
jobtype:request.body.jobtype,
publisher:request.user.username, //////<=HERE
})
postjob.save()
.then(data=>{
response.json(data)
})
.catch(error=>{
response.json(error)
})
});
router.post("/login", (req, res, next) => {
passport.authenticate("local", (err, user, info) => {
if (err) throw err;
if (!user) res.send("No User Exists");
else {
req.logIn(user, (err) => {
if (err) throw err;
res.status(200).send("Successfully Authenticated");
});
}
})(req, res, next);
});
server js
const express =require('express')
const app=express()
const mongoose=require('mongoose')
const dotenv=require('dotenv')
const routes=require('./routes/routes')
const cors=require('cors')
const passport=require("passport")
const passportlocal = require("passport-local").Strategy;
const bodyParser=require("body-parser")
const session=require("express-session")
const cookieparser=require('cookie-parser')
dotenv.config();
mongoose.connect(process.env.DB_CONNECT,{useNewUrlParser:true},()=>
console.log("database connected")
);
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:true}));
app.use(express.urlencoded({ extended: true }));
app.use(cors({
origin:'http://localhost:3000',
credentials:true
}))
app.use(session({
secret:'secret',
resave:true,
saveUninitialized:true
}))
app.use(cookieparser("secret"))
app.use(passport.initialize());
app.use(passport.session());
require('./passport-config')(passport);
app.use(express.json())
app.use('/api',routes)
app.listen(4002,()=>console.log("server running on port 4002"))
module.exports = app;
passport config
const User = require("./models/user");
const bcrypt = require("bcryptjs");
const localStrategy = require("passport-local").Strategy;
module.exports = function (passport) {
passport.use(
new localStrategy((username, password, done) => {
User.findOne({ username: username }, (err, user) => {
if (err) throw err;
if (!user) return done(null, false);
bcrypt.compare(password, user.password, (err, result) => {
if (err) throw err;
if (result === true) {
return done(null, user);
} else {
return done(null, false);
}
});
});
})
);
passport.serializeUser((user, cb) => {
cb(null, user.id);
});
passport.deserializeUser((id, cb) => {
User.findOne({ _id: id }, (err, user) => {
const userInformation = {
username: user.username,
};
cb(err, userInformation);
});
});
};
You are getting typeError because username is not being sent/received properly. Change this line in your post route: publisher: request.user.username, for this: publisher: request.body.username,(I assume you are sending it from the front-end as username, if not, it would be useful to include your request from React in your code) that way you are actually receiving the data you're sending from the front end. Also, if you are using a different field other than username, you need to specify it in your passport strategy like this:
passport.use(
"yourStrategyName", //here you are naming the strategy to be used in your route
new localStrategy( {
usernameField: "publisher", //here you are telling passport to use "publisher" as a username
},(publisher, password, done) => {
User.findOne({ publisher }, (err, user) => { //changed to the field name in database
if (err) throw err;
if (!user) return done(null, false);
bcrypt.compare(password, user.password, (err, result) => {
if (err) throw err;
if (result === true) {
return done(null, user);
} else {
return done(null, false);
}
});
});
})
);
And in your route.js:
router.post("/login", (req, res, next) => {
passport.authenticate("yourStrategyName", (err, user, info) => { //include the strategy name as the first parameter
if (err) throw err;
if (!user) res.send("No User Exists");
else {
req.logIn(user, (err) => {
if (err) throw err;
res.status(200).send("Successfully Authenticated");
});
}
})(req, res, next);
});
I am new to Node.js.
For my application, I have two different type of users being doctors and patient. Currently, I been coding for the login and registration for patients and it works. I starting to code the login for the doctors and it doesn't seem to be working. Below is the passport.js. I watched a video (https://www.youtube.com/watch?v=6FOq4cUdH8k&ab_channel=TraversyMedia) to learn how to code the login and registration.
I think the issue is within the passport.js, I'm not really sure how to code it, when it comes to the second user.
const LocalStrategy = require('passport-local').Strategy;
const bcrypt = require('bcryptjs');
const Patient = require('../models/patients');
module.exports = function(passport) {
passport.use(
new LocalStrategy({ usernameField: 'email' }, (email, password, done) => {
Patient.findOne({
email: email
}).then(patient => {
if (!patient) {
return done(null, false, { message: 'That email is not registered' });
}
bcrypt.compare(password, patient.password, (err, isMatch) => {
if (err) throw err;
if (isMatch) {
return done(null, patient);
} else {
return done(null, false, { message: 'Password is incorrect' });
}
});
});
})
);
passport.serializeUser(function(patient, done) {
done(null, patient.id);
});
passport.deserializeUser(function(id, done) {
Patient.findById(id, function(err, patient) {
done(err, patient);
});
});
const Doctor = require('../models/doctors');
module.exports = function(passport) {
passport.use(
new LocalStrategy({ usernameField: 'email' }, (demail, dpassword, done) => {
Doctor.findOne({
demail: demail
}).then(doctor => {
if (!doctor) {
return done(null, false, { message: 'That email is not registered' });
}
bcrypt.compare(dpassword, doctor.dpassword, (err, isMatch) => {
if (err) throw err;
if (isMatch) {
return done(null, doctor);
} else {
return done(null, false, { message: 'Password is incorrect' });
}
});
});
})
);
passport.serializeUser(function(doctor, done) {
done(null, doctor.id);
});
passport.deserializeUser(function(id, done) {
Doctor.findById(id, function(err, doctor) {
done(err, doctor);
});
});
}}:
This is my doctor.js in route
const express = require('express');
const router = express.Router();
const bcrypt = require('bcryptjs');
const passport = require('passport');
const Doctor = require('../models/doctors');
router.get('/doctorregister', (req, res) => res.render('Doctorregister'));
router.get('/doctorlogin', (req, res) => res.render('Doctorlogin'));
module.exports = router;
router.post('/doctorregister', (req, res) => {
const { dname, dqualification, dlocation, dpractice, demail, dmobileno, dpassword, dpassword2 } = req.body;
let errors = [];
if (!dname|| !dqualification || !dlocation || !dpractice || !demail || !dmobileno || !dpassword || !dpassword2) {
errors.push({ msg: 'Please enter all fields' });
}
if (dpassword != dpassword2) {
errors.push({ msg: 'Passwords do not match' });
}
if (dpassword.length < 6) {
errors.push({ msg: 'Password must be at least 6 characters' });
}
if (errors.length > 0) {
res.render('doctorregister', {
errors,
dname,
dqualification,
dlocation,
dpractice,
demail,
dmobileno,
dpassword,
dpassword2
});
} else {
Doctor.findOne({ demail: demail }).then(doctor => {
if (doctor) {
errors.push({ msg: 'Email already exists' });
res.render('register', {
errors,
dname,
dqualification,
dlocation,
dpractice,
demail,
dmobileno,
dpassword,
dpassword2
});
} else {
const newDoctor = new Doctor({
dname,
dqualification,
dlocation,
dpractice,
demail,
dmobileno,
dpassword,
});
//hashing password in the database
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(newDoctor.dpassword, salt, (err, hash) => {
if (err) throw err;
newDoctor.dpassword = hash;
newDoctor.save()
.then(doctor => {
req.flash('success_msg', 'You are now registered and can log in')
res.redirect('/doctors/doctorlogin');
})
.catch(err => console.log(err));
});
});
}
});
}
});
router.post('/doctorlogin', (req,res, next) => {
passport.authenticate('local', {
successRedirect: '/doctordashboard',
failureRedirect: '/doctors/doctorlogin',
failureFlash: true
})(req, res, next);
});
router.get('/logout', (req, res) => {
req.logout();
req.flash('You are logged out');
res.redirect('/doctors/doctorlogin');
});
The two different type of users should be different through the user Schema if you are using mongoose and mongoDB as Travesty-Media uses in some of his videos, and through the permissions in different sections of your web app.
Use the same passport code that you have used for the patient user and it works. Passport takes the user info and turns it into a Bearer auth token and sends it to the client, and then when it receives it from the client it decodes it to see what kind of user is logging in...
Different users have different info but same Passport logic, even if there are 2 different patient-users. So the logic from patient to doctor regarding the Passport is the same.
If you want the patient to have access to different routes of your app, you need to insert a middleware to that route to check if the type of user is the same with what you want it to be, but after passport has got the info from the token it has received from the client side.
Within my project I have both hcpuser and regular user. I have got the registration working for HCP but when i go to do my login function it still only reads from my users collection and not from the hcpuser I want it to. Is there a simple line of code I can declare before my function that allows this.
Hcp model:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var bcrypt = require('bcryptjs');
var User = require('../model/user.model').schema
var schema = new Schema({
email : {type:String, require:true},
username: {type:String, require:true},
password:{type:String, require:true},
creation_dt:{type:Date, require:true},
hcp : {type:Boolean, require : true},
clinic:{type:String, require:true},
patients: [User],
});
schema.statics.hashPassword = function hashPassword(password){
return bcrypt.hashSync(password,10);
}
schema.methods.isValid = function(hashedpassword){
return bcrypt.compareSync(hashedpassword, this.password);
}
schema.set('collection', 'hcpuser');
module.exports = mongoose.model('Hcpuser',schema);
Hcp controller with first register function working as expected.
const express = require("express");
const mongoose = require("mongoose");
const cors = require("cors");
const router = express.Router();
const Hcpusermodel = mongoose.model("Hcpuser")
const {ObjectId} = require("mongodb");
var Hcpuser = require('../model/hcp.model')
var passport = require('passport');
router.post('/register', function (req, res, next) {
addToDB(req, res);
});
async function addToDB(req, res) {
var hcpuser = new Hcpuser({
email: req.body.email,
hcp : true,
username: req.body.username,
password: Hcpuser.hashPassword(req.body.password),
clinic: req.body.clinic,
creation_dt: Date.now()
});
try {
doc = await hcpuser.save();
return res.status(201).json(doc);
}
catch (err) {
return res.status(501).json(err);
}
}
//login
router.post('/login', function(req,res,next){
passport.authenticate('local', function(err, hcpuser, info) {
if (err) { return res.status(501).json(err); }
if (!hcpuser) { return res.status(501).json(info); }
req.logIn(hcpuser, function(err) {
if (err) { return res.status(501).json(err); }
return res.status(200).json({message:'Login Success'});
});
})(req, res, next);
});
From your question, you either want to auth one OR the other, or check both - I think you're asking for how to auth separately (one OR the other, not both)?
please note, this specific code has been untested, but the principles are there and still stand.
One OR the Other
You need to define the name of each strategy in your passport code.
For example:
passport.use('users', new LocalStrategy({
usernameField: 'user[email]',
passwordField: 'user[password]',
},(email, password, done) => {
Users.findOne({ email })
.then((user) => {
if(!user || !user.validatePassword(password)) {
return done(null, false, { errors: { 'email or password' : 'is valid' } });
}
return done(null, user);
}).catch(done);
}));
passport.use('hcpusers', new LocalStrategy({
usernameField: 'user[email]',
passwordField: 'user[password]',
},(email, password, done) => {
HCPUser.findOne({ email })
.then((user) => {
if(!user || !user.validatePassword(password)) {
return done(null, false, { errors: { 'email or password' : 'is valid' } });
}
return done(null, user);
}).catch(done);
}));
And then in your passport.authenticate method, specify the strategy name:
passport.authenticate('users', function(err, user, info) { ...
and
passport.authenticate('hcpusers', function(err, user, info) { ...
In this case you'll need two separate endpoints for each login method, or just an extra parameter specifying which one to check from an if statement.
Update
For your comment of not knowing where the passport code should be, this is up to you. However, I like to keep passport code in an 'auth' folder and add the following code to a passport.js file:
const mongose = require('mongoose');
const passport = require('passport');
const LocalStrategy = require('passport-local');
const Users = mongose.model('Users');
passport.use('...', new LocalStrategy({
...
...
}));
Include this in your server/index/app.js (whatever yours is) app.use(passport.initialize());
You can then just use the passport code as normal in your user controllers.
My passport.authenticate code looks like:
return passport.authenticate('local', function(err, passUser, info) {
if (err) {
return next(err);
}
if (!passUser) {
return res.status(503).send('error');
}
const user = passUser;
user.token = user.generateJWT();
return res.json({ token: user.token });
})(req, res, next);
But this can be different for you (i.e. you may not be using sessions?) Either way, if authenticated, just send the response to client so it can proceed.
Hi so to solve this issue i followed what was mentioned. I needed to define the name of the collection within the hcp model using this:
module.exports = mongoose.model('Hcpuser', Hcpuser, 'Hcpuser');
I then created a local strategy ensuring that i was searching using the right model which would then point to the right collection within my DB.
Solution:
var passport = require('passport')
, LocalStrategy = require('passport-local').Strategy;
passport.use('hcplocal', new LocalStrategy(
function(uemail, password, done) {
Hcpuser.findOne({ "email" : uemail }, function(err, user) { console.log(user)
if (err) { return done(err); }
if (!user) {
console.log(user);
console.log(err);
console.log(uemail)
return done(null, false, { message: 'Incorrect email.' });
}
if (!user.isValid(password)) {
console.log(user);
return done(null, false, { message: 'Incorrect password.' });
}
return done(null, user);
});
}
));
router.post('/login',function(req,res,next){
passport.authenticate('hcplocal', function(err, user, info) {
if (err) { return res.status(501).json(err); }
if (!user) { return res.status(501).json(info); }
req.logIn(user, function(err) {
if (err) { return res.status(501).json(err); }
console.log(user);
return res.status(200).json({message:'Login Success'});
});
})(req, res, next);
});
I am new to NodeJS. I am made a basic CRUD app with authentication using express. Sign up was successful but login is not successful.I am using passport and bcryptjs for authentication.
Here is home route. As index is called automatically so this is not getting called. For other routes it works only if manually pass the function ensureAuthenticated to their parameters just like below. I want it to work for all endpoints without manually doing so.
app.get("/", ensureAuthenticated, function (req, res) {
res.render('index');
});
Below is the login functionality.
app.get("/login", function (req, res) {
const loginPath = path.join(__dirname, '/login.html');
res.sendFile(loginPath);
});
passport.use(new localStrategy({
usernameField: 'adminUsername',
passwordField: 'password',
session: false
},
function (adminUsername, password, done) {
Admin.getAdminByAdminUsername(adminUsername, function (err, admin) {
if (err) throw err;
console.log('getAdmin called');
if (!admin) {
console.log('Admin Not Found');
return done(null, false);
}
Admin.comparePassword(password, admin.password, function (err, isMatch) {
console.log('comparePassword called');
if (err) throw err;
if (isMatch) {
return done(null, admin);
} else {
console.log('Wrong Password!');
return done(null, false);
}
});
});
}));
passport.serializeUser(function (admin, done) {
done(null, admin.id);
});
passport.deserializeUser(function (id, done) {
Admin.getAdminById(id, function (err, admin) {
done(err, admin);
console.log('findById called');
});
});
app.post('/login', passport.authenticate('local', {
failureRedirect: '/login'}), function(req, res){
console.log('login called');
res.redirect('/');
});
app.get('/logout', function(req,res){
req.logout();
res.redirect('/login');
});
function ensureAuthenticated(req, res, next){
if (req.isAuthenticated()) {
return next();
} else {
res.redirect('/login');
}
}
The problem is even without authentication, I still have access via URL endpoints.
Here is the Admin schema file.
const mongoose = require("mongoose");
const bcrypt = require('bcryptjs');
const schema = new mongoose.Schema({
adminEmail: {
type: String,
unique: true,
required: true
},
adminUsername:{
type: String,
unique: true,
required: true
},
password:{
type: String,
required: true
}
});
const Admin = mongoose.model('Admin', schema);
module.exports = Admin;
module.exports.getAdminByAdminUsername = function (adminUsername, callback) {
const query = {adminUsername: adminUsername};
Admin.findOne(query, callback);
}
module.exports.getAdminById = function (adminId, callback) {
Admin.findById(adminId, callback);
}
module.exports.comparePassword = function (password, hash, callback) {
bcrypt.compare(password, hash, function (err, isMatch) {
if (err) throw err;
callback(null, isMatch);
});
}