req.flash is not a function express passport - javascript

I am trying to authenticate the user using passport.I am trying to display message using flash.In the passport-config.js,I wrote the local strategy.When I run the code ,it give an error "req.flash is not a function " in passport-config.js file.This the first time I am using passport and flash.Please help me.Thanks in advance.
app.js
const express = require("express");
const bodyParser = require("body-parser");
const ejs = require("ejs");
const passport = require("passport");
const initializePassport=require('./passport-config')(passport);
const auth=require('./authenticate');
const bcrypt=require('bcrypt');
const session = require('express-session');
const flash = require('express-flash');
const Post=require("./Post");
const User=require('./User');
const app = express();
app.set('view engine', 'ejs');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(express.static("public"));
app.use(session({
secret:"secret",
resave:false, //this means session variables are not resaved if nothing is changed
saveUninitialized:false //this means we dont want to save empty value in session if there is no value
}))
app.use(flash());
app.use(passport.initialize());
app.use(passport.session());
app.use(function(req, res, next) {
// make all error and success flash messages available from all templates
res.locals.error = req.flash("error")
res.locals.success = req.flash("success")
next()
})
app.get("/login",function(req,res){
res.render('login');
})
app.post("/login",passport.authenticate('local',{
successRedirect:'/',
failureRedirect:'/login',
failureFlash:true
}))
passport-config.js
const LocalStrategy = require('passport-local').Strategy;
const mongoose=require('mongoose');
const bcrypt = require('bcrypt');
const User=require('./User');
function initialize(passport) {
const authenticateUser =(req,email, password, done) => {
User.findOne({email:email}).then(user=>{
if(!user){
// req.flash('error','This email is not registered');
return done(null,false,req.flash('error','This email is not registered'));
}
//Match password
bcrypt.compare(password,user.password,(err,isMatch)=>{
if(err){
// req.flash('error','Something went wrong!Please try again.');
throw err;
}
if(isMatch){
return done(null,user);
}
else{
req.flash('error','Password Incorrect');
return done(null,false, req.flash('error','Password Incorrect'));
}
});
}).catch(err=> console.log(err));
}
passport.use(new LocalStrategy({ usernameField: 'email' ,passReqToCallBack: true}, authenticateUser));
passport.serializeUser((user, done) => done(null, user.id));
passport.deserializeUser((id, done) => {
User.findById(id,(err,user)=>{
done(err,user);
})
})
}
module.exports = initialize;

Try putting passport before the flash
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());

passport.use(new LocalStrategy({ usernameField: 'email' , passReqToCallback : true}, authenticateUser));
I just had to add passReqToCallback : true.It works now.

Related

Passport session doesn't retain after post

I'm new to Node.js app, and I writing authentication by passport. I can login and authentication routine works fine. However, after post, isAuthenticated() return false and redirect to index page. It seems like the user session is gone after doing post.
Could anybody tell me how to fix it? Here's my code.
app.js
var createError = require('http-errors');
var express = require('express');
const expressLayouts = require('express-ejs-layouts');
var path = require('path');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
var flash = require('connect-flash');
const session = require('express-session')
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy
var manageRouter = require('./routes/manage');
var app = express();
app.use(fileUpload());
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('tiny'));
app.use(expressLayouts);
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(express.static('public'));
app.use(flash());
app.use(cookieParser('remote_teach'));
app.use(bodyParser.json());
app.use(session({
secret: "remote_teach",
resave: true,
saveUninitialized: true,
cookie: {maxAge: 60 * 60 * 24 * 1000}
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(function(req, res, next){
if (req.user && req.isAuthenticated()) {
res.locals["login"] = true;
}
return next();
});
app.use('/manage', manageRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
console.log("404");
next(createError(404));
});
module.exports = app;
route/manage.js
var express = require('express');
var router = express.Router();
var file_system = require('file-system');
var fs = require('fs');
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const bcrypt = require('bcryptjs');
var md5 = require('md5');
const { encrypt, decrypt, randomString } = require('../crypto');
const db_configure = require('../configure');
var rootDirectory = 'public/data/';
// 資料庫
var mysql = require('mysql');
var connection = mysql.createConnection({
host : db_configure.db_host,
port : db_configure.db_port,
user : db_configure.db_user,
password : db_configure.db_pwd,
database : db_configure.db_name
});
// 顯示登入頁面
router.get('/login', function(req, res, next){
if (req.isAuthenticated()) {
res.redirect('/manage/index');
}else{
res.render('manage/login');
}
});
// Passport JS 登入驗證
passport.use(new LocalStrategy(
{
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
},
// Verify Callback
function(req, email, passwd, done) {
//verrify if the user is existed
})
);
passport.serializeUser(function(user, done) {
done(null, user.user_id)
});
passport.deserializeUser(function(id, done) {
//select user and deserialize
done(null, user);
});
router.post('/login', passport.authenticate('local', { successRedirect: '/manage',
failureRedirect: '/',
failureFlash: true})
);
router.post('/user/create', isAuthenticated, function(req, res, next){
var name = req.body.name;
var email = req.body.email;
var password = md5(req.body.password);
connection.query('INSERT INTO users (name, email, password) VALUES (?, ?, ?)',[name, email, password], function (error, results, fields){
if (error){
console.log(error);
}
res.redirect('/manage/users');
});
});
function isAuthenticated(req, res, next) {
if (req.user && req.isAuthenticated()) {
return next();
}
return res.redirect('/');
}
module.exports = router;

Cannot read property 'name' of undefined in nodejs using passport

I'm makking login system in node js whem I try to get user detail after logged in in log it says undefined
here is app.js
const express = require('express');
const session = require('express-session');
const mongoose = require('mongoose');
const passport = require('passport');
const bodyParser = require('body-parser');
const app = express();
//Passport Config
require('./config/passport')(passport);
//DB config
const db= require('./config/key').dbURI;
//Connect to mongodb
mongoose.connect(db,{ useNewUrlParser: true})
.then(() => console.log('MongoDB Connected...'))
.catch(err => console.log(err));
//ejs
app.set('view engine','ejs');
//Bodyparser
app.use(bodyParser.json());
app.use(express.urlencoded({ extended: false }));
//Express session
app.use(session({
secret: 'secret key',
resave: true,
saveUninitialized: true
}));
//passport middleware
app.use(passport.initialize());
app.use(passport.session());
//Routes
app.use('/', require('./routes/index'));
app.use('/users', require('./routes/users'));
app.listen(3000,console.log("Server started on 3000"));
here is my login system
router.post('/login', (req,res,next) => {
passport.authenticate('local',{
successRedirect: '/dashboard',
failureRedirect: '/users/login',
failureFlash: true
})(req,res,next);
});
here is my dashboard redirection code
route.get('/dashboard',ensureAuthenticated,(req,res) => {
console.log(req.admin);
res.render('dashboard', { admin : req.admin });
});
in this console.log(req.admin); it says undefined in log
here is passport config
const LocalStrategy = require('passport-local').Strategy;
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
const passport = require('passport');
//Load user model
const User = require('../models/admin');
module.exports=function(passport){
passport.use(
new LocalStrategy({ usernameField: 'email' }, (email,password,done) => {
//Check if user is available or not
User.findOne({ email: email })
.then(user => {
if(!user){
return done(null, false, console.log('That email is not registerd'));
}
//match password
bcrypt.compare(password, user.password, (err, isMatch) => {
if(err) throw err;
if(isMatch){
return done(null, user);
}else{
return done(null, false, console.log('Password Incorrect'));
}
});
})
.catch(err => console.log(err));
})
);
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => {
done(err, user);
});
});
}
here is the code of auth.js
module.exports = {
ensureAuthenticated: function(req,res,next){
if(req.isAuthenticated()){
return next();
}
console.log('Please log in to view this resourse');
res.redirect('/users/login');
}
}
and in dashboard.ejs i'm using <%= admin.name %> and it gives error
Cannot read property 'name' of undefined
I don't know what's the matter here or what's i'm missing here
After successful authentication in passport.js, usedetails are assigned to "user" object in request through a passport middleware.
so you can access it using "req.user".
error
Include the new keyword while initializing the Strategy.
solution

Node js logout instruction isn't running in a serial way

eI'm using:
framework: express
template engine :handlebars
authentification: passport / passport-local
So login process goes well, but in logout i have a problem:
//routes/users.js
//logout
router.get("/logout",(req,res)=>{
req.logout();
req.flash("success_msg","You are logged out");
console.log(req.user);
res.render("users/login");
});
//views/users/login.js
{{user}}
//app.js:
// Setting Global variables:
app.use(function(req,res,next){
res.locals.success_msg = req.flash("success_msg");
res.locals.error_msg = req.flash("error_msg");
res.locals.error = req.flash("error");
res.locals.user = req.user || null;
next();
});
So the probleme is that when i clic on logout, i'm redirected to login view but the user object still there(not null),and when I refresh the user is initialised to null,
So my problem why the user haven't been set to null before refirection ?
Full files codes :(app.js, routes/users.js, /config/passport.js)
* app.js
const express = require('express');
const methodOverride = require('method-override');
const mongoose = require('mongoose');
const exphbs = require('express-handlebars');
const bodyParser = require('body-parser');
const flash = require('connect-flash');
const session = require('express-session');
//const path = require("path");
const passport = require('passport');
const app=express();
// load routes :
const ideas = require("./routes/ideas");
const users = require("./routes/users");
//---------------Mongoose Connect-----------------------
//Map global promise = get rid of warning
mongoose.Promise = global.Promise;
//Connect to mongoose
mongoose.connect('mongodb://localhost/vidjot-db',{
useMongoClient: true
})
.then(function(){
console.log("MongoDB connected ...");
})
.catch(err => console.log(err));
//----------------Middlewares set in Use-----------------
// Static folder Set:
//app.use(express.static(path.join(__dirname,'public')));
app.use(express.static('public'));
// Session middleware :
app.use(session({
secret: 'mySecret',
resave: true,
saveUninitialized: true,
//cookie: { secure: true }
}));
// passport middleware :
app.use(passport.initialize());
app.use(passport.session());
// handlebars middleware :
app.engine('handlebars', exphbs({defaultLayout: 'main'}));
app.set('view engine', 'handlebars');
// body parser middleware :
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }));
// parse application/json
app.use(bodyParser.json());
//methodOverride middleware:
app.use(methodOverride('_method'));
//Connect flash middleware:
app.use(flash());
//----------------My Own Middlewares-----------------
// Setting Global variables:
app.use(function(req,res,next){
res.locals.success_msg = req.flash("success_msg");
res.locals.error_msg = req.flash("error_msg");
res.locals.error = req.flash("error");
console.log("res.locals.user");
res.locals.user = req.user || null;
next();
});
/* app.use(function(req,res,next){
console.log("3ale rou7i");
console.log(Date.now());
req.att_x="karim";
next();
}) */
app.use(function(req,res,next){
console.log("hani ne5dem");
next();
});
//-----------------Routes-----------------------------
// Index Route:
app.get("/",(req,res) => {
res.render('index');
//console.log("get callback");
});
// about Route:
app.get("/about",(req,res)=>{
res.render("about",{title:"about1"});
});
// Use routes :
app.use("/ideas",ideas);
app.use("/users",users);
//--------------------------------------------------
//call local-strategy:
require("./config/passport")(passport);
//--------------------------------------------------
const port=5000;
app.listen(port,()=>{
console.log(`server started on port ${port}`);
});
* routes/users.js:
const express = require("express");
const mongoose = require("mongoose");
const bcrypt = require('bcryptjs');
const passport = require("passport");
const router = express.Router();
//--------------------------------------------------
// Load User Model:
require('../models/User');
const User = mongoose.model('Users');
//--------------------------------------------------
//login form
router.get("/login",(req,res)=>{
res.render("users/login");
});
//handle login form:
router.post('/login',
passport.authenticate('local', {
successRedirect: '/ideas',
failureRedirect: '/users/login',
failureFlash:true,
})
);
//logout
router.get("/logout",(req,res)=>{
req.logout();
req.flash("success_msg","You are logged out");
console.log("routes users",req.user);
res.render("users/login");
});
//register form
router.get("/register",(req,res)=>{
res.render("users/register");
});
// handle register form
router.post("/register",(req,res)=>{
let errors=[];
if(req.body.password != req.body.password2)
errors.push({"text":"password do not match"});
if(req.body.password.length < 4)
errors.push({"text":"password must be at least 8 characters"});
if(errors.length > 0)
res.render("users/register",{
errors:errors,
name:req.body.name,
email:req.body.email,
});
else{
User.findOne({email:req.body.email})
.then(user=>{
if(user){
req.flash("error_msg","email already registred");
res.render("/users/login");
}else{
const newUser = new User({
name:req.body.name,
email:req.body.email,
password:req.body.password,
date:req.body.date,
});
bcrypt.hash(newUser.password, 10, function(err, hash) {
if (err) throw err;
newUser.password=hash;
newUser
.save()
.then(user=>{
req.flash("success_msg","You are registered, You can connect Now");
res.redirect("/users/login");
}).catch(err=>{
console.log(err);
return;
});
});
}
})
}
});
//--------------------------------------------------
module.exports = router;
* config/passport.js :
const mongoose = require('mongoose');
const bcrypt = require("bcryptjs");
const LocalStrategy = require("passport-local").Strategy;
const passport = require("passport");
//-------------------------------------------------------
// Load User Model:
require('../models/User');
const User = mongoose.model('Users');
//-------------------------------------------------------
module.exports=function(passport){
passport.use(
new LocalStrategy({usernameField:'email'},function(email, password, done){
User.findOne({'email':email},function(err, user) {
if (err)
return done(err);
if (!user)
return done(null, false,{message:"You are not registred"});
if (!bcrypt.compareSync(password,user.password) ){
return done(null, false,{message:"Missing email or password !"});
}
return done(null, user);
});
}));
passport.serializeUser(function(user, done) {
console.log("SERIALIZE");
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
console.log("DESERIALIZE");
User.findById(id, function(err, user) {
done(err, user);
});
});
}
You have middleware that set res.locals based on a logged in user for every request.
Your res.render() template uses that res.locals data when rendering the page.
When you call req.logout(), nobody clears the res.locals that were already set when the user was still logged in so res.locals.user is now inaccurate.
So, when res.render() gets called after the logout, res.locals are still set as if the user is logged in and thus the page renders that way.
A simple solution is to clear the locals when you logout so they don't wrongly indicate the user is still logged in:
//routes/users.js
//logout
router.get("/logout",(req,res)=>{
req.logout();
// clear user before rendering to indicate logged out
res.locals.user = null;
req.flash("success_msg","You are logged out");
console.log(req.user);
res.render("users/login");
});

Can't get Passport.js to work with Google OAuth 2.0

I'm trying to add the ability to Login/Register with Google to my app. I tried using Passport to create that functionality, but I'm getting this error:
Error: Failed to serialize user into session.
I tried using express-session and cookie-session, but I'm still getting the same error.
This is my app.js:
const express = require('express');
const app = express();
const mongoose = require('mongoose');
const keys = require('./config/keys');
const expressSession = require('express-session');
const cookieParser = require('cookie-parser');
const passport = require('passport');
// Set Mongoose Promise Library To Default
mongoose.Promise = global.Promise;
// Connect To The Database
mongoose.connect(keys.mongodb.dbURI, {useMongoClient: true})
.catch(err => console.log(err));
// -------------------------//
// Middlewares //
// -------------------------//
// Set View Engine To Pug
app.set('view engine', 'pug');
// Cookie Parser Middleware
app.use(cookieParser());
// Express-Session Config & Middleware
app.use(expressSession({
secret: keys.session.cookieKey,
resave: false,
saveUninitialized: true,
cookie: {
maxAge: 60000
}
}));
// Passport Middlewares
app.use(passport.initialize());
app.use(passport.session());
// Serve Static Assets
app.use(express.static('public'));
// -------------------------//
// Routes //
// -------------------------//
app.get('/', (req, res) => {
res.render('home');
});
const authRoutes = require('./routes/auth');
app.use('/auth', authRoutes);
// -------------------------//
// Initalize //
// -------------------------//
const portNum = 5000;
app.listen(portNum, () => console.log(`Started On Port ${portNum}`));
And this is the Passport-setup (Strategy):
'use strict';
const passport = require('passport');
const GoogleStrategy = require('passport-google-oauth20').Strategy;
const keys = require('./keys');
const User = require('../models/user');
passport.use(
new GoogleStrategy({
clientID: keys.google.clientID,
clientSecret: keys.google.clientSecret,
callbackURL: '/auth/google/redirect'
}, (accessToken, refreshToken, userInfo, done) => {
User.find({googleId: userInfo.id}).then(foundUser => {
if (!foundUser) {
new User({
userName: userInfo.displayName,
googleId: userInfo.id
})
.save().then(createdUser => done(null, createdUser))
.catch(err => console.log(err));
} else {
done(null, foundUser);
}
})
.catch(err => console.log(err));
})
);
passport.serializeUser((user, done) => {
done(null, user.id)
});
passport.deserializeUser((id, done) => {
User.findById(id).then(foundUser => done(null, foundUser))
.catch(err => console.log(err));
});
Thanks.
You need to have an if statement in deserializeUser checking that a user with id actually exists. Otherwise you will be deserializing and thus serializing a user that does not exist. In deserializeUser, try adding a DB lookup for the user and then if that user does not exist, call done(null, false).
The issue was that I used User.find() instead of User.findOne(). User.find() returns an array with an object rather than the object itself.

"Router.use() requires a middleware function but got a undefined" error while using express and Passport.js

I am setting up my backend, but keep getting the "Router.use() requires a middleware function but got a undefined" error. Here is my code:
const express = require('express');
const session = require('express-session');
const MongoStore = require('connect-mongo')(session);
const path = require('path');
const logger = require('morgan');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const passport = require('passport');
const LocalStrategy = require('passport-local');
const mongoose = require('mongoose');
var REQUIRED_ENV = "SECRET MONGODB_URI".split(" ");
REQUIRED_ENV.forEach(el => {
if (!process.env[el]) {
console.error("Missing required env var " + el);
process.exit(1);
}
});
mongoose.connect(process.env.MONGODB_URI);
const User = require('./backend/models').User;
const routes = require('./backend/routes/routes');
const auth = require('./backend/routes/auth');
const app = express();
app.use(logger('tiny'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(session({
secret: process.env.SECRET,
store: new MongoStore({ mongooseConnection: mongoose.connection })
}));
app.use(passport.initialize());
app.use(passport.session());
passport.serializeUser((user, done) => {
done(null, user._id);
});
passport.deserializeUser((id, done) => {
User.findById(id).exec((err, user) => {
done(err, user);
});
});
passport.use(new LocalStrategy((username, password, done) => {
User.findOne({ username: username }, (err, user) => {
// if there's an error, finish trying to authenticate (auth failed)
if (err) {
console.error('Error fetching user in LocalStrategy', err);
return done(err);
}
// if no user present, auth failed
if (!user) {
// return done(null, false, { message: 'Incorrect username.' });
return done(null, false);
}
// if passwords do not match, auth failed
if (user.password !== password) {
// return done(null, false, { message: 'Incorrect password.' });
return done(null, false);
}
// username and password match! auth has has succeeded
return done(null, user);
});
}));
app.use('/', auth(passport));
app.use('/', routes);
const PORT = process.env.PORT || 3000;
app.listen(PORT, error => {
error
? console.error(error)
: console.info(`==> 🌎 Listening on port ${PORT}. Visit http://localhost:${PORT}/ in your browser.`);
});
The error points to the app.use(session({secret: process.env.SECRET... line but when I take that away it still produces the error but this time does not cite a specific line in the error message. I can show you my routes.js and auth.js files if you want but I don't think that is causing the problem.
Thanks so much!

Categories

Resources