Unable to store and manage session in express - node.js

I am new to express and using express-session to manage login(s) in my application.
I have followed a blog and declared my session as below:-
app.use(session({
secret:'Keep It Secret',
name : 'uniqueSessionID',
resave : true,
saveUninitialized : true,
cookie : { secure : false, maxAge : 3600000, loggedIn : false, username : "" }
}));
The problem is that on a successful login I'm updating the session and printing it, which outputs to:-
Session {
cookie: {
path: '/',
_expires: 2021-12-27T13:16:17.355Z,
originalMaxAge: 3600000,
httpOnly: true,
secure: false,
loggedIn: true,
username: 'pushkar#gmail.com'
}
}
But after that when I authenticate the routes, the session remains unchanged just like below:-
Session {
cookie: {
path: '/',
_expires: 2021-12-27T13:16:17.355Z,
originalMaxAge: 3600000,
httpOnly: true,
secure: false
}
}
I have tried all and need help.
This is my login where I login and make the session:-
const login = (req, res, next) => {
console.log(req.body);
const email = req.body.email;
const password = req.body.password;
if(email == "" && password == ""){
req.flash("message","please fill in the required fields");
res.redirect("/admin/login");
}
else if(email == ""){
req.flash("message", "please fill in the email");
res.redirect("/admin/login");
}
else if(password == ""){
req.flash("message", "please fill in the password");
res.redirect("/admin/login");
}
else {
user.findOne({email : email}, function(err, data){
debugger;
if(err){
req.flash("message", "Username not found");
res.redirect("/admin/login");
}
else {
if(data.password == password){
req.session.cookie.loggedIn = true;
req.session.cookie.username = email;
req.session.save(function(err) {
if (err) console.log(err);
})
console.log(req.session);
}
else{
req.flash("message", "Invalid Password");
res.redirect("/admin/login");
}
res.redirect("/admin/dashboard");
}
})
}
};
and This is my authentication function:-
exports.authenticated = (req, res, next) => {
debugger;
console.log(req.session);
if(req.session.cookie.loggedIn) {
next();
}
else {
res.redirect("/admin/login");
}
}

It's incorrect to set the value, you want to save, to req.session.cookie it the place where you set up uniqueSessionID cookie options, not saved value.
See this tutorial for example
try
//to write
req.session.loggedIn = true;
req.session.username = email;
//to read
if(req.session.loggedIn) {
next();
}
if all works, maybe you will want to make the session permanent between restarts, so see next
Example with permanent storage

Related

I am trying to set cookie from backend but it is not showing and not getting console.log

I am trying to set cookie called JWT from backend but it is not able to set and I am not getting cookie in browser too where I am going wrong?
backend code for storing cookie
exports.login = async (req, res) => {
const findData = await Registeration.findOne({ email: req.body.email });
console.log(findData);
if (findData === null || findData === {}) {
res.status(404).json({message:"user not found",statusCode:res.statusCode});
} else {
if (findData.password === req.body.password) {
const token = await findData.generateAuthToken();
console.log(token);
res.cookie("jwt", token, {
path: "/",
expires: new Date(Date.now() + 1000 * 30 * 100),
httpOnly: true,
sameSite: "lax",
});
console.log("cookie : ",req.cookies.jwt)// getting undefined
if (findData.isSeller === true) {
res.status(200).json({message:"logged into as seller",statusCode:res.statusCode});
} else {
res.status(200).json({message:"welcome to customer page",statusCode:res.statusCode});
}
} else {
res.status(401).send("ircorrect password");
}
}
}

Using Passport.js and express-session, every route but the login route sends a cookie that does not include user information

I'm trying to build an app with Node.js and Passport.js, but I don't want to continue if I can't nail down authentication. Right now I have passport-local set up and once I log in, by all accounts I should be getting an authenticated user on other routes. But I'm not. It looks like the session cookie being sent when logged in has the user info, but every other route sends a cookie that lacks the user info. I can't for the life of me figure out what I'm doing wrong.
here is how app is set up:
app.use(
session({
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: true,
cookie: {
secure: false,
},
store: new FirestoreStore({
dataset: new Firestore(),
kind: "express-sessions",
}),
})
);
app.use(passport.initialize());
app.use(passport.session());
My route:
userRouter
.route("/api/v1/signup")
.post(jsonParser, async (req, res, next) => {
// console.log(req.body);
addUser(req.body);
res.status(200).json({ message: "success" });
});
userRouter.route("/api/v1/login").post(
jsonParser,
passport.authenticate("local", {
session: true,
}),
async (req, res, next) => {
res.status(200).json({ message: "success" });
}
);
and my passport.js
const LocalStrategy =
require("passport-local").Strategy;
const argon2 = require("argon2");
const {
getUserByEmail,
getUserById,
} = require("../database/users");
const initialize = (passport) => {
const authenticateUser = async (
email,
password,
done
) => {
const user = await getUserByEmail(email);
if (user === null) {
return done(null, false, {
message: "No user with that email",
});
}
// argon2.verify(user.email, password);
try {
const verifiedPassword =
await argon2.verify(
user.password,
password
);
if (verifiedPassword) {
// password match
console.log("success");
return done(null, user);
} else {
// password did not match
console.log("failure");
return done(null, false, {
message: "Password incorrect",
});
}
} catch (error) {
// internal failure
console.log(error, "error");
return done(error);
}
};
passport.use(
new LocalStrategy(
{
usernameField: "email",
},
authenticateUser
)
);
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
return done(null, getUserById(id));
});
};
module.exports = initialize;
When I login, my session gets this cookie:
Session {
cookie: {
path: '/',
_expires: null,
originalMaxAge: null,
httpOnly: true,
secure: false
},
passport: { user: 1657255017610 }
}
On every other route when I want to check if the user is authenticated or not, I get this:
Session {
cookie: {
path: '/',
_expires: null,
originalMaxAge: null,
httpOnly: true,
secure: false
}
}

Passport isAuthenticated() always returns false?

So I am having a problem with Passport I've been trying to move from my original method of authentication because Passport supports other types like Google and GitHub. I'm trying to implement the local authentication and it doesn't seem to be working, even after looking up many articles and they all don't work.
This is at the top of the code:
const cookieExpirationDate = new Date();
cookieExpirationDate.setDate(cookieExpirationDate.getDate() + 7);
app.use(session({
secret: secret_key,
store: sessionStore,
resave: true,
saveUninitialized: true,
cookie: {
httpOnly: true,
sameSite: 'strict',
expires: cookieExpirationDate
}
}));
// PASSPORT //
app.use(passport.initialize());
app.use(passport.session());
passport.use('local', new LocalStrategy({
usernameField: 'username',
passwordField: 'password',
passReqToCallback: true //passback entire req to call back
}, async function (req, username, password, done) {
if (!username || !password) {
return done(null, false, {message: 'Please complete the form!'})
}
const reqBody = {
response: req.body['h-captcha-response'],
secret: captcha_key
}
let axiosResult = await axios.post('https://hcaptcha.com/siteverify', qs.stringify(reqBody), {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
if (axiosResult.data.success === true) {
let results = await runQuery('SELECT * FROM accounts WHERE (username = ? OR email = ?)', [username, username])
const forwarded = req.headers['x-forwarded-for']
const ip = forwarded ? forwarded.split(/, /)[0] : req.connection.remoteAddress
if (!results.length) {
let amtLeft = await loginAttempts(ip);
if (amtLeft > 1) {
return done(null, false, {message: `Incorrect Username and/or Password! (${amtLeft} attempt(s) left)`});
} else {
return done(null, false, {message: `You must wait 15 minutes before trying again!`});
}
}
let user = results[0]
let isMatch = await bcrypt.compareSync(password, user.password)
if (!isMatch) {
let amtLeft = await loginAttempts(ip);
if (amtLeft > 1) {
return done(null, false, {message: `Incorrect Username and/or Password! (${amtLeft} attempt(s) left)`});
} else {
return done(null, false, {message: `You must wait 15 minutes before trying again!`});
}
} else {
if (user.activation_code === "activated") {
return done(null, user)
} else {
return done(null, false, {message: 'Check your email for an activation email!'})
}
}
} else {
return done(null, false, {message: `You must complete the captcha!`});
}
}
));
passport.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(async function (usrid, done) {
let results = await runQuery('SELECT * FROM accounts WHERE id = ?', usrid)
done(results[0]);
});
Login API part:
app.post('/login_sys', regularFunctions, function (req, res, next) {
passport.authenticate('local', {failWithError: true}, function (error, user, info) {
if (error) {
return res.status(500).json(error);
}
if (!user) {
return res.status(401).json(info);
}
return res.status(200).send('Success')
})(req, res, next);
})
regularFunctions:
let regularFunctions = [
bodyParser.urlencoded({extended: true}),
bodyParser.json(),
function (req, res, next) {
console.log('Authenticated: ' + req.isAuthenticated())
if (req.isAuthenticated()) {
req.session.loggedin = true;
return next();
} else {
req.session.loggedin = false;
return next();
}
}
]
I need it to return some sort of notification to the client if it fails or succeeds because I have a little pop up that lets them know they are getting redirected if it works and to notify them of their attempts left. The problem is it works and says that it logged in but when I refresh the page it never did.
Ok just found out the answer after searching for a while, I had to use req.login inside the login_sys route.

session expires not in the expected time in node.js

I'm pretty new to Node.js and Express-session. I have created a login/registration system, whenever the user logs in redirected to a page called scoreboard.
Problem: Session expires very soon, not the value that I have set it. I don't know how to fix it?
server.js
var session = require('express-session');
app.use(session({
secret: "ILoveMostafa",
resave: false,
saveUninitialized: false,
cookie: {
expires: new Date(Date.now() + 43200)
}
}))
user.js
router.post('/login', (req, res) => {
var email = req.body.email;
var password = req.body.password;
userModel.authenticate(email, password, (err, user) => {
if (err) {
console.log(err)
}
else if (!user) {
console.log('Wrong Password')
}
else {
req.session.userId = user._id;
res.redirect('/user/scoreboard')
}
})
});
router.get('/scoreboard',async (req, res) => {
console.log(req.session.userId)
if (req.session.userId) {
const teams = await userModel.find({}).sort('-score')
const faculties = await userModel.aggregate([{
"$group": {
_id: "$faculty",
average: {
$avg: "$score"
}
}
}]).sort("-average")
res.render('main/scoreboard', {
teamInformation: teams,
finalResult: faculties
})
}
else {
res.redirect('/')
}
});
After about 2 minutes when I refresh the page, I redirected to login page!
Date time is measured in milliseconds.
expires: new Date(Date.now() + 43200) is setting the expire time to be 43.2 seconds later than the present time.

trying to check if another session with same session.username exists

I am currently practicing nodeJS and I would like to achieve something like this :
I am trying to check if another session with the same session.username exists. and if it does, display a warning. I am doing it this way :
app.post('/login', (req, res) => {
let options = {"username": req.body.username, "error": null};
if(!req.body.username) {
options.error = "username required nobi";
res.render('login', options);
} else if (req.body.username == req.session.username) {
res.redirect('/');
} else {
req.sessionStore.all( (err, sessions) => {
if(!err) {
let isUsed = false;
let i=0;
for(i; i < sessions.length; i++) {
let session = JSON.parse(sessions[i]);
if (session.username == req.body.username) {
err = "name already taken";
isUsed = true;
break;
}
}
}
if (err) {
options.error = err;
res.render('login', options);
} else {
req.session.username = req.body.username;
res.redirect("/");
}
});
}
});
It is not working : I am connecting on chrome and IE with the same username. I do not want that to be possible
as an illustration (if needed) :
{ If9a9SgOoq7roW8Za84CouSEzgqDs1Q3:
{ cookie: { originalMaxAge: null, expires: null, httpOnly: true, path: '/' },
username: 'pseudo' },
MBs41iJmoQpLLCDhP8aFAk5PWAZ_ZQSV:
{ cookie: { originalMaxAge: null, expires: null, httpOnly: true, path: '/' },
username: 'pseudo' } }
app.post('/login', (req, res) => {
// You can store username in res.locals.username after auth
// It's not necessary to pass it into render.
let username = req.body.username;
if(!username)
return res.render('login', {error: 'username required nobi'});
if (username == req.session.username)
return res.redirect('/');
if (username && username != req.session.username)
return ... // maybe destroy current session?
req.sessionStore.all( (err, sessions) => {
if (err)
return res.render('login', {error: err.message});
let isUsed = Object.keys(sessions).some((id) => sessions[id].username == username);
if (isUsed)
return res.render('login', {error: 'Already used'});
req.session.username = username;
res.locals.username = username;
res.redirect('/');
});
});

Resources