Node + Express + Passport + Mongoose: req.user Undefined - javascript

When you log in, req.user is defined, but on other paths, req.user is undefined. Maybe I'm doing something wrong, I ran out of ideas.
Also desirilization is never called
server.js:
var LocalStrategy = require('passport-local').Strategy;
const User = require('./models/user');
const app = express();
mongoose.Promise = global.Promise;
const mongoDB = 'mongodb://mlab.com:21494/tester';
mongoose.connect(mongoDB, { useMongoClient: true })
const db = mongoose.connection;
db.on('error', console.error.bind(console, 'MongoDB connection error:'));
app.use(function (req, res, next) {
res.header('Access-Control-Allow-Credentials', 'true');
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept, Authorization');
if ('OPTIONS' == req.method) {
res.sendStatus(200);
} else {
next();
}
});
app.use(logger('dev'));
app.use(compression());
//////////////////////////////////////////////////
passport.use(new LocalStrategy(
function(username, password, done) {
console.log('Strategy>>>>');
User.findOne({ username: username }, function (err, user) {
if (err) { return done(err); }
if (!user) { return done(null, false); }
if (!user.verifyPassword(password)) { return done(null, false); }
return done(null, user);
});
}
));
passport.use(User.createStrategy());
passport.serializeUser(function (user, done) {
console.log('SERIALIZE', user); //called
done(null, user.id);
});
passport.deserializeUser(function (id, done) {
console.log('DESIRIALIZE'); // not called
User.findById(id, function (err, user) {
console.log('USER Desirialise', user);
done(err, user);
});
});
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
// Session
app.use(require('express-session')({
secret: 'keyboard cat',
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
//=====================LOGIN==================================
app.use('/', require('./routes/userRouters'));
userRouters.js:
const router = require('express').Router();
const jwt = require('jsonwebtoken');
const passport = require('passport');
const User = require('../models/user');
router.post('/signin', passport.authenticate('local'), function (req, res, next) {
console.log('SIGN IN');
const { user } = req
const token = jwt.sign({ username: user.username, email: user.email, _id: user._id }, 'RESTFULAPIs')
console.log('REQ USER>>', req.user); // defined
console.log('SESION', req.session.cookie); // passport defined
res.json({
user: {
user: user.username,
email: user.email,
created: user.created
},
token: token
});
})
router.get('/test', function (req, res) {
console.log('============================================');
console.log('reqUSER', req.user); //undefined
console.log('SESION', req.session.cookie); // passport undefined
res.json(req.user);
});
///////////////////////////////////////////////////
router.post('/register', function (req, res, next) {
const { username, email, password } = req.body;
User.register(
new User({ username, email, password }),
req.body.password,
(err, account) => {
if (err) {
res.send({
status: 400,
error: err.message,
data: {
errorName: err.name
}
});
return;
}
passport.authenticate('local')(req, res, function () {
console.log('REG req.user:>>>>', req.user); // defined
res.send({ auth: true })
});
});
})
router.get('/logout', function (req, res) {
console.log('============================================');
console.log('reqUSER', req.user); //undefined
console.log('SESION', req.session.cookie); // passport undefined
req.logout();
res.json({ messageSuccessful: 'Logout successful' });
consol.log(req.user)// null
});
Client:
signUp(user) {
const { cookies } = this.props;
const date = new Date();
date.setDate(date.getDate() + 2000)
axios.post(`${URL}/register`, user).then((result) => {
console.log('RESULT SIGNIN', result);
if (result.data.error) {
this.setState({ error: result.data.error })
}
this.setState({
message: result.data.message,
auth: result.data.auth
})
}
}
)
}
signIn(user) {
const { cookies } = this.props;
const date = new Date();
date.setDate(date.getDate() + 2000);
axios.post(`${URL}/signin`, user).then((result) => {
console.log('RESULT SIGNIN', result);
if (result.data.error) {
this.setState({ loginErrorMessage: result.data.error })
}
this.setState({
loginErrorMessage: '',
modalIsOpen: false,
auth: true
})
}
}
)
};
Help please, I tried to change the settings of sessions, it did not help.
I'm trying to fix for more than a week.
P.S. Checked through the postman, everything works there, deserializeUser is called and req.user defined

The problem was on the client in cors. I hope this helps someone.
Does not work:
axios.post(`${URL}/signin`, user).then((result) => {
//something
})
Working:
const myInit = {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(user),
mode: 'cors',
credentials: "include",
};
fetch(`${URL}/signin`, myInit).then(res => res.json())
.then(res => {
console.log(res)
});

Related

Passport's req.isAuthenticated always returning false with Redis and Express Session

When I do the login "post" I want to be authenticated but req.isAuthenticated is always false, so I can't access home. This problem will not be solved. I don't know what's wrong, any help would be appreciated.
I'm starting to learn backend.
These would basically be the files with which I am working on this part of the project
app.js
const app = express();
app.use(express.json());
app.use(express.urlencoded({
extended: true
}));
app.set("views", "./views");
app.set("view engine", "ejs");
passport.use(
"login",
new LocalStrategy((username, password, done) => {
User.findOne({ username }, (err, user) => {
if (err) return done(err);
if (!user) {
return done(null, false);
}
if (!isValidPassword(user, password)) {
return done(null, false);
}
return done(null, user);
});
})
);
passport.use(
"register",
new LocalStrategy({
passReqToCallback: true
}, (req, username, password, done) => {
User.findOne({
username: username
}, (err, user) => {
if (err) {
return done(err);
}
if (user) {
return done(null, false, {
message: "Usuario ya registrado",
});
}
const newUser = new User({
username: username,
password: createHash(password),
});
User.create(newUser, (err, userWithId) => {
if (err) {
return done(err);
}
return done(null, userWithId);
});
});
})
);
passport.serializeUser((user, done) => {
done(null, user._id);
});
passport.deserializeUser((id, done) => {
User.findById(id, done);
});
app.use(passport.initialize());
app.use(passport.session());
//Redis
const client = redis.createClient({
legacyMode: true,
});
client.connect();
const RedisStore = connectRedis(session);
app.use(
session({
store: new RedisStore({ host: "localhost", port: 6379, client, ttl: 300 }),
secret: "keyboard cat",
resave: false,
saveUninitialized: false,
rolling: true,
cookie: {
maxAge: 86400000,
httpOnly: false,
secure: false,
},
})
);
app.use(homeRouter);
app.use(authWebRoutes);
auth.routes.js
export const authWebRouter = new Router();
authWebRouter.get('/', (req, res) => {
res.redirect('/home')
})
authWebRouter.get("/login", (req, res) => {
if (req.isAuthenticated()) {
res.redirect("/home");
} else {
res.render("login");
}
})
authWebRouter.get("/register", (req, res) => {
if (req.isAuthenticated()) {
res.redirect('/home')
} else {
res.render(path.join(process.cwd(), '/views/register.ejs'))
}
})
authWebRouter.get('/logout', (req, res) => {
req.logout();
res.redirect('/login')
})
authWebRouter.get('/failLogin', (req, res) => {
res.render(path.join(process.cwd(), '/views/failLogin.ejs'))
})
authWebRouter.get('/failRegister', (req, res) => {
res.render(path.join(process.cwd(), '/views/failRegister.ejs'))
})
authWebRouter.post(
"/login",
passport.authenticate("login", {
successRedirect: "/home",
failureRedirect: "/failLogin",
})
);
authWebRouter.post(
"/register",
passport.authenticate("register", {
successRedirect: "/login",
failureRedirect: "/failRegister",
})
);
home.routes.js
export const homeRouter = new Router();
homeRouter.get("/home", checkAuth, (req, res) => {
res.render(path.join(process.cwd(), '/views/home.ejs'), {
username: req.user.username,
})
});
auth.js
export function checkAuth(req, res, next) {
console.log(req.isAuthenticated());
if (req.isAuthenticated()) {
next();
} else {
res.redirect("/login");
}
}

How do I get the email of the user who is logged in?

my problem is that I want to access to the user who is logged in. All users are saved in a database and then SELECTED into a variable.
In the passport-config-js I am checking the login by comparing the email and the hashed password. So I hope you all can help me, I need this for a school project.
severs.js
const express = require('express');
const app = express();
const bcrypt = require('bcrypt');
const passport = require('passport');
const flash = require('express-flash');
const session = require('express-session');
const methodOverride = require('method-override');
const initializePassport = require('./passport-config');
initializePassport(
passport,
email => users.find(user => user["email"] === email),
id => users.find(user => user["id"] === id)
)
const users = [];
app.set('view-engine', 'ejs');
app.use(express.urlencoded({extended: false}))
app.use(flash());
app.use(session({
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(methodOverride('_method'));
app.use(express.static("public"))
app.get('/' , checkAuthenticated,(req, res) => {
res.render('startseite.ejs')
})
app.get('/login', checkNotAuthenticated ,(req, res) =>{
res.render('login.ejs');
})
app.post('/login', checkNotAuthenticated ,passport.authenticate('local',
{
successRedirect: '/startseite',
failureRedirect: '/login',
failureFlash: true
})
)
app.get('/startseite',checkAuthenticated,(req, res) =>{
res.render('startseite.ejs', {email: req.body.email});
console.log(req.body);
})
app.post('/register', checkNotAuthenticated,async (req, res, next) =>{
try {
const hashedPassword = await bcrypt.hash(req.body.password, 10);
let newUser = {
id: Date.now().toString(),
name: req.body.name,
email: req.body.email,
password: hashedPassword
}
if(users.length){
for(let i = 0; i < users.length; i+
if(req.body.email === users[i].email){
console.log(users[i].email + " email already taken");
alert("Email already taken");
res.render('/register');
}
}
}
let sql = `INSERT INTO Players (email, name, password) VALUES ('${newUser.email}', '${newUser.name}', '${newUser.password}')`;
connection.query(sql, (err, result) =>{
if(err) throw err;
console.log("User with email: " + newUser.email + " inserted")
allPlayers();
});
res.redirect('/login');
} catch {
res.redirect('/register');
}
//console.log(users);
})
app.delete('/startseite', (req, res) =>{
req.logOut();
res.redirect('/login');
})
function checkAuthenticated(req, res, next) {
if(req.isAuthenticated()){
return next()
}
res.redirect('/login');
}
function checkNotAuthenticated(req, res, next) {
if(req.isAuthenticated()){
return res.redirect('/');
}
next();
}
function allPlayers(){
let userList = query("*");
userList
.then()
.then((values) =>{
let i = 0;
while(values[i] != null){
users.push(values[i]);
i++;
}
//console.log(users);
})
}
allPlayers();
app.listen(3000);
passport-config.js
const LocalStrategy = require('passport-local').Strategy;
const bcrypt = require('bcrypt');
const {connection, select, query} = require('./db');
function initialize(passport, getUserByEmail, getUserById){
const authenticateUser = async (email, password, done) =>{
const user = getUserByEmail(email);
if(user == null){
return done(null, false, {message: 'email or password incorrect'});
}
try {
if(await bcrypt.compare(password, user.password)) {
return done(null, user);
} else {
return done(null, false, {message: 'email or 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) => {return done(null, getUserById(id))})
}
module.exports = initialize;

oauth20 is working properly but passport local not working

this is my local strategy configuration
const passport = require('passport')
const LocalStrategy = require('passport-local').Strategy
const LocalUsers = require('../db/localUser')
const bcrypt = require('bcrypt')
passport.use(new LocalStrategy({
usernameField: 'email',
passwordField: 'password'
},
(username, password, done) => {
LocalUsers.findOne({ email: username }, async (err, user) => {
if (err) { return done(err); }
if (!user) {
return done(null, false, { message: 'Incorrect email.' });
}
const matchedPassword = await bcrypt.compare(password, user.password)
if (!matchedPassword) {
return done(null, false, { message: 'Incorrect password.' });
}
else{
return done(null, user);
}
});
}
));
passport.serializeUser(function (user, done) {
return done(null, user.id);
});
passport.deserializeUser(async (id, done) => {
await LocalUsers.findById(id, function (err, user) {
done(err, user);
});
});
and this is the server file
require('dotenv').config()
const express = require('express')
const app = express()
const authRoute = require('./routes/auth')
const loginRoute = require('./routes/login')
const homeRoute = require('./routes/home')
const signupRoute = require('./routes/signup')
const passport = require('passport')
const session = require('express-session')
const MongoStore = require('connect-mongo')
require('./db/connection')
require('./config/local-passport-setup')
require('./config/google-passport-setup')
const store = MongoStore.create({ mongoUrl: 'mongodb://localhost:27017/quora', collectionName: 'sessions' })
app.use(express.json())
app.use(express.urlencoded({ extended: false }))
app.use(session({
resave: true,
saveUninitialized: true,
secret:'qwerty',
store: store,
cookie: {
maxAge: 24 * 60 * 60 * 1000
}
}))
app.use(passport.initialize())
app.use(passport.session())
app.set('view engine', 'hbs')
app.use('/', express.static(__dirname + '/public'));
app.get('/', (req, res) => {
if (!req.user) {
res.redirect('/login')
}
else {
res.redirect('/home')
}
})
app.use('/', homeRoute)
app.use('/login', loginRoute)
app.use('/auth', authRoute)
app.use('/', signupRoute)
app.listen(3000, () => {
console.log('server started on http://localhost:3000')
})
here I am calling the passport.authenticate function
onst express = require('express')
const route = express.Router()
const passport = require('passport')
require('../config/local-passport-setup')
route.get('/', (req, res) => {
res.render('login')
})
route.post('/', passport.authenticate('local', { successRedirect: '/home', failureRedirect: '/login' }))
module.exports = route
here the serialize user and deserialize user functions are never being called and thus the req.user is undefined
here the user is not getting authenticated although this oAuth code is working properly
const passport = require('passport')
const GoogleStrategy = require('passport-google-oauth20').Strategy
const GoogleUsers = require('../db/googleUser')
passport.use(new GoogleStrategy(
{
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: 'http://localhost:3000/auth/google/redirect'
},
(accessToken, refreshToken, profile, done) => {
GoogleUsers.findOne({ googleId: profile.id })
.then((currentUser) => {
if (currentUser) {
console.log('current user: ', currentUser)
done(null, currentUser)
}
else {
const newUser = new GoogleUsers({
googleId: profile.id,
name: profile.displayName
})
newUser.save()
.then((newUser) => {
console.log('new user: ', newUser)
done(null, newUser)
})
}
})
}
))
passport.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(async (id, done) => {
await GoogleUsers.findById(id, function (err, user) {
done(err, user);
});
});
Please help me out I have been figuring out the error for a lot time now

How to setCookie session ona brower with React and express backend?

This is my first post on stackoverflow so I apologize in advance if the form of my post is weird. I'm looking to use sessions with express-session to persist a user's connection in a react application. With PostMan, the cookie is saved, the back-end recognizes the user while from my browser which performs a post request with axios I send a (res.send (req.session)))
receives the session, but after another call is not recognized by the server.
My server code:
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const sha1 = require('sha1');
const cors = require('cors');
const path = require('path');
const cookieParser = require('cookie-parser');
const session = require('express-session');
const React = require('react');
const app = express();const MONGOURI = "mongodb+srv://loulou00:loulou00#cluster0.2t92n.mongodb.net/User?retryWrites=true&w=majority";
//connect to mongoose db
mongoose.connect(MONGOURI, {useNewUrlParser: true})
.then(() => console.log('DB CONNECTED'))
.catch(error => console.log(error));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(express.static(path.join(__dirname, '../build')));
app.use(cors({credentials: true, origin: 'http://localhost:1200', exposedHeaders: ["set-cookie"],}));
let sess = {
secret: 'keyboard cat',
cookie: {
maxAge: 60000
},
resave: true,
saveUninitialized: true
}
if (app.get('env') === 'production') {
app.set('trust proxy', 1) // trust first proxy
sess.cookie.secure = true // serve secure cookies
}
app.use(session(sess))
const { Customer } = require('./models/customer');
const { response } = require('express');
//API ROUTE
app.get('/zeb', function (req, res) {
res.send(req.session)
console.log(req.session)
//res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
})
app.post('/api/token_add', (req, res) => {
if (req.body.secret == 'super secret')
{
Customer.findOne({ name: req.body.name }, (err, response) => {
if (!response)
{
const token = sha1(req.body.name)
const customer = new Customer({
name: req.body.name,
pack: req.body.pack,
token: token,
}).save((e, resp) => {
if(e) res.status(400).send(e);
res.status(200).send(resp);
console.log(resp);
})
}
else
{
res.status(400).send('This name is already use')
}
})
}
})
app.post('/api/token_connect', (req, res) => {
Customer.findOne({ token: req.body.token }, (err, response) => {
if(err) res.status(400).send(err)
if (response) {
req.session.token = req.body.token;
res.status(200).send(req.session);
console.log(req.session)
}
else{
res.send('Invalid token')
}
})
});
app.get('/api/token_getinfo', (req, res) => {
console.log(req.session)
Customer.findOne({ token: req.query.token }, (err, response) => {
if(err) res.status(400).send(err)
if (response) {
res.status(200).send(response);
}
else{
res.send('Invalid token')
}
})
})
app.get('/api/token_connectsess', (req, res) => {
console.log(req.session)
Customer.findOne({ token: req.session.token }, (err, response) => {
if(err) res.status(400).send(err)
if (response) {
res.status(200).send(req.session);
}
else{
res.send('Invalid token')
}
})
});
const port = process.env.PORT || 1200;
app.listen(port, () => {
console.log('Server runnin on ' + port)
})
My axios request:
const connect = () => {
axios.post('http://192.168.1.24:1200/api/token_connect', {token: token}
,{
"headers": {
"content-type": "application/json",
}
}).then((res) => {
if (res.data.token)
{
console.log(res.data.token);
setUser(res.data.token) ;
}
})
}
The session :
Session {
cookie: {
path: '/',
_expires: 2020-10-26T22:14:31.294Z,
originalMaxAge: 60000,
httpOnly: true
},
token: 'f7ed376ba27377ae2680fafe1a67037df80b7e36'
}
you need to pass this {withCredentials: true} as an option in your request
For Example:
axios.post(API_SERVER + '/login', { email, password }, { withCredentials: true })

.isAuthenticated() always false || passport local strategy

There are many similar posts to this one, but I haven't found a qualifying solution in any of the answers to those posts that have helped me with this.
the code
"use strict";
require('dotenv').config();
const auth = require('./auth.js');
const express = require('express');
const passport = require('passport');
const bcrypt = require('bcrypt');
const mongo = require('mongodb');
const session = require('express-session');
const cors = require('cors');
const util = require('util');
const app = express();
const port = process.env.PORT || 8080;
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({extended:true}));
app.use(session({
secret: process.env.SESSION_SECRET,
resave: true,
saveUninitialized: true,
cookie: {
secure: false,
maxAge: 1000 * 60 * 60 * 24 * 7
}
}));
app.use(passport.initialize());
app.use(passport.session());
mongo.connect(process.env.DATABASE, {useNewUrlParser: true, useUnifiedTopology: true}, (err, db) => {
if (err) {
console.log('Database error: ' + err);
} else {
console.log('Database connection successful');
auth(app, db);
app.route('/test').get((req, res) => {
res.send('The connection works!')
});
const ensureAuthenticated = (req, res, next) => {
console.log('isAuth() is: ' + req.isAuthenticated());
console.log('session store: ' + util.inspect(req.session, {showHidden: false, depth: null}));
if (req.isAuthenticated()) return next();
res.send('user not authenticated, begone! >:(');
}
app.route('/profile').get(
ensureAuthenticated,
(req, res) => {
res.render({username: req.user.username});
}
);
app.post('/login',
(request, response, next) => {
console.log(request.session)
passport.authenticate('local',
(err, user, info) => {
if(!user){ response.send(info.message);}
else{
request.login(user, function(error) {
if (error) return next(error);
console.log("Request Login supossedly successful.");
return response.send('Login successful');
});
//response.send('Login successful');
}
})(request, response, next);
}
);
app.route('/register').post((req, res, next) => {
const hash = bcrypt.hashSync(req.body.password, 13);
db.db().collection('users').findOne({username: req.body.username}, (err, user) => {
if (err) {
next(err);
} else if (user) {
res.send('user already exists :(');
} else {
db.db().collection('users').insertOne({
username: req.body.username,
password: hash
},
(err, doc) => {
if (err) {
res.send('registration mongo error');
} else {
next(null, user);
}
}
)
}
})
},
passport.authenticate('local', {failureMessage: 'passport authenticate failure'}),
(req, res, next) => {
console.log('registration successful');
req.logIn(req.user, err => {
if (err) next(err)
return console.log("i'm trying: " + req.user);
});
res.send('registration successful!!! :D');
}
);
app.listen(port, () => {console.log(`Listening on port: ${port}`)});
}
});
auth.js
const passport = require('passport');
const LocalStrategy = require('passport-local');
const ObjectID = require('mongodb').ObjectID;
const bcrypt = require('bcrypt');
module.exports = (app, db) => {
passport.use(new LocalStrategy(
(username, password, done) => {
db.db().collection('users').findOne({username: username}, (err, user) => {
console.log(`${username} attempted to log in`);
if (err) return done(err);
if (!user) return done(null, false);
if (!bcrypt.compareSync(password, user.password)) return done(null, false);
console.log('local strategy successful');
return done(null, user);
})
}
));
passport.serializeUser((user, done) => {
console.log(user.username + " serialized");
done(null, user._id);
});
passport.deserializeUser((id, done) => {
db.db().collection('users').findOne(
{_id: new ObjectID(id)},
(err, doc) => {
done(null, doc);
}
);
});
}
The Question:
All of the functions work just fine, I get all of the success return messages, and even register saves the user to the database, and login loads it successfully from the database. The only problem I'm having is that req.isAuthenticated() in the function ensureAuthenticated is always returning false, and as you can see, I really really really need it to be true so I can send the information to the client for the /profile route, and do all the other things I need with Passport. What am I missing?
Solution: I needed to add credentials: true to cors(), and something similar to the http headers (withCredentials:true for axios) in the client. I'm adding this because I know somebody is going to have this same problem one day, and will probably have as hard of a time finding this answer as I did.
Extra: In most forums that I asked this question in, the answers I got were all people not believing that this code works, and patronizing me by telling me I need to re-learn passport and react (if I got an answer at all lmao).

Categories