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
Related
I have installed express-session before initializing passport yet the passport authenticate doesn't works and it simply redirects to the failureRedirect url without any errors or messages.
i have checked that passport initializing works perfectly just authentication is not working
my index.js file
const ejs = require("ejs");
const url = require("url");
const session = require("express-session");
const cookieParser = require('cookie-parser')
const flash = require('connect-flash');
const toastr = require('express-toastr');
const Profile = require('./models/Profile.js');
const passport = require("passport");
const { customAlphabet } = require('nanoid');
const express = require("express"),
path = require('path')
const app = express();
const port = 3000;
const { Notyf } = require('notyf')
const { connect } = require('mongoose');
const LocalStrategy = require('passport-local');
const MemoryStore = require("memorystore")(session);
const methodOverride = require('method-override')
connect(process.env.mongodb);
const initializePassport = require('./utils/passport-config.js')
initializePassport(
passport,
email => Profile.find({ email_id: email }),
id => Profile.find({ user_id: email })
)
var bodyParser = require('body-parser');
app.use(cookieParser());
app.use(
session({
store: new MemoryStore({ checkPeriod: 86400000 }),
secret: "##%#&^$^$%#$^$&%#$%##$%$^%&$%^#$%##$%#E%#%#$FEErfgr3g#%GT%536c53cc6%5%tv%4y4hrgrggrgrgf4n",
resave: false,
saveUninitialized: false,
}),
);
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
app.use(toastr());
app.use('/assets', express.static(path.join(__dirname, 'assets')))
app.use('/scripts', express.static(path.join(__dirname, 'node_modules')))
app.set('views', './views');
app.set('view engine', 'ejs');
app.use(bodyParser.json());
app.use(
bodyParser.urlencoded({
extended: true,
}),
);
const checkAuth = (req, res, next) => {
try {
if (req.isAuthenticated()) return next();
req.session.backURL = req.url;
res.redirect("/login");
} catch (e) {
console.log(e)
}
};
app.get('/', async function(req, res){
res.render('index.ejs', { url: req.url })
});
app.get('/login', async function(req, res){
if (req.session.backURL) {
req.session.backURL = req.session.backURL;
} else if (req.headers.referer) {
const parsed = url.parse(req.headers.referer);
if (parsed.hostname === app.locals.domain) {
req.session.backURL = parsed.path;
}
} else {
req.session.backURL = "/";
}
res.render('login.ejs', { url: req.url })
});
app.get('/signup', async function(req, res){
res.render('signup.ejs', { url: req.url })
});
app.get('/newshop', async function(req, res){
res.render('shopcreate.ejs', { url: req.url })
});
app.get('/profile', async function(req, res){
res.render('profile.ejs', { url: req.url })
});
app.get('/settings', async function(req, res){
res.render('settings.ejs', { url: req.url })
});
app.post('/login', passport.authenticate('local', {
failureRedirect: '/login',
}), async (
err,
req,
res,
next,
) => {
try {
await console.log(req)
if (req.session.backURL) {
const backURL = req.session.backURL;
req.session.backURL = null;
res.redirect(backURL);
} else {
res.redirect('/');
}
} catch(e) {
console.log(e)
}
})
app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`));
my passport-config.js file -
const LocalStrategy = require('passport-local').Strategy
const bcrypt = require('bcrypt')
function initialize(passport, getUserByEmail, getUserById) {
const authenticateUser = async (email, password, done) => {
console.log(email)
const user = getUserByEmail(email)
if (user == null) {
return done(null, false, { message: 'User not found' })
}
try {
if (await bcrypt.compare(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) => {
return done(null, getUserById(id))
})
}
module.exports = initialize
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;
the req.isAuthenticated an req.logout seems not to be working and flagged as 'not a function' in my project. here's the code for the project. my verify function seems not to be working as expected.
i've worked other video tutorials aside the paid tutorial i'm watching now on udemy, yet i get the same error on my end or my session's aren't stored.
const http = require("http");
const path = require("path");
const express = require("express");
const helmet = require("helmet");
const passport = require("passport");
const cookieSession = require("cookie-session");
const googleStrategy = require("passport-google-oauth20").Strategy;
require("dotenv").config();
const PORT = 8000;
const G_CONF = {
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: "/auth/google/cb",
};
const CC_CONF = {
name: "session",
maxAge: 60 * 60 * 1000,
keys: [process.env.COOKIE_KEY_00, process.env.COOKIE_KEY_01],
secure: false,
httpOnly: true,
};
const app = express();
const server = http.createServer(app);
function verifyUser(req, res, next) {
const loggedIn = req.user;
console.log(loggedIn);
if (req.user === undefined) {
return res.status(401).json({ error: "you must log in" });
}
next();
}
passport.use(
new googleStrategy(G_CONF, (accessToken, refreshToken, profile, done) => {
done(null, profile);
})
);
// Serializes or push authenticated user to session.
passport.serializeUser((user, done) => {
done(null, user.id);
});
// Deserializes or pull authenticated user from subsequent session request.
passport.deserializeUser((id, done) => {
done(err, user);
});
app.use(helmet());
app.use(cookieSession(CC_CONF));
app.use(passport.initialize());
app.get("/", (req, res) => {
res.status(200).sendFile(path.join(__dirname, "public", "index.html"));
});
app.get(
"/auth/google",
passport.authenticate("google", { scope: ["profile"] })
);
app.get(
"/auth/google/cb",
passport.authenticate("google", {
failureRedirect: "/failed",
successRedirect: "/success",
session: true,
})
);
app.get("/secret", verifyUser, (req, res, next) => {
res.send("secret");
});
app.get("/failed", (req, res) => {
res.sendFile(path.join(__dirname, "public", "failed.html"));
});
app.get("/success", (req, res) => {
res.status(200).sendFile(path.join(__dirname, "public", "success.html"));
});
app.get("/auth/logout", (req, res) => {
req.logout();
res.redirect("/");
});
server.listen(PORT, (err) => {
if (err) {
console.error(err);
}
console.log("Auth Server running on port 8000");
});
i get 'undefined' when i log 'user'
my verify seems not to be working properly
passportjs req.method() isn't working.
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).
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)
});