PassportJs not saving sessions - javascript

I am using react and nodejs with passportjs. I called a post request to validate the username and password using local strategy. and on same page, I have a button that calls a get request to just console.log(req.user).
The issue is: on route /login - post, I am being able to console.log(req.user) while when I click on a button to make a get request to /getstatus, it gives me undefined.
If you check the /login post route, the res.send(req.user) also sends undefined, whereas the console.log(req.user) is showing the right information in the console.
I need help, do not know what I am doing wrong.
Below I have my code:
const express = require("express");
const bodyParser = require("body-parser");
require("dotenv").config();
const mongoose = require("mongoose");
const passport = require("passport");
const passportLocalMongoose = require("passport-local-mongoose");
const cookieParser = require("cookie-parser");
const expressSession = require("express-session");
const cors = require("cors");
const session = require("cookie-session");
const LocalStrategy = require("passport-local").Strategy;
//............................Initialization of middleware..........................
const app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(cors());
app.use(cookieParser());
app.use(passport.initialize());
app.use(passport.session());
//..............connect to a database...............................
const Users = new mongoose.Schema({
username: String,
password: String,
});
Users.plugin(passportLocalMongoose);
const MyModel = mongoose.model("MyModel", Users);
passport.use(MyModel.createStrategy());
// passport.use(new LocalStrategy(MyModel.authenticate()));
passport.serializeUser(MyModel.serializeUser());
passport.deserializeUser(MyModel.deserializeUser());
mongoose.connect(
process.env.DB_HOST,
{
useNewUrlParser: true,
useUnifiedTopology: true,
},
() => {
console.log("Database Connected");
}
);
// };
//......................Routes........................
app.post(
"/login",
cors(),
passport.authenticate("local", {
failureRedirect: "/failure",
}),
function (req, res, next) {
res.send(req.user);
console.log(req.user);
}
);
app.get("/failure", (req, res) => {
res.send({
name: "fff",
age: 23,
status: 500,
msg: "Invalid Username or Password",
color: "danger",
});
});
app.post("/reg", cors(), (req, res) => {
let username = req.body.username;
let password = req.body.password;
// connectdb();
MyModel.register({ username: username, active: false }, password, function (
err,
user
) {
if (err) {
console.log(err);
} else {
res.send("Success");
}
});
});
app.get("/getstatus", (req, res) => {
console.log(req.user);
});
//...........Start Server..........................
app.listen(5000, () => {
console.log("Server Started on Port 5000");
});

I got the solution, the issue is not with passportJS. it is with Axios.
This line of code is needed:
Axios.defaults.withCredentials = true;

Related

req.isAuthenticated is not a function while using Express and passport

in the last few hours I setup a backend express server. It works just fine and now I tryed to implement an authorization with help of a tutorial.
The login works, but when I try to open /authrequired (so basically a future page which needs a logged in user to work) I get the error message: "TypeError: req.isAuthenticated is not a function"
Here is my index.js file:
const express = require('express');
const fs = require('fs');
const http = require('http');
const https = require('https');
const path = require('path');
const uuid = require('uuid').v4;
const session = require('express-session');
const FileStore = require('session-file-store')(session);
const bodyParser = require('body-parser');
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const users = [
{id: '2f24vvg', email: 'test#test.com', password: 'password'}
]
// configure passport.js to use the local strategy
passport.use(new LocalStrategy(
{ usernameField: 'email' },
(email, password, done) => {
console.log('Inside local strategy callback')
// here is where you make a call to the database
// to find the user based on their username or email address
// for now, we'll just pretend we found that it was users[0]
const user = users[0]
if(email === user.email && password === user.password) {
console.log('Local strategy returned true')
return done(null, user)
}
}
));
// tell passport how to serialize the user
passport.serializeUser((user, done) => {
console.log('Inside serializeUser callback. User id is save to the session file store here')
done(null, user.id);
});
passport.deserializeUser((id, done) => {
console.log('Inside deserializeUser callback')
console.log(`The user id passport saved in the session file store is: ${id}`)
const user = users[0].id === id ? users[0] : false;
done(null, user);
});
const app = express();
app.enable('trust proxy')
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.use(session({
genid: (req) => {
console.log('Inside the session middleware')
console.log(req.sessionID)
return uuid() // use UUIDs for session IDs
},
store: new FileStore(),
secret: 'keyboard cat',
resave: false,
saveUninitialized: true
}))
app.use(passport.session());
app.post('/login', (req, res, next) => {
console.log('Inside POST /login callback')
passport.authenticate('local', (err, user, info) => {
console.log('Inside passport.authenticate() callback');
console.log(`req.session.passport: ${JSON.stringify(req.session.passport)}`)
console.log(`req.user: ${JSON.stringify(req.user)}`)
req.login(user, (err) => {
console.log('Inside req.login() callback')
console.log(`req.session.passport: ${JSON.stringify(req.session.passport)}`)
console.log(`req.user: ${JSON.stringify(req.user)}`)
return res.send('You were authenticated & logged in!\n');
})
})(req, res, next);
})
function isAuthenticated (req, res, next) {
if (req.session.user) next()
else next('route')
}
app.get('/authrequired', isAuthenticated, function (req, res) {
res.send('you hit the authentication endpoint\n')
})
app.use(express.static(path.resolve(__dirname, 'build')));
app.use(express.json());
// Redirect from http port to https
http.createServer(function (req, res) {
res.writeHead(301, { "Location": "https://" + req.headers['host'].replace(80,433) + req.url });
console.log("http request, will go to >> ");
console.log("https://" + req.headers['host'].replace(80,433) + req.url );
res.end();
}).listen(80, () => console.info('Listening on port', 80))
//Start https server
https.createServer({
key: fs.readFileSync('./ssl/privkey.key'),
cert: fs.readFileSync('./ssl/cert.cer'),
keepAlive: true
}, app).listen(443, () => console.info('Listening on port', 443));
Anyone got a clue? I saw similar questions on stackoverflow, but nothing worked for me.
There is no such function isAuthenticated. That's why you get the error.
Try replace it with if(req.session.user) {
Or by the example in express-session
// middleware to test if authenticated
function isAuthenticated (req, res, next) {
if (req.session.user) next()
else next('route')
}
app.get('/', isAuthenticated, function (req, res) {
// this is only called when there is an authentication user due to isAuthenticated
res.send('hello, ' + escapeHtml(req.session.user) + '!' +
' Logout')
})
EDIT: You also need to use passport session middleware, by adding
app.use(passport.session());
Make sure it is coming after the session init.

Csurf (Cross Site Request Forgery) Protection in a pop up css login authentication modal in Pug/Express

I can't seem to get my csurf token to work in my pop up strictly css modal, for authentication purposes. It works fine in a page (not in modal). I am using Pug view engine, express and cookie parser. Below is the relevant code, any suggestions would be appreciated, thank you.
layout.pug
a(href="#open-modal")
span Login
div(id="open-modal" class="modal-window")
div
a(href="#" title="Close" class="modal-close") Close
h1 Login
div
+errorSummaryList(errors)
form(method="post" action="/get" class="nav__login")
input(type="hidden" name="_csrf" value=csrfToken)
label(for="username") Username:
input(type="text" name="username" id="username")
label(for="password") Password:
input(type="password" name="password" id="password")
button Submit
button Demo User
auth.js
const { User } = require('./db/models');
function loginUser(req, res, user){
req.session.auth = {
userId: user.id
};
req.session.save(function () {
res.redirect("/");
});
console.log(req.session)
};
async function restoreUser(req, res, next){
if(req.session.auth){
let { userId }= req.session.auth;
try{
let user = await User.findByPk(userId);
if(user){
res.locals.authenticated = true;
res.locals.user = user;
console.log(res.locals)
next();
}
} catch(error){
res.locals.authenticated = false;
next(error);
}
}
res.locals.authenticated = false;
next();
}
function logoutUser(req,res){
delete req.session.auth;
}
users.js
router.get('/login', csrfProtection, asyncHandler(async(req, res, next)=> {
let user = User.build();
res.render('user-login',{user, csrfToken: req.csrfToken()})
}));
router.post('/login',loginValidators, csrfProtection, asyncHandler(async(req, res, next)=>{
const { username, password } = req.body;
let errors = [];
const validationErrors = validationResult(req);
if(validationErrors.isEmpty()){
const user = await User.findOne({
where:{
username
}
})
if(user){
console.log('found user')
const isVerified = await bcrypt.compare(password, user.password.toString())
if(isVerified){
console.log("verified")
loginUser(req, res, user)
return;
}
errors.push("Username and/or password are incorrect. Try again. ");
}
}
validationErrors.array().map(err => errors.push(err.msg));
res.render('user-login',{errors, csrfToken: req.csrfToken()})
}));
app.js
const createError = require('http-errors');
const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const { sequelize } = require('./db/models');
const session = require('express-session');
const SequelizeStore = require('connect-session-sequelize')(session.Store);
const indexRouter = require('./routes/index');
const usersRouter = require('./routes/users');
const { restoreUser } = require('./auth');
const { sessionSecret } = require('./config');
const app = express();
// view engine setup
app.set('view engine', 'pug');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser(sessionSecret));
app.use(express.static(path.join(__dirname, 'public')));
// set up session middleware
const store = new SequelizeStore({ db: sequelize });
app.use(
session({
secret: sessionSecret,
store,
saveUninitialized: false,
resave: false,
})
);

rendering username or id in the url with express routing

I have read some documentation on express routing and I am trying to render the logged in user's username or identification in the url. I need help getting the routing hit in my server.js to render the pages even before authentication. Where am I messing up?
Routing (profile.js)
const express = require("express");
var router = express.Router();
const User = require("../models/user");
const passport = require("passport");
const multer = require("multer");
// Profile Avatar
const upload = multer({ dest: "upload" });
// ACCOUNT ROUTES
router
.route("/profile/:id")
.get(function (req, res) {
if (req.isAuthenticated()) {
let dateObj = req.user.createdAt;
let createdDate = dateObj.toString().slice(4, 16);
let navbarLoggedIn = "partials/loggedIn-navbar.ejs";
let id = req.params.username;
console.log(id + "\n");
res.render(
"profile",
{ id: req.params.id },
{
currentUser: req.user.username,
currentCompany: req.user.company,
currentLocation: req.user.location,
currentPosition: req.user.position,
memberStatus: createdDate,
navbar: navbarLoggedIn,
}
);
} else {
res.redirect("login");
}
})
.post(function (req, res) {});
module.exports = router;
server.js
require("dotenv").config();
const express = require("express");
const session = require("express-session");
const passport = require("passport");
const path = require("path");
const ejs = require("ejs");
const logger = require("morgan");
const main = require("./routes/main");
const about = require("./routes/about");
const contact = require("./routes/contact");
const profile = require("./routes/profile");
const pricing = require("./routes/pricing");
const help = require("./routes/help");
const login = require("./routes/login");
const signup = require("./routes/signup");
const forgot_password = require("./routes/forgot-password");
const User = require("./models/user");
const multer = require("multer");
// PORT
const port = 8080;
const app = express();
// COOKIES AND SESSION
app.use(
session({
secret: process.env.SECRET,
resave: false,
saveUninitialized: true,
})
);
app.use(passport.initialize());
app.use(passport.session());
// DATABASE
require("./config/database.js");
// PASSPORT AUTHENTICATION
require("./config/passport.js");
// MIDDLEWARE
app.use(logger("dev"));
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use("/public", express.static(path.join(__dirname + "/public")));
app.set("view engine", "ejs");
app.set("view cache", false);
// ROUTES
app.use("/", main);
app.use("/about", about);
app.use("/contact", contact);
app.use("/pricing", pricing);
app.use("/profile/:id", profile, (req, res, next) => {
next();
});
app.use("/help", help);
app.use("/login", login);
app.use("/signup", signup);
app.use("/forgot-password", forgot_password);
// Logout
app.get("/logout", function (req, res) {
res.clearCookie("connect.sid");
res.redirect("/");
});
app.listen(port, (err, done) => {
if (!err) {
console.log({ message: "success!" });
} else {
return err;
}
});
And here is my file structure.file structure.
views strucutre
When you define the profile router in your main server file, instead of defining one specific route, define a short prefix. In your case you'll use /profile. Then in your router simply define the rest of the route (/:id).
Example:
Server:
app.use("/profile", profile, (req, res, next) => {
next();
});
Router:
router
.route("/:id")
.get(function (req, res) {
if (req.isAuthenticated()) {
let dateObj = req.user.createdAt;
let createdDate = dateObj.toString().slice(4, 16);
let navbarLoggedIn = "partials/loggedIn-navbar.ejs";
let id = req.params.username;
console.log(id + "\n");
res.render(
"profile",
{
id: req.params.id
},
{
currentUser: req.user.username,
currentCompany: req.user.company,
currentLocation: req.user.location,
currentPosition: req.user.position,
memberStatus: createdDate,
navbar: navbarLoggedIn,
}
);
} else {
res.redirect("login");
}
});

password comparison with bcrypt not working

i'm fairly new to express js i want to do a login app so far i did the register part but in login app i want to do the comparaison between the password in database and the password provided by the user and compare it with bcrypt since i'm using it to crypt password , but its not doing the comparaison , what i'm missing here
router
const express = require('express')
const router = express.Router()
const bcrypt = require('bcrypt');
const User = require('../models/user')
const jwt = require('jsonwebtoken')
router.get('/login', function (req, res) {
res.render('login')
})
router.get('/', function (req, res) {
res.render('home')
})
router.get('/register', function (req, res) {
res.render('register')
})
router.post('/register', async function(req,res){
User.beforeCreate((user, options) => {
return bcrypt.hash(user.password, 10)
.then(hash => {
user.password = hash;
})
.catch(err => {
throw new Error();
});
});
return User.create({
username: req.body.name,
password: req.body.password,
email: req.body.email,
createdAt: Date.now()
}).then(function (users) {
res.send(users);
}).catch((err)=>{
console.log(err)
})
})
router.post('/login', function(req,res){
User.findOne({
where:{
username:req.body.name
}
})
.then(user=>{
if(user){
if(bcrypt.compareSync(req.body.password,user.password)){
let token = jwt.sign(user.dataValues,secretKey,{
expiresIn:1440
})
res.send(token)
}
else {
res.status(400).json({
error:'error exissts'
})
}
}
})
.catch(err=>{
res.status(400).json({err:err})
})
})
module.exports = router
models
const sequelize = require('../database/db.js')
const Sequelize = require('sequelize');
const User = sequelize.define('authentication',{
username: {
type: Sequelize.STRING,
allowNull: false
},
password: {
type: Sequelize.STRING
// allowNull defaults to true
} ,
email: {
type: Sequelize.STRING
// allowNull defaults to true
},
created_at: {
field: 'createdAt',
type: Sequelize.DATE,
},
updated_at: {
field: 'updatedAt',
type: Sequelize.DATE,
},
}, {
freezeTableName: true
},
{
notNull: { args: true, msg: "You must enter a name" }
},
)
module.exports = User
index
const express = require('express');
const exphbs = require('express-handlebars');
const bodyParser = require('body-parser');
const path = require('path');
// const passport = require('passport');
// const passportJWT = require('passport-jwt');
// Database
const db = require('./database/db');
// Test DB
db.authenticate()
.then(() => console.log('Database connected...'))
.catch(err => console.log('Error: ' + err))
const app = express();
// Handlebars
app.engine('handlebars', exphbs({ defaultLayout: 'main' }));
app.set('view engine', 'handlebars');
// Body Parser
app.use(bodyParser.urlencoded({ extended: false }));
// Set static folder
app.use(express.static(path.join(__dirname, 'public')));
// Importing files
const routes = require("./routes/route");
app.use("/", routes);
const PORT = process.env.PORT || 5000;
app.listen(PORT, console.log(`Server started on port ${PORT}`));
index.js
const express = require('express');
const exphbs = require('express-handlebars');
const bodyParser = require('body-parser');
const path = require('path');
// const passport = require('passport');
// const passportJWT = require('passport-jwt');
// Database
const db = require('./database/db');
// Test DB
db.authenticate()
.then(() => console.log('Database connected...'))
.catch(err => console.log('Error: ' + err))
const app = express();
// Handlebars
app.engine('handlebars', exphbs({ defaultLayout: 'main' }));
app.set('view engine', 'handlebars');
// Body Parser
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json())
// Set static folder
app.use(express.static(path.join(__dirname, 'public')));
// Importing files
const routes = require("./routes/route");
app.use("/", routes);
const PORT = process.env.PORT || 4500;
app.listen(PORT, console.log(`Server started on port ${PORT}`));
route.js
const express = require('express')
const router = express.Router()
const bcrypt = require('bcrypt');
const User = require('../models/user')
const jwt = require('jsonwebtoken')
const uuid = require('uuidv4').default;
const secretKey = '321'
router.get('/login', function (req, res) {
res.render('login')
})
router.get('/', function (req, res) {
res.render('home')
})
router.get('/register', function (req, res) {
res.render('register')
})
router.post('/register', function(req,res){
User.beforeCreate((user, options) => {
return bcrypt.hash(user.password, 10)
.then(hash => {
user.password = hash;
})
.catch(err => {
throw new Error();
});
});
return User.create({
id: uuid(),
username: req.body.name,
password: req.body.password,
email: req.body.email,
createdAt: Date.now()
}).then(function (users) {
res.send(users);
}).catch((err)=>{
console.log(err)
})
})
router.post('/login', function(req,res){
User.findOne({
where:{
username:req.body.name
}
})
.then(user=>{
if(user){
if(bcrypt.compareSync(req.body.password,user.password)){
let token = jwt.sign(user.dataValues,secretKey,{
expiresIn:1440
})
res.send(token)
}
else {
res.status(400).json({
error:'error exissts'
})
}
}
})
.catch(err=>{
res.status(400).json({err:err})
})
})
module.exports = router
just add app.use(bodyParser.json()) in index.js and define secretKey also add id in user model for primary key and the code working properly

req.user is unidentified in session (Node, express, session, passport)

For some reason req.user is undefined, and after 4+ hours of trying to figure out why, I'm asking here. I even copy-pasted the server/index.js file of a friend's server, changed the auth strategy so it worked for mine, and I get the same issue.
Everything else is working. It redirects to auth0, comes back to the correct place, either creates a new user in the DB or finds the user. In passport.serializeUser it has all the data I passed along. But when I hit the '/auth/me' endpoint, req.user is undefined.
server/index.js
require('dotenv').config();
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors')
const session = require("express-session");
const passport = require('passport');
const Auth0Strategy = require('passport-auth0');
const massive = require('massive');
const axios = require('axios');
const process = require("process");
const moment = require('moment');
const app = express();
//app.use(express.static(__dirname + './../build'));
app.use(bodyParser.json());
app.use(cors());
app.use(session({
secret: process.env.SECRET,
cookie: { maxAge: 60000 },
resave: false,
saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());
// Use the session middleware
massive(process.env.CONNECTION_STRING)
.then( (db) => {
console.log('Connected to Heroku')
app.set('db', db);
}).catch(err=>console.log(err))
passport.use(new Auth0Strategy({
domain: process.env.AUTH_DOMAIN,
clientID: process.env.AUTH_CLIENT_ID,
clientSecret: process.env.AUTH_CLIENT_SECRET,
callbackURL: process.env.AUTH_CALLBACK
}, (accessToken, refreshToken, extraParams, profile, done) => {
const db = app.get("db");
const userData = profile._json;
db.find_user([userData.identities[0].user_id]).then(user => {
if (user[0]) {
return done(null, user[0]);
} else {
db.create_user([
userData.given_name,
userData.family_name,
userData.email,
userData.identities[0].user_id
])
.then(user => {
return done(null, user);
});
}
});
}))
passport.serializeUser( (user, done) => {
//console.log('serializeuser', user)
done(null, user);
})
passport.deserializeUser( (id, done) => {
app.get("db").find_session_user([id])
.then(user => {
console.log(user);
done(null, user[0]);
});
})
app.get('/auth', passport.authenticate('auth0'));
app.get('/auth/callback', passport.authenticate('auth0', {
successRedirect: process.env.SUCCESS_REDIRECT
}))
app.get('/auth/me', (req, res) => {
console.log('auth/me endpoint hit')
console.log(req.user)
if(!req.user){
return res.status(401).send('No user logged in.');
}
return res.status(200).send(req.user);
})
app.listen(process.env.PORT, () => console.log(`Listening on port: ${process.env.PORT}`));
server/.env
CONNECTION_STRING=postgres:*****
SECRET=*******
AUTH_DOMAIN=****.auth0.com
AUTH_CLIENT_ID=***
AUTH_CLIENT_SECRET=***
AUTH_CALLBACK=http://localhost:8084/auth/callback
SUCCESS_REDIRECT=http://localhost:3000/
PORT=8084
Try moving the app.get('/auth', passport.authenticate('auth0')); line after the app.get('/auth/me', (req, res) => { block. app.get can do regex matches and goes with the first one that matches (http://expressjs.com/en/api.html#path-examples), and I think it's trying to run the /auth logic for the /auth/me path.

Categories

Resources