Sending passport-local and express middleware to express router - node.js

I have a simple app.js file with passport authentication, I have a app.get on my app.js that looks something like this
app.get('/test', isAuthenticated, (req, res) => {
res.json(req.user)
})
When I open this page ('/test'), I get the following data
{
"email": "jhondoe#example.com",
"id": "f8dbee1ba8e95ace16656a008c548b91",
"expiry": "06/10/2022"
}
Now, I'm trying to do the same thing, but in my express router ('/s/main'), this is how I've imported my router
const settings = require('./routes/settings')
app.use("/s", settings)
Now I want to be able to access my 'req.user' and the isAuthenticated middleware that I declared in app.js
function isAuthenticated(req, res, done) {
if (req.user) {
return done();
}
return res.send('You need to be authenticated to view this page.');
}
this is my settings.js file from the routes folder
const express = require('express')
const router = new express.Router();
router.get('/main', (req, res) => {
res.send(req.user)
})
module.exports = router;
Conclusion
I want to do the same thing as the '/test' app.js in my '/s/main' in express router
Thanks for reading
app.js
const express = require('express');
const app = express();
const session = require('express-session');
const passport = require('passport')
const LocalStrategy = require('passport-local').Strategy;
const fs = require('fs');
const settings = require('./routes/settings')
app.use("/s", settings) //
app.use(express.urlencoded({ extended: false }))
app.use(session({ secret: 'pswd', resave: false, saveUninitialized: false }))
app.use(passport.initialize());
app.use(passport.session());
passport.use(new LocalStrategy(
function(email, password, done) {
console.log(email, password)
let user = findByEmail(email) // converts email address to user ID
let uid = user.id;
console.log(user, uid)
// compare(id) basically gets the password from the database
if (user.code != 200) {
return done(null, false, { message: 'Email not registered.' });
}
if (compare(uid) == password) {
return done(null, user); // login success
} else {
return done(null, false, { message: 'Incorrect password.' });
}
}
))
passport.serializeUser((user, done) => {
if (user) {
return done(null, user.id);
}
return done(null, false);
});
passport.deserializeUser((id, done) => {
let user = findById(id)
if (user.id == null) {
return done(null, false)
}
return done(null, user)
});
function isAuthenticated(req, res, done) {
if (req.user) {
return done();
}
return res.send('You need to be authenticated to view this page.');
}
app.get('/test', isAuthenticated, (req, res) => {
res.json(req.user)
})
app.get('/login', (req, res) => {
res.send('Login Page')
})
app.post('/login', passport.authenticate('local'), function (req, res) {
console.log('Valid login')
res.json(req.user)
})
app.post('/logout', (req, res) => {
req.logout();
res.send('Logged out')
})
app.get('/', (req, res) => {
res.send('Hello World!');
})
function findByEmail(email) {
let users = JSON.parse(fs.readFileSync('users.json', 'utf8'));
let index = users.findIndex(user => user.email == email);
if (index != -1) {
users[index].code = 200;
return users[index]
} else {
return { code: 404, email: null, id: null, expiry: null }
}
}
function findById(id) {
let users = JSON.parse(fs.readFileSync('users.json', 'utf8'));
let index = users.findIndex(user => user.id == id);
if (index != -1) {
return users[index]
} else {
return { email: null, id: null, expiry: null }
}
}
function compare(id) {
// basisically comparing the user ID's password and the entered password
if (id == 'f8dbee1ba8e95ace16656a008c548b91') {
return 'pswd_admin'
}
}
app.listen(3000, () => {
console.log('Server is up on port 3000');
});
module.exports = { isAuthenticated }
settings.js
const express = require('express')
const router = new express.Router();
router.get('/main', (req, res) => {
res.json(req.user)
})
module.exports = router;```

Related

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.

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.

Node.js auth page with passport-local and bcryptjs

I have a basic login auth page but whenever i try and login the page just reloads,
I'm relatively new to this and really need help.
server.js👇
const express = require("express");
const fs = require("fs");
const path = require("path");
const passport = require("passport");
const session = require("express-session");
const initializePasspost = require("./passport-config");
const flash = require("express-flash");
const bcrypt = require("bcryptjs");
initializePasspost(
passport,
email => users.find(user => user.email === email),
id => users.find(user => user.id === id)
);
let data = fs.readFileSync("./files/users.json");
let userData = JSON.parse(data);
app.set("view-engine", "ejs");
app.use(express.urlencoded({ extended: false }));
app.use("/assets", express.static(path.join(__dirname, "/assets")));
app.use("/script", express.static(path.join(__dirname, "/script")));
app.use(flash());
app.use(
session({
secret: "woff",
resave: false,
saveUninitialized: false
})
);
app.use(passport.initialize());
app.use(passport.session());
// Middleware
const checkAuthenticated = (req, res, next) => {
if (req.isAuthenticated()) {
return next();
}
res.redirect("/admin");
};
const checkNotAuthenticated = (req, res, next) => {
if (req.isAuthenticated()) {
return res.redirect("/");
}
next();
};
app.get("/test", checkAuthenticated, (req, res) => res.render("test.ejs"));
app.get("/register", checkNotAuthenticated, (req, res) =>
res.render("register.ejs")
);
app.post(
"/adminLogin",
passport.authenticate("local", {
successRedirect: "/test",
failureRedirect: "/adminLogin",
failureFlash: true
}),
(req, res) => {}
);
const PORT = process.env.PORT || 3000;
app.listen(PORT, err => {
console.log(`Server Running at port: ${PORT}`);
});
I know im not the best or optimal coder, but i need help.
passport-config.js👇
const bcrypt = require("bcryptjs");
const LocalStrategy = require("passport-local").Strategy;
const initialize = (passport, getUserByEmail, getUserById) => {
const authenticateUser = async (email, password, done) => {
const user = getUserByEmail(email);
if (user == null) {
return done(null, false, { message: "No user with that email" });
}
try {
if (bcrypt.compareSync(password, user.password)) {
return done(null, user);
} else {
return done(null, false, { message: "password Incorrect" });
}
} catch (e) {
return done(e);
}
};
passport.use(new LocalStrategy({ usernameField: "email" }, authenticateUser));
passport.serializeUser((user, done) => done(null, user.id));
passport.deserializeUser((id, done) => done(null, getUserById(id)));
};
module.exports = initialize;
I would have installed bcrypt but there was a problem installing it so I opted for bcryptjs.
I got some of the code from a youtube tutorial.
I don't know what to do. Please help. I'm stuck on this for more than a week.

Connect-pg-simple not saving session to database

I am trying to implement simple authentication with Node, Express, Express-Session and Passport.js. As a storage middleware I'm using connect-pg-simple as I am using pg-promise in my project.
I managed to configure passport to work with my routers but for some reason sessions won't be saved to my database. None of the plugins return any errors, everything seems to be running smoothly but my sessions table is empty.
What could I be doing wrong? connect-pg-simple connects to the server, passport.js is holding sessions and express-session assigns configured maxAge to cookies.
server.js
const express = require('express');
const db = require('./database.js');
const cors = require('cors');
const helmet = require('helmet');
const session = require('express-session');
const passport = require('passport');
const port = process.env.PORT || 3000;
const app = express();
const pgSession = require('connect-pg-simple')(session);
const pgStoreConfig = {
pgPromise: db.conn
};
app.set('trust proxy', 1);
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(
session({
secret: REDACTED, // need to change it later to some proper hash
store: new pgSession(pgStoreConfig),
resave: true,
cookie: {
maxAge: 30 * 24 * 60 * 60 * 1000, // 30 days ;)
secure: app.get('env') === 'production'
},
saveUninitialized: false
})
);
app.use(passport.initialize());
app.use(passport.session());
app.use(cors());
app.use(helmet());
app.get('/', (req, res) => {
if (req.session.views) {
req.session.views++;
} else {
req.session.views = 1;
}
//res.send(`Views: ${req.session.views}`);
res.json(req.session);
});
const userRouter = require('./routes/user.js');
app.use(userRouter);
config/passport.js
const passport = require('passport');
const local = require('passport-local');
const db = require('../database.js');
const statements = require('../routes/statements/user.js');
const cryptoUtils = require('../utils/crypto.js');
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser(async (id, done) => {
try {
let result = await db.conn.one(statements.getUserByIdStatement, [id]);
done(null, result);
} catch (error) {
console.log(`Error while deserializing user: ${error}`);
return done(error);
}
});
passport.use(
new local.Strategy(
{ usernameField: 'email', passwordField: 'password' },
async (username, password, done) => {
try {
let user = await db.conn.one(statements.loginUserStatement, [username]);
if (user == null) {
console.log(`Couldn't find user!`);
return done(null, false);
} else {
let passwordCheck = cryptoUtils.comparePasswords(
password,
user.password,
user.salt
);
if (passwordCheck) {
delete user.password;
delete user.salt;
console.log(`Successfuly logged in!`);
return done(null, user);
} else {
console.log(`Wrong password!`);
return done(null, false);
}
}
} catch (error) {
console.log(`Error during local strategy authentication: ${error}`);
return done(null, false);
}
}
)
);
module.exports = passport;
routes/user.js
router.post('/user/login', (req, res, next) => {
console.log('Authenticating');
passport.authenticate('local', (err, user, info) => {
if (err) {
res.status(500).json({ status: err });
}
if (!user) {
res.status(404).json({ status: 'User not found' });
}
if (user) {
req.logIn(user, function(err) {
if (err) {
res.status(500).json({ status: 'Error while logging in' });
}
res.redirect('/');
});
}
})(req, res, next);
});
router.get('/user/logout', userUtils.loginRequired, (req, res, next) => {
req.logout();
res.status(200).json({ status: 'Logged out' });
});
database.js
const pgp = require('pg-promise')(initOptions);
const conn = pgp(connectionConfig);
module.exports = {
pgp,
conn
};
Any help would be much appreciated.

Passport.js remember me functionality

https://github.com/jaredhanson/passport-remember-me
passport.use(new RememberMeStrategy(
function(token, done) {
Token.consume(token, function (err, user) {
if (err) { return done(err); }
if (!user) { return done(null, false); }
return done(null, user);
});
},
function(user, done) {
var token = utils.generateToken(64);
Token.save(token, { userId: user.id }, function(err) {
if (err) { return done(err); }
return done(null, token);
});
}
));
post
app.post('/login',
passport.authenticate('local', { failureRedirect: '/login', failureFlash: true }),
function(req, res, next) {
// issue a remember me cookie if the option was checked
if (!req.body.remember_me) { return next(); }
var token = utils.generateToken(64);
Token.save(token, { userId: req.user.id }, function(err) {
if (err) { return done(err); }
res.cookie('remember_me', token, { path: '/', httpOnly: true, maxAge: 604800000 }); // 7 days
return next();
});
},
function(req, res) {
res.redirect('/');
});
I'm trying to implement remember me feature (above) into my existing application but I couldn't make it. When I add RememberMeStrategy into my login.js, it throws
ReferenceError: RememberMeStrategy is not defined
error. What's missing here?
index.js
var rendering = require('../util/rendering');
var express = require('express');
var router = express.Router();
exports.home = function(req, res) {
res.render('index/index');
};
exports.userHome = function(req, res) {
res.render('index/user-home');
};
login.js
var crypto = require('crypto'),
passport = require('passport'),
passportRememberMe = require('passport-remember-me'),
passportLocal = require('passport-local'),
data = require('../models/auth')();
exports.registerPage = function (req, res) {
res.render('login/register', {username: req.flash('username')});
};
exports.registerPost = function (req, res) {
var vpw = req.body.vpw;
var pwu = req.body.pw;
var un = req.body.un;
req.flash('username', un);
if (vpw !== pwu) {
req.flash('error', 'Your passwords did not match.');
res.redirect('/register');
return;
}
req.checkBody('un', 'Please enter a valid email.').notEmpty().isEmail();
var errors = req.validationErrors();
if (errors) {
var msg = errors[0].msg;
req.flash('error', msg);
res.redirect('/register');
return;
}
var new_salt = Math.round((new Date().valueOf() * Math.random())) + '';
var pw = crypto.createHmac('sha1', new_salt).update(pwu).digest('hex');
var created = new Date().toISOString().slice(0, 19).replace('T', ' ');
new data.ApiUser({email: un, password: pw, salt: new_salt, created: created}).save().then(function (model) {
passport.authenticate('local')(req, res, function () {
res.redirect('/home');
})
}, function (err) {
req.flash('error', 'Unable to create account.');
res.redirect('/register');
});
};
exports.loginPage = function (req, res) {
res.render('login/index', {username: req.flash('username')});
};
exports.checkLogin = function (req, res, next) {
passport.authenticate('local', function (err, user, info) {
if (err || !user) {
req.flash('username', req.body.un);
req.flash('error', info.message);
return res.redirect('/login');
}
req.logIn(user, function (err) {
if (err) {
req.flash('error', info.message);
return res.redirect('/login');
}
req.flash('success', 'Welcome!');
return res.redirect('/home');
});
})(req, res, next);
};
exports.logout = function (req, res) {
req.logout();
req.flash('info', 'You are now logged out.');
res.redirect('/login');
};
routes.js
var rendering = require('./util/rendering'),
indexController = require('./controllers/index'),
loginController = require('./controllers/login');
module.exports = function (app, passport) {
// Home
app.get('/', indexController.home);
app.get('/home', ensureAuthenticated, indexController.userHome);
// Auth
app.get('/register', loginController.registerPage);
app.post('/register', loginController.registerPost);
app.get('/login', loginController.loginPage);
app.post('/login', loginController.checkLogin);
app.get('/logout', loginController.logout);
// 'rendering' can be used to format api calls (if you have an api)
// into either html or json depending on the 'Accept' request header
app.get('/apitest', function(req, res) {
rendering.render(req, res, {
'data': {
'test': {
'testsub': {
'str': 'testsub hello world'
},
'testsub2': 42
},
'test2': 'hello world'
}
});
})
// Auth Middleware
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) { return next(); }
res.redirect('/login');
}
}
server.js
var dbConfig;
try {
// Look for dev conf for local development
dbConfig = require('./config/db.dev.conf.js');
} catch(e) {
try {
// production conf?
dbConfig = require('./config/db.conf.js');
} catch(e) {
console.log('Startup failed. No db config file found.');
return false;
}
}
var knex = require('knex')({
client: 'mysql',
connection: dbConfig
}),
express = require('express'),
bodyParser = require('body-parser'),
cookieParser = require('cookie-parser'),
cookieSession = require('cookie-session'),
serveStatic = require('serve-static'),
expressValidator = require('express-validator'),
flash = require('connect-flash'),
swig = require('swig'),
passport = require('passport'),
passportRememberMe = require('passport-remember-me'),
passportLocal = require('passport-local'),
crypto = require('crypto'),
Bookshelf = require('bookshelf'),
messages = require('./util/messages');
var app = express();
Bookshelf.mysqlAuth = Bookshelf(knex);
app.use(cookieParser('halsisiHHh445JjO0'));
app.use(cookieSession({
keys: ['key1', 'key2']
}));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(expressValidator());
app.use(passport.initialize());
app.use(passport.session());
app.use(passport.authenticate('remember-me'));
app.use(flash());
app.use(serveStatic('./public'));
//app.use(express.favicon(__dirname + '/public/images/shortcut-icon.png'));
app.use(messages());
app.engine('html', swig.renderFile);
app.set('view engine', 'html');
app.set('views', __dirname + '/views');
require('./util/auth')(passport);
require('./routes')(app, passport);
app.listen(process.env.PORT || 3000);
console.log('Listening on port 3000');
That error is simply saying that you haven't defined the RememberMeStrategy function before calling it (you're using new but in Javascript that's just calling a function with a special variable called this). You need to require the module first, in this case:
var RememberMeStrategy = require('passport-remember-me').Strategy;
Just require it in the variable RememberMeStrategy
var RememberMeStrategy= require('passport-remember-me').Strategy;

Resources