ERROR: req.logIn is not a function Passport Js MERN STACK - node.js

I am trying use passport-local to authenticate user for a MERN Stack project. Currently I am unable to LOG IN or LOG OUT and I keep getting errors like this:
TypeError: req.logIn is not a function & req.logOut is not a function
I am not sure why is this happening. I have been following the Passport Js documentation. What should I do to fix this?
Thank you
const express = require("express");
const app = express();
const cors = require("cors");
const mongoose = require("mongoose");
const passport = require("passport");
const passportLocal = require("passport-local").Strategy;
const initialize = require("./passport-config");
const session = require("express-session");
const bcrypt = require("bcrypt");
const User = require("./modules/User");
const port = XXXXX;
mongoose.connect(
"XXXXXXXXXX",
{ useNewUrlParser: true },
() => console.log("Mongoose Connected"),
);
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(cors());
app.use(
session({
secret: "secret",
resave: false,
saveUninitialized: false,
}),
);
passport.use(passport.initialize());
passport.use(passport.session());
initialize(passport);
app.get("/users", (req, res) => {
res.send("Hello");
});
app.post("/users/create", (req, res) => {
User.findOne(
{ username: req.body.username },
async (err, doc) => {
if (err) throw err;
if (doc) {
res.json({
auth: false,
message: "User Already Exist",
});
} else {
const hashedPassword = await bcrypt.hash(
req.body.password,
10,
);
const newUser = User({
username: req.body.username,
password: hashedPassword,
});
await newUser.save();
res.json({
auth: true,
message: "User Created",
});
console.log("User Created");
}
},
);
});
app.get("/users/logout", (req, res) => {
req.logOut();
res.send(true);
console.log("Logged Out");
});
app.post("/users/login", (req, res, next) => {
passport.authenticate("local", (err, user, info) => {
if (err) {
return next(err);
}
if (!user) {
res.json({
auth: true,
message: "Cannot Log In",
});
}
req.logIn(user, (err) => {
if (err) {
return next(err);
}
res.json({
auth: true,
message: "User Logged In",
});
console.log("Successfully Logged In");
});
})(res, req, next);
});
app.listen(port, () =>
console.log(`Server started on port: ${port}`),
);

The problem is here
passport.use(passport.initialize());
passport.use(passport.session());
initialize(passport);
it is not passport.use it should be app.use and
the initialize passport should be called first.
initialize(passport);
app.use(passport.initialize());
app.use(passport.session());

Related

How to use connect-flash with passport-local

hello every one i was trying to use connect-flash with passport local but can not seem to find relevant info either on the docs and other sources,if any one can guide me on this and tell me what i went wrong ,thanks.And why does request to login-fail gives this error:-
ERROR is AxiosError: Request failed with status code 404
but when i test the route with rest client on vscode it responses perfectly like seen
here.
also when i check the database right after i click submit on the route
there will be two sessions stored consecutively one having the flash(the first) and the other not like this:-
session:
{"cookie":{"originalMaxAge":259200000,"expires":"2023-01-16T12:30:14.395Z","secure":false,"httpOnly":true,"path":"/"},"flash":{"error":["Incorrect password"]}}
session:
{"cookie":{"originalMaxAge":259200000,"expires":"2023-01-16T12:30:14.453Z","secure":false,"httpOnly":true,"path":"/"}}
why this is happening?
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 flash = require("connect-flash");
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.redirect("/");
} else {
const {
fullName,
email,
id,
department,
stream,
batch,
sex,
age,
phoneNumber,
password,
} = req.body;
const hash = bcrypt.hashSync(password, 12);
console.log(hash);
const newUser = new User({
fullName,
email,
id,
department,
stream,
batch,
sex,
age,
phoneNumber,
password: hash,
});
newUser.save((err, data) => {
if (err) res.redirect("/");
next(null, data);
});
}
});
},
passport.authenticate("local", { failureRedirect: "/" }),
(req, res, next) => {
res.json({ user: "i am josh" });
}
);
router
.route("/login")
.post(
passport.authenticate("local", {
failureRedirect: "/login-fail",
failureFlash: true,
}),
(req, res) => {
res.json({ user: "i am josh" });
}
);
router.route("/login-fail").get((req, res) => {
// console.log(req.flash('error'));
res.json({ user: "josh" });
});
router.route("/logout").get((req, res) => {
req.logout();
res.redirect("/");
});
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.username} attempted to log in.`);
if (err) return done(err);
if (!user) return done(null, false, { message: "email does not exist" });
if (!bcrypt.compareSync(password, user.password)) {
return done(null, false, { message: "Incorrect password" });
}
return done(null, user);
});
})
);
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next();
}
res.json({ msg: "You are not authorized to view this page" });
}
module.exports = router;
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: false,
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 usersRouter = require("./routes/userRoutes");
app.use("/user", usersRouter);
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
console.log(`server is running on port ${PORT}`);
});
module.exports = app;
ya,have seen the same question here on stack over flow but none of the answers work

req.isAuthenticated() always return false and req.session.passport is undefined

I know that there are some questions like this already, but i already tried every single response and nothing works, i don't know what the heck to add to app.js to make it work and store the sessions.
Here is my app.js:
const express = require("express");
const cors = require("cors");
const usersRouter = require("./routes/users");
const passport = require("passport");
const cookieParser = require("cookie-parser");
const session = require("express-session");
require("dotenv").config();
const app = express();
const connectDB = require("./db/connect");
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cookieParser(process.env.SESSION_SECRET));
app.use(
session({
secret: process.env.SESSION_SECRET,
resave: true,
saveUninitialized: true,
cookie: { secure: false },
})
);
app.use(passport.initialize());
app.use(passport.session());
app.use(cors());
app.use("/api/v1/users", usersRouter);
const PORT = process.env.PORT || 5000;
const start = async () => {
try {
await connectDB(process.env.MONGO_URI);
app.listen(PORT, console.log(`Server is listening on port: ${PORT}....`));
} catch (error) {
console.log(error);
}
};
const notFound = require("./middleware/notFound");
app.use(notFound);
start();
My passport-config looks like this:
const localStrategy = require("passport-local").Strategy;
const bcrypt = require("bcryptjs");
const User = require("../models/user");
const initialize = (passport) => {
const authenticateUser = async (email, password, done) => {
let user = await User.findOne({ email: email });
User.findOne({ email: email });
if (!user) {
return done(null, false, {
message: "That email is not registered",
});
}
try {
if (await bcrypt.compare(password, user.password)) {
return done(null, user, { message: "User logged in" });
} else {
return done(null, false, { message: "Password incorrect" });
}
} catch (e) {
return done(e);
}
};
passport.use(new localStrategy({ usernameField: "email" }, authenticateUser));
passport.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(function (user, done) {
User.findById(id, function (err, user) {
done(err, user);
});
});
};
module.exports = initialize;
And my users router looks like this:
const express = require("express");
const router = express.Router();
const passport = require("passport");
const initializePassport = require("../config/passport-config");
initializePassport(passport);
const { postRegister } = require("../controllers/register");
router.route("/register").post(postRegister);
router.post("/login", function (req, res, next) {
passport.authenticate("local", function (err, user, info) {
if (err) {
return next(err);
}
if (!user) {
return res.status(401).json({ message: info.message });
}
console.log(req.session.passport);
res.status(200).json(user);
})(req, res, next);
});
module.exports = router;
I'm making a middleware to authorize or to not authorize the call to another endpoint based on if it is authenticated or if it isn't.
Here is how that middleware looks:
const checkAuthenticated = (req, res, next) => {
const isAuthenticated = req.isAuthenticated();
console.log(req.session.passport);
if (isAuthenticated) {
next();
}
next();
};
module.exports = checkAuthenticated;
const checkNotAuthenticated = (req, res, next) => {
const isAuthenticated = req.isAuthenticated();
if (!isAuthenticated) {
res
.status(401)
.json({ msg: "Not allowed to this path without credentials" });
}
};
module.exports = checkNotAuthenticated;
req.session.passport is undefined, isAuthenticated() is always false, i don't know what to add.
Your bug in the deserializer function:
It will work by changing your deserializer callback argument from user to id as shown below.
passport.deserializeUser(function (id, done) {
User.findById(id, function (err, user) {
done(err, user);
});
That was a very obvious bug to me, to be sure you are not missing any other thing, check the lengthy answer I gave to this on another thread a few minutes ago here: https://github.com/jaredhanson/passport/issues/914#issuecomment-1241921637
Good luck.

Cannot set headers after they are sent to the client/ Server crashes with this when page refreshes

Made a Question a few days ago on here, thought I had it figured out, even accepted the answer, because it was right regardless. but now I have the Same issue, same error.
Heres the Error.
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:558:11)
at ServerResponse.header (/Users/apple/Documents/Web Dev/collab/Backend/node_modules/express/lib/response.js:771:10)
at ServerResponse.send (/Users/apple/Documents/Web Dev/collab/Backend/node_modules/express/lib/response.js:170:12)
at ServerResponse.json (/Users/apple/Documents/Web Dev/collab/Backend/node_modules/express/lib/response.js:267:15)
at /Users/apple/Documents/Web Dev/collab/Backend/routes/index.js:90:23
at processTicksAndRejections (internal/process/task_queues.js:93:5) {
code: 'ERR_HTTP_HEADERS_SENT'
}
Heres Index.js. Line 90 is at the very bottom,
# router.get("/", isAuth, (req, res)
const router = require("express").Router();
const passport = require("passport");
const bodyParser = require("body-parser");
const genPassword = require("../lib/passwordUtils").genPassword;
const connection = require("../config/database");
const mongoose = require("mongoose");
const User = mongoose.models.User;
const isAuth = require("./authMiddleware").isAuth;
// cors is needed with router.use else you have to put routes on the app.js
const cors = require("cors");
router.use(cors({ origin: "http://localhost:3001", credentials: true }));
// const isAdmin = require("./authMiddleware").isAdmin;
router.use(bodyParser.urlencoded({ extended: false }));
/**
* -------------- Post ROUTES ----------------
*
*/
router.post("/login", (req, res, next) => {
passport.authenticate("local", (err, user, info) => {
if (err) {
throw err;
} else if (!user) {
res.send("No User Exists");
} else {
req.logIn(user, (err) => {
if (err) throw err;
res.send(user);
return;
// console.log(req.user);
});
}
})(req, res, next);
});
router.post("/register", (req, res) => {
const saltHash = genPassword(req.body.repeatPassword);
const salt = saltHash.salt;
const hash = saltHash.hash;
const newUser = new User({
username: req.body.firstInput,
fName: "",
lName: "",
title: "",
hash: hash,
salt: salt,
});
newUser.save().then((user) => {});
res.sendStatus(200);
});
/**
* -------------- GET ROUTES ----------------
*
*/
router.post("/user", (req, res) => {
const fName = req.body.firstInput;
const lName = req.body.secondInput;
const title = req.body.repeatPassword;
const user = req.session.passport.user;
User.updateOne(
{ _id: user },
{ fName: fName, lName: lName, title: title },
function (err, result) {
if (err) {
res.sendStatus(401);
console.log(err);
} else {
res.sendStatus(200);
}
}
);
});
router.get("/", isAuth, (req, res) => {
const userMap = {};
User.find({}, function (err, users) {
users.forEach(function (user) {
userMap[user._id] = user;
});
return userMap;
})
.then((response) => {
res.status(200).json({ user: req.user, auth: true, response });
return;
})
.catch((err) => console.log(err));
});
module.exports = router;
Heres App.js
const express = require("express");
const app = express();
const mongoose = require("mongoose");
const session = require("express-session");
const passport = require("passport");
const crypto = require("crypto");
const routes = require("./routes");
const isAuth = require("./routes/authMiddleware").isAuth;
const connection = require("./config/database");
const cors = require("cors");
app.use(cors({ origin: "http://localhost:3001", credentials: true }));
const User = mongoose.models.User;
const bodyParser = require("body-parser");
const MongoStore = require("connect-mongo")(session);
require("dotenv").config();
app.use(express.json());
// app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.urlencoded({ extended: true }));
const sessionStore = new MongoStore({
mongooseConnection: mongoose.connection,
collection: "sessions",
});
app.use(
session({
secret: "zdfbdaf",
resave: true,
saveUninitialized: true,
store: sessionStore,
cookie: {
cookie: { secure: false },
maxAge: 1000 * 60 * 60 * 24,
},
})
);
require("./config/passport");
app.use(passport.initialize());
app.use(passport.session());
app.use("/", routes);
app.listen(3000);
heres authMiddleware.js
module.exports.isAuth = (req, res, next) => {
if (req.isAuthenticated()) {
next();
// res.status(200).json({ user: req.user, auth: true });
} else {
res.status(401).json({ auth: false });
}
};
// module.exports.isAdmin = (req, res, next) => {
// if (req.isAuthenticated() && req.user.admin) {
// next();
// } else {
// res.status(401).json({ msg: 'You are not authorized to view this resource because you are not an admin.' });
// }
// }
Heres passport.js
const passport = require("passport");
const LocalStrategy = require("passport-local").Strategy;
const connection = require("./database");
const mongoose = require("mongoose");
const User = mongoose.models.User;
const validPassword = require("../lib/passwordUtils").validPassword;
const cors = require("cors");
passport.use(cors({ origin: "http://localhost:3001" }));
const customFields = {
usernameField: "username",
passwordField: "password",
};
passport.use(
new LocalStrategy(customFields, (username, password, done) => {
User.findOne({ username: username })
.then((user) => {
if (!user) {
console.log("No user");
return done(null, false);
} else {
const isValid = validPassword(password, user.hash, user.salt);
if (isValid) {
console.log("Logged in");
return done(null, user);
} else {
console.log("Wrong Password");
return done(null, true);
}
}
})
.catch((err) => {
done(err);
});
})
);
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => {
done(err, user);
})
.then((user) => {
done(null, user);
})
.catch((err) => done(err));
});
It only crashes half the time, kind of? It works at first, until you refresh the page. I am at a loss. Had someone in the discord also not know the issue. I'm begging for some help here. I'm losing my mind.
its because you are calling done twice once after finding the user
and second after .then block in passport.deserializeUser function
this will work:
passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => {
done(err, user)
});
});

At the time I test logout The result of executing req.isAuthenticated() is always false.(node js passport login problem)

I am implementing login using passport. and I have a question about a tricky login problem
login router is this
router.post('/login', isNotLoggedIn ,(req, res, next) => {
passport.authenticate('local', (err, user, info) => {
if (err) {
console.error(err);
return next(err);
}
if (info) {
return res.status(401).send(info.reason);
}
return req.login(user, async (loginErr) => {
if (loginErr) {
console.error(loginErr);
return next(loginErr);
}
// console.log("user : ", user);
console.log("login check : ", req.isAuthenticated());
const fullUserWithoutPassword = await User.findOne({
where: { id: user.id },
attributes: {
exclude: ['password']
},
include: [{
model: Post,
attributes: ['id'],
}, {
model: User,
as: 'Followings',
attributes: ['id'],
}, {
model: User,
as: 'Followers',
attributes: ['id'],
}]
})
// console.log("fullUserWithoutPassword : ", fullUserWithoutPassword);
return res.status(200).json(fullUserWithoutPassword);
});
})(req, res, next);
});
and result of below code is true
console.log("login check : ", req.isAuthenticated());
Whenever I try to log out, if I check whether I am currently logged in and req.user is set, the result is as follows.
req.isAuthenticated() => false.
console.log("logout check :::::::::::::", req.user); => undefined
logout router
router.post('/logout', (req, res, next) => {
console.log("login check :::::::::::::", req.isAuthenticated());
console.log("logout check :::::::::::::", req.user);
req.logout();
req.session.destroy();
res.send('ok')
})
I am looking for the cause of this problem.
Maybe back/app.js is in the wrong order?
or pass port code is wrong?
Or is it something else?
Thanks for your review
back\app.js
const express = require('express');
const postRouter = require('./routes/post');
const userRouter = require('./routes/user');
const cors = require('cors');
const session = require('express-session');
const cookieParser = require('cookie-parser');
const passport = require('passport');
const passportConfig = require('./passport');
const dotenv = require('dotenv');
dotenv.config();
const app = express();
const db = require('./models');
db.sequelize.sync()
.then(() => {
console.log("db connection success !!");
})
.catch("error : ", console.error)
passportConfig();
app.use(cors({
origin: '*',
credentials: true,
}));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cookieParser(process.env.COOKIE_SECRET));
app.use(session({
resave: true,
saveUninitialized: false,
cookie: { maxAge: 24 * 60 * 60 * 1000 },
secret: process.env.COOKIE_SECRET,
}));
app.use(passport.initialize());
app.use(passport.session());
app.get('/', (req, res) => {
res.send("hello express");
});
app.use('/post', postRouter);
app.use('/user', userRouter);
app.listen(3065, () => {
console.log("Ecpress Server is Excuting");
});
passport/index.js
const { User } = require('../models');
const passport = require('passport');
const local = require('./local');
module.exports = () => {
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser(async (id, done) => {
try {
const user = await User.findOne({ where: { id }}); console.log("user : ", user);
done(null, user);
} catch (error) {
done(error);
}
});
local();
}
passport/local.js
const passport = require('passport');
const { Strategy: LocalStrategy } = require('passport-local');
const { User } = require('../models');
const bcrypt = require('bcrypt');
module.exports = () => {
passport.use(new LocalStrategy({
usernameField: 'email',
passwordField: 'password'
}, async (email, password, done) => {
try {
const user = await User.findOne({
where: { email }
});
if (!user) {
console.log("email is not exists");
return done(null, false, { reason: 'email is not exists' });
}
const result = await bcrypt.compare(password, user.password);
if (result) {
console.log("result :::::::::::::" , result);
return done(null, user);
}
return done(null, false, { reason: 'pass word is wrong' });
} catch (error) {
console.log(error);
console.error(error);
return done(error);
}
}));
}
Ciao, try to modify /logout post like that:
router.post('/logout', (req, res, next) => {
console.log("login check :::::::::::::", req.isUnauthenticated());
req.logout();
req.session.destroy();
res.send('ok')
})
req.isUnauthenticated() is equal to true so that means that after you logout the request is always unauthenticated.

Setting up passport for the first time. isAuthenticated() always returning false

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.

Resources