I'm starting with Nuxt JS trying to migrate an old site with passport local and express-session, I get to make the authentication based on this repository but the main problem comes when I reload the page the users logout, its appears that Nuxt JS it's not saving my user session on the browser. I mostly sure there is something that im forgetting to implement or im not understanding. How could I save my res session token on my user browser?. Btw I have my API running on a separate port, so im not sure if there is any problem on saving session from other port. Here is my code:
Login.vue
<script>
import axios from 'axios';
export default {
data() {
return {
error : false,
form : {
username: '',
password: ''
}
}
},
created() {
if(this.$store.state.user) {
return this.$router.push('/');
}
},
methods: {
async login () {
await this.$store.dispatch('login', {
username : this.form.username,
password: this.form.password
});
this.form.password = '';
this.form.username = '';
}
},
}
</script>
Store/Index.js:
import axios from "axios";
export const state = () => ({
user: null,
});
export const mutations = {
SET_USER(state, user) {
state.user = user;
},
};
export const actions = {
nuxtServerInit({ commit }, { req }) {
if (req) {
if (
typeof req.session !== "undefined" &&
typeof req.user !== "undefined"
) {
commit("SET_USER", req.user);
}
}
},
login({ commit }, { username, password }) {
return axios({
method: "post",
url: this.$axios.defaults.baseURL + "/auth/login",
credentials: "same-origin",
data: {
username,
password
}
})
.then(res => {
if (res.data.meta.error === true) {
throw res.data;
}
return res.data.user;
})
.then(authUser => {
commit("SET_USER", authUser);
});
},
};
API Index.js
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const helmet = require('helmet');
const cors = require('cors') // Srsly. Fuck Cors
const morgan = require('morgan');
const session = require('express-session');
const MySQLStore = require('express-mysql-session')(session);
const passport = require('passport');
const { database } = require('./config/keys');
const config = require('./config/config.json');
require('./lib/bAuth');
app.disable('view cache');
app.disable('x-powered-by');
app.set('port', process.env.PORT || config.port);
app.use(helmet());
app.use(cors());
app.use(morgan('dev'));
app.use(express.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
app.use(cookieParser());
app.use(session({
name: '_hsid',
key: 'sessionKey',
secret: config.session_secret,
resave: false,
saveUninitialized: false,
store: new MySQLStore(database),
cookie : {
maxAge: 1000 * 60 * 60 *24 * 365,
},
})
);
app.use(passport.initialize());
app.use(passport.session());
app.listen(app.get('port'), () => console.log(`[✔] Website connected and running at port: ${app.get('port')}`))
Login Route:
app.post('/login', async (req,res,next) => {
req.query = req.body;
auth.authenticate('user-login', (err,user,info) => {
if(user){
req.logIn(user,(err)=>{
if(err){
return res.json({
meta: {
error: true,
msg: err
}
});
}else{
if(req.isAuthenticated()){
if(!req.user.authenticated){
return res.json({
meta: {
error: true,
msg: "Bad credentials"
}
});
}else{
return res.json({
meta: {
error: false
},
user: bAccess.cleanUser(Object.assign({}, user))
});
};
}
}
});
}else{
return res.json({
meta: {
error: true,
msg: "Bad credentials"
}
});
}
})(req,res,next);
});
Passport Config:
auth.use('user-login', new Strategy({
usernameField: 'username',
passwordField: 'password',
passReqToCallback: true
}, async (req, username, password, done) => {
const _user = await _context.query('select username,password from users where username = ?', username);
if (!_user[0]) return done(null,false);
if (!_user[0].password || !await bAccess.verifyPassword(password, _user[0].password)) {
return done(null, false);
}
done(null, _user[0], {scope : '*'});
}, ));
auth.serializeUser(function (user, done) {
done(null, user);
});
auth.deserializeUser(async (user, done) => {
done(null, user);
});
Related
I am writing a client/server application where the frontend is using React and Axios while the backend is using Express, MySQL and PassportJS. I have a running MySQL database with a users-table, and in the app I can register users successfully with their passwords being hashed and stored in the database. I have also implemented PassportJS to successfully authorize logins. After logging in with a correct username/password combination, a cookie with the following form is saved in the browser:
userId:
s:"qAxPZ8u77YA7_NRSk2sfLxltZI3D5klX.5okMTprFTBBq4RFwyCd2ptkAfv9dfL9Z7IViSK5bGpg"
I don't know if anything seems incorrect about the above cookie. It has some other properties of course like expires etc., but no obvious "user"-object or similar except for the string saved to userId.
Main problem is when I try to check whether a user is logged in to the app on the server side. I use axios on the client side, setup like this:
import axios from 'axios';
axios.defaults.baseURL = 'http://localhost:3000/api/v1';
axios.defaults.withCredentials = true;
And from the login-module (could be anyone but I used this to test) of my React app I call on a method I have saved which looks like this:
login() {
return axios.get("/login").then((response) => {
console.log(response);
});
}
This sends the request to the backend which is set up like this:
index.ts
import express from 'express';
import router from '../src/router';
import path from 'path';
import db from '../src/mysql-pool';
require('dotenv').config()
const app = express();
const passport = require('passport');
const flash = require('express-flash');
const session = require('express-session');
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
app.use(express.static(path.join(__dirname, '/../../client/public')));
app.use(express.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser(process.env.SESSION_SECRET));
app.use(flash());
app.use(session({
key: "userId",
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
cookie: {
expires: 86400000 // ms, aka 24 hours
}
}));
app.use(passport.initialize());
app.use(passport.session());
const initializePassport = require('./passport-config');
initializePassport(
passport,
(username: string) => {
return new Promise<{}>((resolve, reject) => {
db.query('SELECT * FROM users WHERE username = ?', [username], (error, results) => {
if (error) return reject(error);
if (!(results.length > 0)) {
return reject({ message: "User doesn't exist." });
}
resolve(results[0]);
});
});
},
(id: number) => {
return new Promise<{}>((resolve, reject) => {
db.query('SELECT * FROM users WHERE user_id = ?', [id], (error, results) => {
if (error) return reject(error);
if (!(results.length > 0)) {
return reject({ message: "User doesn't exist." });
}
resolve(results[0]);
});
});
}
);
// the method being called from the client side
router.get('/login', (request, response) => {
console.log(request.user);
if (request.user) {
response.send({ loggedIn: true, user: request.user });
} else {
response.send({ loggedIn: false })
}
});
router.post('/login', passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/login',
failureFlash : true
}));
app.use('/api/v1', router);
const port = 3000;
app.listen(port, () => {
console.info(`Server running on port ${port}`);
});
The router is declared in another file called router.ts:
import express from 'express';
import { registerService, loginService } from './services'; // file with some MySQL database queries
require('dotenv').config()
const bcrypt = require('bcrypt');
const saltRounds = 10;
const router = express.Router();
// [.. some unrelated and unproblematic api-calls and routes omitted here ..]
router.post('/register', (request, response) => {
const username = request.body.username;
const password = request.body.password;
if (username && username.length != 0) {
bcrypt.hash(password, saltRounds, (error: Error, hash: string) => {
if (error) response.status(500).send(error);
registerService.register(username, hash)
.then(() => response.status(201).send('New user registered'))
.catch((error) => response.status(500).send(error));
});
} else response.status(400).send("Can't register user: Missing username og password.");
});
export default router;
And passport is configured in a file called passport-config.ts:
// #ts-nocheck
const LocalStrategy = require('passport-local').Strategy;
const bcrypt = require('bcrypt');
function initialize(passport, getUserByUsername, getUserById) {
const authenticateUser = async (username, password, done) => {
const user = await getUserByUsername(username);
if (user == null) {
return done(null, false, { message: 'No user exists that matches the given username.' })
}
try {
if (await bcrypt.compare(password, user.passwd)) {
return done(null, user)
} else {
return done(null, false, { message: 'Wrong username or password.' })
}
} catch (error) {
return done(error)
}
}
passport.use(new LocalStrategy({ usernameField : 'username', passwordField : 'password'}, authenticateUser));
passport.serializeUser((user, done) => done(null, user.user_id));
passport.deserializeUser((id, done) => {
return done(null, getUserById(id));
});
};
module.exports = initialize;
Now: The PassportJS docs and most guides I have tried to follow say that user data after authenticating is stored as req.user. But this route on the backend:
router.get('/login', (request, response) => {
console.log(request.user);
if (request.user) {
response.send({ loggedIn: true, user: request.user });
} else {
response.send({ loggedIn: false })
}
});
returns undefined.
If I instead call:
router.get('/login', (request, response) => {
console.log(request.session); // console log the session instead of req.user
if (request.user) {
response.send({ loggedIn: true, user: request.user });
} else {
response.send({ loggedIn: false })
}
});
It logs:
Session {
cookie: {
path: '/',
_expires: 86400000,
originalMaxAge: 86400000,
httpOnly: true
}
}
So something is definetly happening.
It just doesn't seem like Passport ever saved the user data in the session after authenticating, or if it did, I can't find it.
Any help would be greatly appreciated, I can include more info as well if needed.
EDIT:
For future reference, the solution ended up having something to do with the order of the commands in index.ts. If I remember correctly I think the app.use(passport.xxx)-commands had to be above alot of the other commands. I am afraid I can't recall exactly what order fixed the issue.
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)
});
});
i am trying to develop a login system with React,Node,Mysql,Express and Passport but i have encountered this problem. After calling req.login and passing it the userID, when i go to the route where i check for the req.user it says undefined. Here is my code for the server side.
const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const app = express();
const session = require("express-session");
const { PORT = 8000 } = process.env;
const bcrypt = require("bcrypt");
const saltRounds = 10;
const cookieParser = require("cookie-parser");
const passport = require("passport");
var LocalStrategy = require('passport-local').Strategy;
const mysql = require("mysql");
/app.options("*", cors());
app.use(cors());
app.use(express.json()) // for parsing application/json
app.use(express.urlencoded({ extended: true })) // for parsing application/x-www-form-urlencoded
// app.use(cookieParser());
app.use(
session({
secret: "keyboard cat",
resave: false,
saveUninitialized: false
// cookie: { secure: false }
})
);
app.use(passport.initialize());
app.use(passport.session());
const connection = mysql.createConnection({
host: "localhost",
user: "root",
password: "qwertyhnjkl",
database: "login"
});
connection.connect(err => {
if (err) {
console.error("Error connection to database");
}
else console.log("Database connected");
});
app.get('/',function (req,res){
console.log(req.user);
console.log(req.isAuthenticated())
res.send('hello world')
});
app.post("/register", (req, res) => {
const { name, username, email, password } = req.body;
console.log(req.body);
bcrypt.hash(password, saltRounds, function(err, hash) {
connection.query(
`insert into users(Name,Username,Email,Password) values('${name}','${username}','${email}','${hash}')`,
function(error) {
if (error) console.error(error);
}
);
connection.query("SELECT LAST_INSERT_ID() as userID", (error,results,fields) =>
{
if (error) throw error;
console.log(results)
const userID = results[0].userID;
console.log("userid in query: " + userID);
req.login(userID, function(err) {
if(err) res.send(err);
else{
console.log("req.user in req.login: " + req.user)
console.log("isAuthenticated: "+ req.isAuthenticated())
console.log(req.session )
console.log('Logged in succesfully')
res.send("Logged in succesfully");
}
});
});
});
});
And this is how i handle the form in react:
submitRegister(event) {
event.preventDefault();
const data = this.state.data
axios.post("http://localhost:8000/register", {
name: data.name,
username: data.username,
email: data.email,
password: data.password
})
.then(response => {
console.log(response);
if(response.data){
console.log('Succesful signup');
this.setState({ //redirect to login page
redirectTo: '/'
})
}
}).catch(error => {
console.log("Sign up to server failed");
console.log(error)
});
}
After i request the '/' of the server and check for the session in Application->Cookies->localhost there is no session.
The insertion is well done. I get the username email hashed password in my database. i get the right userID i even get the console.log in serialize function with the right userID(the last one introduced)
req.user in req.login: 47
isAuthenticated: true
Session {
cookie:
{ path: '/',
_expires: null,
originalMaxAge: null,
httpOnly: true },
passport: { user: 47 } }
Logged in succesfully
serialize 47
This is what i get in the console when requesting the route /register from the server. Now when i go for localhost:8000 it says req.user is undefined and isAuthenticated false.
Looks like cors() was the issue here. After removing it and using proxy in package.json solved the issue.
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.
I'm having an issue with saving the session. It appears that logging in and logging out works fine. However, if making code changes or if the nodemon server refreshes, it renders null on the current_user route.
And then this error when making post requests.
Cannot read property 'id' of undefined
router.get("/current_user", (req, res) => {
if(req.user){
res.status(200).send({ user: req.user});
} else {
res.json({ user:null})
}
});
routes
const jwt = require('jsonwebtoken');
const passport = require('passport');
router.post('/loginUser', passport.authenticate('login', {session: true}), (req, res, next) => {
passport.authenticate('login', (err, user, info) => {
if (err) {
console.log(err);
}
if (info != undefined) {
console.log(info.message);
res.status(401).send(info.message);
} else {
req.logIn(user, err => {
models.User.findOne({
where: {
username: req.body.username,
},
}).then(user => {
const token = jwt.sign({ id: user.id }, process.env.JWT_SECRET);
// res.cookie("jwt", token, { expires: new Date(Date.now() + 10*1000*60*60*24)});
jwt.verify(token, process.env.JWT_SECRET, function(err, data){
console.log(err, data);
})
res.status(200).send({
auth: true,
token: token,
message: 'user found & logged in',
});
// console.log(req.user)
});
});
}
})(req, res, next);
});
passport.js
const bcrypt = require('bcrypt'),
BCRYPT_SALT_ROUNDS = 12,
JWTstrategy = require('passport-jwt').Strategy,
ExtractJWT = require('passport-jwt').ExtractJwt,
Sequelize = require('sequelize'),
Op = Sequelize.Op,
models = require( '../models/'),
localStrategy = require('passport-local').Strategy;
// passport = require("passport");
// serialize session, only store user id in the session information
module.exports = async (passport) => {
passport.use(
'register',
new localStrategy(
{
usernameField: 'username',
passwordField: 'password',
passReqToCallback: true,
session: false,
},
(req, username, password, done) => {
try {
models.User.findOne({
where: {
[Op.or]: [
{
username: username,
},
{ email: req.body.email },
],
},
}).then(user => {
if (user != null) {
console.log('username or email already taken');
return done(null, false, {
message: 'username or email already taken',
});
} else {
bcrypt.hash(password, BCRYPT_SALT_ROUNDS).then(hashedPassword => {
models.User.create({
username: req.body.username,
password: hashedPassword,
email: req.body.email
}).then(user => {
console.log('user created');
return done(null, user);
});
});
}
});
} catch (err) {
done(err);
}
},
),
);
passport.use(
'login',
new localStrategy(
{
usernameField: 'username',
passwordField: 'password',
session: false,
},
(username, password, done, req) => {
try {
models.User.findOne({
where: {
[Op.or]: [
{
username: username,
}
],
},
}).then(user => {
if (user === null) {
return done(null, false, { message: 'Username doesn\'t exist' });
} else {
bcrypt.compare(password, user.password).then(response => {
if (response !== true) {
console.log('passwords do not match');
return done(null, false, { message: 'passwords do not match' });
}
console.log('user found & authenticated');
// note the return needed with passport local - remove this return for passport JWT
return done(null, user);
});
}
});
} catch (err) {
done(err);
}
},
),
);
const opts = {
jwtFromRequest: ExtractJWT.fromAuthHeaderWithScheme('JWT'),
secretOrKey: process.env.JWT_SECRET,
};
passport.use(
'jwt',
new JWTstrategy(opts, (jwt_payload, done) => {
try {
models.User.findOne({
where: {
username: jwt_payload._id,
},
}).then(user => {
if (user) {
console.log('user found in db in passport');
// note the return removed with passport JWT - add this return for passport local
done(null, user);
// console.log(user);
} else {
console.log('user not found in db');
done(null, false);
}
});
} catch (err) {
done(err);
}
}),
);
passport.serializeUser(function(user, done) {
done(null, user.id);
console.log(user.id); // gets user id
});
// from the user id, figure out who the user is...
passport.deserializeUser(function(id, done){
models.User.findOne({
where: {
id,
},
}).then(user => done(null, user))
.catch(done);
});
}
app.js
var express = require('express');
var app = express();
var userRoute = require('./routes/users');
var postRoute = require('./routes/posts');
var bodyParser = require('body-parser');
var logger = require('morgan');
var session = require('express-session');
var cookieParser = require('cookie-parser') ;
var dotenv = require('dotenv');
var env = dotenv.config();
var cors = require('cors');
var models = require('./models/');
const host = '0.0.0.0';
const PORT = process.env.PORT || 8000;
const passport = require('passport');
const path = require('path');
// const allowOrigin = process.env.ALLOW_ORIGIN || '*'
// CORS Middleware
if (!process.env.PORT) {
require('dotenv').config()
}
// console.log(process.env.DATABASE_URL);
if (!process.env.PORT) {
console.log('[api][port] 8000 set as default')
console.log('[api][header] Access-Control-Allow-Origin: * set as default')
} else {
console.log('[api][node] Loaded ENV vars from .env file')
console.log(`[api][port] ${process.env.PORT}`)
console.log(`[api][header] Access-Control-Allow-Origin: ${process.env.ALLOW_ORIGIN}`)
}
app.use(logger('dev'));
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'build')));
app.use(cookieParser());
app.use(session({
secret : process.env.JWT_SECRET,
}));
require('./config/passport.js')(passport); // PASSPORT Init
app.use(passport.initialize());
app.use(passport.session());
app.use(bodyParser.urlencoded({ extended:false}));
app.use(bodyParser.json());
// this code may be useless or useful, still trying to understand cors.
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Credentials', true);
res.header("preflightContinue", false)
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
next();
});
app.use(cors({
origin: process.env.ALLOW_ORIGIN,
credentials: true,
allowedHeaders: 'X-Requested-With, Content-Type, Authorization',
methods: 'GET, POST, PATCH, PUT, POST, DELETE, OPTIONS'
}))
app.use('/api/users', userRoute );
app.use('/api/posts', postRoute );
// In order to use REACT + EXPRESS we need the following code, alone with a build
// in the client folder we run a npm run build in the client folder then it is referred
// in the following code.
app.use(express.static(path.join(__dirname, 'client/build')));
if(process.env.NODE_ENV === 'production') {
app.use(express.static(path.join(__dirname, 'client/build')));
//
app.get('*', (req, res) => {
res.sendfile(path.join(__dirname = 'client/build/index.html'));
})
}
//build mode
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname+'/client/public/index.html'));
})
app.use(function(req, res, next) {
res.locals.user = req.user; // This is the important line
// req.session.user = user
console.log(res.locals.user);
next();
});
models.sequelize.sync().then(function() {
app.listen(PORT, host, () => {
console.log('[api][listen] http://localhost:' + PORT)
})
})
The question is not so much about saving the req.user, this is an issue with not having a store set in place.
app.use(session({
store: '', // enter a store
secret : process.env.JWT_SECRET,
}));
You're using Sequelize, so i would recommend you to look into this
https://github.com/mweibel/connect-session-sequelize
If all runs well, you will not have to worry about req.id becoming undefined everytime you make a code change. Hope this helps.
You can do something like
const SequelizeStore = require('connect-session-sequelize')(session.Store);
const sequelize = new Sequelize(
process.env.POSTGRES_DB,
process.env.POSTGRES_USER,
process.env.POSTGRES_PASSWORD,{
"dialect": "sqlite",
"storage": "./session.sqlite"
});
myStore = new SequelizeStore({
db:sequelize,
})
app.use(session({
store: myStore,
secret : process.env.JWT_SECRET,
}));