I am implementing a basic login system with passport but I keep receiving this error when I login with the correct credentials:
Express
500 TypeError: Cannot read property 'passport' of undefined
However works fine when I login with wrong credentials by redirecting back to login page. Help?
app.js
//dependencies
var express = require('express');
var routes = require('./routes');
var http = require('http');
var path = require('path');
var mongoose = require('mongoose');
var passport = require('./auth');
var app = express();
server = require('http').createServer(app),
io = require('socket.io').listen(server);
// all environments
app.use(passport.initialize());
app.use(passport.session());
....
app.use(app.router);
app.use(require('less-middleware')({src: path.join(__dirname, 'public')}));
app.use(express.static(path.join(__dirname, 'public')));
......
//routes
app.get('/login', routes.login);
app.post('/login', passport.authenticate('local', {
failureRedirect: '/login',
successRedirect: '/user'
}));
app.get('/user', routes.user);
index.js
exports.login = function(req, res) {
res.render('login', {title: 'Log in'});
};
exports.user = function(req, res) {
if (req.session.passport.user === undefined) {
res.redirect('/login');
} else {
res.render('user', {title: 'Welcome!',
user: req.user
})
}
};
auth.js
var passport = require('passport'),
LocalStrategy = require('passport-local').Strategy;
passport.use(new LocalStrategy(
function(username, password, done) {
if (username === 'admin' && password === 'lynda') {
return done(null, {username: 'admin'});
}
return done(null, false);
}
));
passport.serializeUser(function(user, done) {
done(null, user.username);
});
passport.deserializeUser(function(username, done) {
done(null, {username: username});
});
module.exports = passport;
You're missing the session declaration, so req.session is undefined
app.use( express.cookieParser() );
app.use(express.session({ secret: 'my secret', cookie: { maxAge : 1200000 } }));
also, you seem to be mixing up the requires:
var passport = require('./auth');
I would change this to:
var auth = require('./auth');
to avoid confusion with the passport library
You don't have a session, so you can't do if (req.session.passport.user === undefined) ...
You probably didn't set the session after login
Related
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;
Trying to use passport-saml connecting to ADFS.
The SAML Response is coming back with Successful status codes.
We get the following success code back:
"<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" /></samlp:Status>"
But our Passport IsAuthenicated is always generating a false.
I have listed out all of our files used for this below and would appreciate any help.
server.js file:
const express = require('express');
const http = require('http');
const path = require('path');
const passport = require('passport');
const morgan = require('morgan');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const session = require('express-session');
const errorhandler = require('errorhandler');
var env = process.env.NODE_ENV || 'development';
const config = require('./config/config')[env];
console.log('Using configuration', config);
require('./config/passport')(passport, config);
var app = express();
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(cookieParser());
app.enable('trust proxy'); // add this line
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(session(
{
resave: true,
saveUninitialized: true,
secret: 'default',
proxy: true // add this line
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(morgan('combined'));
function ensureAuthenticated(req, res, next) {
if (//req.isAuthenticated()
true
) {
console.log('req.isAuthenticated = ' + req.isAuthenticated());
return next(); }
else{
console.log('req.isAuthenticated = ' + req.isAuthenticated());
res.redirect('/login');
}
}
app.set('port', config.app.port);
require('./config/routes')(app, config, passport);
//ensure that ensureAuthenticated is in the get function call before master build
//ie app.get('/*', ensureAuthenticated, (req, res)
app.use(express.static(path.join(__dirname, 'public')));
app.get('/*', ensureAuthenticated, (req, res) => {
res.sendFile(path.join(__dirname, 'public/index.html'));
});
app.listen(app.get('port'), function () {
console.log('Express server listening on port ' + app.get('port'));
});
routes.js
module.exports = function (app, config, passport) {
app.get('/', function (req, res) {
res.redirect('/home')
});
app.get('/login',
passport.authenticate(config.passport.strategy,
{
successRedirect: '/',
failureRedirect: '/login'
})
);
app.post('/',
passport.authenticate(config.passport.strategy,
{
failureRedirect: '/',
failureFlash: true
}),
function (req, res) {
res.redirect('/');
}
);
app.get('/logout', function (req, res) {
req.logout();
// TODO: invalidate session on IP
res.redirect('https://redrectsite.com/?wa=signout1.0');
});
};
config.js
module.exports = {
development: {
app: {
name: 'Passport SAML strategy example',
port: process.env.PORT || 80
},
passport: {
strategy: 'saml',
saml: {
callbackUrl: process.env.SAML_CALLBACK_URL || 'https://oursite.com',
entryPoint: process.env.SAML_ENTRY_POINT || 'https://oursite.com/adfs/ls/idpinitiatedsignon',
issuer: process.env.SAML_ISSUER || 'https://oursite.com',
identifierFormat: null,
signatureAlgorithm: 'sha256',
authnContext: 'http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/windows',
disableRequestedAuthnContext: true
//cert: process.env.SAML_CERT || null
}
}
}
};
passport.js
const SamlStrategy = require('passport-saml').Strategy;
module.exports = function (passport, config) {
passport.serializeUser(function (user, done) {
done(null, user);
});
passport.deserializeUser(function (user, done) {
done(null, user);
});
passport.use(new SamlStrategy(
{
callbackUrl: config.passport.saml.callbackUrl,
entryPoint: config.passport.saml.entryPoint,
issuer: config.passport.saml.issuer,
cert: config.passport.saml.cert,
identifierFormat: config.passport.saml.identifierFormat,
signatureAlgorithm: config.passport.saml.signatureAlgorithm,
authnContext: config.passport.saml.authnContext,
disableRequestedAuthnContext: config.passport.saml.disableRequestedAuthnContext
},
function (profile, done) {
return done(null,
{
id: profile.uid,
email: profile.email,
displayName: profile.cn,
firstName: profile.givenName,
lastName: profile.sn
});
})
);
};
I had a similar issue. If you look at what isAuthenticated() does, it's actually just checking a property within the request.session object.
https://github.com/jaredhanson/passport/blob/2327a36e7c005ccc7134ad157b2f258b57aa0912/lib/http/request.js#L86
req.isAuthenticated = function() {
var property = 'user';
if (this._passport && this._passport.instance) {
property = this._passport.instance._userProperty || 'user';
}
return (this[property]) ? true : false;
};
I'm not sure if it's passport or express-session, but once you get to the authentication method, the user object is stored at request.session.passport.user so if you like, you can directly verify that it's non-null instead of using the packaged isAuthenticated() method, which seems to check the wrong path.
My code started working after changing it to the following.
if (_.get(req, 'session.passport.user', null)) {
return next();
}
(lodash _.get for easier null-checking of the nested properties)
When I have all of my code in app.js, authenticating with Google works fine, but I tried breaking out the authentication routes in their own files and now I get a connection refused.
//authRouter.js
const express = require("express");
const authRouter = express.Router();
const SECRETS = require("../config/secrets");
const GoogleStrategy = require("passport-google-oauth").OAuth2Strategy;
const passport = require("passport");
passport.use(new GoogleStrategy(SECRETS.google,
(accessToken, refreshToken, profile, done) => {
return done(null, profile);
})
);
authRouter.get("/google", passport.authenticate('google', { scope: ['openid email profile'] }));
authRouter.get("/google/callback",
passport.authenticate("google",
{
failureRedirect: "/login",
successRedirect: "/"
},
(req, res) => {
res.render("hello world"); //successful auth, redirect home, but res is undefined
})
)
module.exports = authRouter;
//app.js
var authConfig = require('./config/secrets'),
express = require('express'),
passport = require('passport'),
TwitterStrategy = require("passport-google-oauth").OAuth2Strategy,
SECRETS = require("./config/secrets"),
authRoutes = require("./routes/authRoutes");
passport.serializeUser((user, done) => {
done(null, user);
});
passport.deserializeUser((obj, done) => {
done(null, obj);
});
//setup for previously working Google auth
// passport.use(new GoogleStrategy(
// authConfig.google,
// (accessToken, refreshToken, profile, done) => {
// return done(null, profile);
// }
// ));
var app = express();
app.set('view engine', 'hbs');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var session = require('express-session');
app.use(logger('dev'));
app.use(cookieParser());
app.use(session({
secret: 'secret',
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(express.static(__dirname + '/public'));
// Application routes
app.get('/', (req, res) => {
res.render('index', {
user: req.user
});
});
app.get('/login', (req, res) => {
res.render('login', {
user: req.user
});
});
//previously working google auth
// app.get('/auth/google',
// passport.authenticate('google', { scope: ['openid email profile'] }));
// app.get('/auth/google/callback',
// passport.authenticate('google', {
// failureRedirect: '/login'
// }),
// (req, res) => {
// // Authenticated successfully
// res.redirect('/');
// });
//**registering authentication routes
app.use("/auth", authRoutes);
app.get('/account', ensureAuthenticated, (req, res) => {
res.render('account', {
user: req.user
});
});
app.get('/logout', (req, res) => {
req.logout();
res.redirect('/');
});
app.listen(process.env.PORT || 3000, () => {
console.log("Listening...");
});
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next();
}
res.redirect('/login');
}
When I visit the app in a browser where I am logged i to Google, I get a connection refused. I know the credentials are correct, and it's likely some express setup I'm missing. Any thoughts? Thanks in advance.
I'm trying to add user-login module to an existing app in node. It is using separate route files for each module and one main route file to use all the child routes which is ultimately used in server.js
When I try to pass passport instance to the user route, it gives me error as passport is not defined. Here is my app code and structure:
app
views
user
index.ejs
login.ejs
signup.ejs
profile.ejs
routes
docs
index.js
user
index.js
index.js
config
passport.js
server.js
server.js
const express = require('express')
const app = express()
const path = require('path')
const bodyParser = require('body-parser')
const cookieParser = require('cookie-parser')
const passport = require('passport')
const flash = require('connect-flash')
const session = require('express-session')
const routes = require('./routes/')
const port = process.env.PORT || 3000;
app.use(express.static(path.join(__dirname, 'public')));
require('./config/passport')(passport);
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(cookieParser());
app.use(bodyParser.json());
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
app.use(session({ secret: '********' }));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
app.use('/', routes)(app,passport);
const server = app.listen(port, function(){
console.log('Server listening on port '+port);
});
config/passport.js
var LocalStrategy = require('passport-local').Strategy;
const sql = require('mssql')
const bcrypt = require('bcrypt-nodejs')
module.exports = function(passport) {
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function (username, done) {
done(null,username);
});
passport.use('local-signup', new LocalStrategy({
usernameField : 'email',
passwordField : 'password',
passReqToCallback : true
},
function(req, email, password, done) {
process.nextTick(function() {
var strSQL = "SELECT count(id) as uCount FROM <tbl> WHERE username = '"+email+"'";
var cb1 = function(err,recordset){
if(recordset[0].uCount>0){
return done(null, false, req.flash('signupMessage', 'That email is already taken.'));
} else{
var strSQL1 = "INSERT INTO <tbl>(username, password) VALUES('"+email+"','"+generateHash(password)+"')";
var cb2 = function(err,recordset){
return done(null, recordset,req.flash('signupMessage', 'Email registered successfully.'));
};
executeQuery(strSQL1,'INSERTION','<tbl>',cb2);
}
};
executeSelection(strSQL,'SELECTION','<tbl>',cb1);
});
}));
passport.use('local-login', new LocalStrategy({
usernameField : 'email',
passwordField : 'password',
passReqToCallback : true
},
function(req, email, password, done) {
var strSQL = "SELECT a.count, id, username, password FROM <tbl> c , (SELECT COUNT(dbid) count FROM <tbl> b WHERE b.username = '"+email+"' ) a WHERE c.username = '"+email+"'";
var cb1 = function(err,recordset){
if(recordset[0].uCount <= 0){
return done(null, false, req.flash('loginMessage', 'No user found.'));
}
if (!validPassword(password,recordset[0].password))
return done(null, false, req.flash('loginMessage', 'Oops! Wrong password.'));
return done(null, recordset[0]);
};
executeSelection(strSQL,'SELECTION','<tbl>',cb1);
}));
};
executeSelection = function(strSQL, operationType, tableName, cb){
var request = new sql.Request(connection);
request.query(strSQL,function(err,recordset) {
if(err){
logger.error('ERROR in '+operationType+' ON '+tableName+': '+err);
}
logger.info(operationType+' ON '+tableName+' successful!');
cb(err,recordset);
});
};
executeQuery = function(strSQL, operationType, tableName, cb,validateClient) {
var request = new sql.Request(connection);
request.query(strSQL,function(err, recordset) {
if(err){
logger.error('ERROR in '+operationType+' ON '+tableName+': '+err);
}
logger.info(operationType+' ON '+tableName+' successful!');
if(cb){
cb(validateClient);
}
});
};
generatePasswordHash = function(password) {
return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null);
};
validatePassword = function(curPass, dbPass) {
return bcrypt.compareSync(curPass, dbPass);
};
routes/index.js
const mainroute = require('express').Router()
/* ---- other existing routes included ---- */
const r_docs = require('./docs')
const r_user = require('./user') /*my custom route*/
/* ---- all other routes ---- */
mainroute.use('/docs', r_docs);
mainroute.use('/user', r_user)(app, passport); /*my custom route*/
mainroute.get('/', function(req, res){
res.render('home');
});
module.exports = function(app, passport){
mainroute;
}
routes/user/index.js
const express = require('express')
const router = express.Router()
router.get('/', function(req, res) {
res.render('user/index.ejs');
});
router.get('/login', function(req, res) {
res.render('user/login.ejs', { message: req.flash('loginMessage') });
});
// process the login form
router.post('/login', passport.authenticate('local-login', {
successRedirect : '/profile',
failureRedirect : '/login',
failureFlash : true
}));
router.get('/signup', function(req, res) {
res.render('user/signup.ejs', { message: req.flash('signupMessage') });
});
router.post('/signup', passport.authenticate('local-signup', {
successRedirect : '/profile',
failureRedirect : '/signup',
failureFlash : true
}));
router.get('/profile', isLoggedIn, function(req, res) {
res.render('user/profile.ejs', {
user : req.user
});
});
router.get('/logout', function(req, res) {
req.logout();
res.redirect('/');
});
function isLoggedIn(req, res, next) {
if (req.isAuthenticated())
return next();
res.redirect('/');
}
module.exports = function(app, passport) {
router;
}
Please suggest what am I doing wrong here. Thanks
You should wrap your main and user routes to run their logic when you call them and at end return prepared route:
routes/index.js
module.exports = function(app, passport) {
const mainroute = require('express').Router()
/* ---- other existing routes included ---- */
const r_docs = require('./docs');
const r_user = require('./user'); /*my custom route*/
/* ---- all other routes ---- */
mainroute.use('/docs', r_docs);
mainroute.use('/user', r_user)(app, passport); /*my custom route*/
mainroute.get('/', function(req, res) {
res.render('home');
});
return mainroute;
};
routes/user/index.js
module.exports = function(app, passport) {
const express = require('express');
const router = express.Router();
router.get('/', function(req, res) {
res.render('user/index.ejs');
});
router.get('/login', function(req, res) {
res.render('user/login.ejs', {
message: req.flash('loginMessage')
});
});
// process the login form
router.post('/login', passport.authenticate('local-login', {
successRedirect: '/profile',
failureRedirect: '/login',
failureFlash: true
}));
router.get('/signup', function(req, res) {
res.render('user/signup.ejs', {
message: req.flash('signupMessage')
});
});
router.post('/signup', passport.authenticate('local-signup', {
successRedirect: '/profile',
failureRedirect: '/signup',
failureFlash: true
}));
router.get('/profile', isLoggedIn, function(req, res) {
res.render('user/profile.ejs', {
user: req.user
});
});
router.get('/logout', function(req, res) {
req.logout();
res.redirect('/');
});
function isLoggedIn(req, res, next) {
if (req.isAuthenticated())
return next();
res.redirect('/');
}
return router;
};
You need to require it at the top of your user/index.js. Simply:
var passport = require('passport');
Then to make sure the user is authenticated:
router.get('/some/path', isLoggedIn, function(req, res) {
var user = req.user;
});
function isLoggedIn(req, res, next) {
if (req.isAuthenticated())
return next();
res.redirect('/');
}
trying first time node with passport for signing to app and can't get any error in command.
after too much load it responds:
No data received
ERR_EMPTY_RESPONSE
can't find any solution for this error.
routes
loginRouter.route('/login')
.get(loginController.getLogin)
.post(loginController.postLogin);
postlogin function :
var postLogin = function(req, res, next){
passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/auth/login',
failureFlash : true
});
};
passport.js
var passport = require('passport');
var localStrategy = require('passport-local').Strategy;
var bcrypt = require('bcrypt-nodejs');
var User = require('../app/models/model')().User;
module.exports = function(){
passport.use('local',new localStrategy({
usernameField: 'username',
passwordField: 'password',
passReqToCallback : true
},
function (username, password, done){
User.findOne({
where: {
username: username
}
}).then(function(user){
if(!user) {
console.log(user);
done(null, false, req.flash('invalid credentials try again'));
} else if (!bcrypt.compareSync(password, user.password)) {
done(null, false, req.flash('invalid credentials try again'));
} else {
done(null, user);
}
});
}));
passport.serializeUser(function (user,done) {
done(null, user.id);
});
passport.deserializeUser(function (id, done){
User.findOne({where: {id: id}}).then(function(user){
done(null, user);
});
});
};
app.js
var express = require('express'),
session = require('express-session'),
cookieParser = require('cookie-parser'),
bodyParser = require('body-parser'),
passport = require('passport'),
flash = require('express-flash'),
app = express(),
port = 80;
app.use(express.static(__dirname + '/public'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded( { extended: true } ));
app.use(cookieParser());
app.use(session({
secret: 'lirary',
cookie: {
maxage: 1200000
},
resave: true,
saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
require('./config/passport')();
app.set('views','./resources/views');
app.set('view engine','ejs');
require(__dirname + '/app/routes/routes')(app);
app.listen(port,function(err){
console.log('server running on : '+ port)
if (err) {
throw err;
};
});
Just little change in my route and solved this now.
loginRouter.post('/login',
function (req, res, next) {
console.log(User.validate());
next();
},
passport.authenticate('local',{
successRedirect: '/dashboard',
failureRedirect: '/auth/login',
failureFlash : true
}
));