Passport - Cannot read property 'isAuthenticated' - javascript

I am trying to fix the following error:
/home/ubuntu/workspace/src/util/utils.js:2
if (req.isAuthenticated()) {
^
TypeError: Cannot read property 'isAuthenticated' of undefined
at Object.isLogged (/home/ubuntu/workspace/src/util/utils.js:2:11)
at Object.<anonymous> (/home/ubuntu/workspace/src/routes/index.js:6:23)
I am using passport the following in my app:
require('dotenv').config()
const express = require('express')
//...
const session = require('express-session')
const passport = require('passport')
// configure passport
require('./config/passport')(passport)
const auth = require('./routes/auth')
const index = require('./routes/index')
const app = express()
// ...
app.use(
session({
secret: 'super-mega-hyper-secret',
resave: false,
saveUninitialized: true,
})
)
app.use(passport.initialize())
app.use(passport.session())
app.use((req, res, next) => {
res.locals.currentUser = req.user
next()
})
// routes
app.use('/', auth)
app.use('/', index)
app.listen(port, host, () => {
console.log(`Listening on ${host}:${port}`)
})
module.exports = app
My passport.js file looks like the following:
const passport = require('passport')
const LocalStrategy = require('passport-local').Strategy
const service = require('../service/auth')
module.exports = () => {
passport-serialize-deserialize
passport.serializeUser((user, done) => {
done(null, user.id)
})
passport.deserializeUser(async function(id, done) {
const user = await service.findById(id)
done(null, user)
})
passport.use('local', new LocalStrategy({
usernameField: 'username',
}, async(username, password, done) => {
const user = await service.signin(username, password)
done(null, user)
}))
}
When my / gets called I am using the isLogged() function to control if a login is required:
const express = require('express')
const router = express.Router()
const utils = require('../util/utils')
router.get('/', utils.isLogged(), (req, res) => {
res.render('dashboard')
})
module.exports = router
The definition of the function can be found in my utils.js file, where the error log above is pointing:
function isLogged(req, res, next) {
if (req.isAuthenticated()) {
next()
} else {
res.redirect('/')
}
}
module.exports = {
isLogged,
}
The full code flow can be found in the following repo: passport example
Any suggestions what I am doing wrong?`
I appreciate your replies!

When you run this code:
router.get('/', utils.isLogged(), (req, res) => {
res.render('dashboard')
});
What happens is that utils.isLogged() is being executed, the the result of this execution is registered as a middleware.
Since you try to execute it without any parameters passed, res is passed as undefined and you get your error.
Now, what you really want to do is pass the function itself, not it's execution, so when express will call it (during request processing), it will pass the parameters to it. So your code should look like this:
router.get('/', utils.isLogged, (req, res) => {
res.render('dashboard')
});

Related

req.isAuthenticated is not a function while using Express and passport

in the last few hours I setup a backend express server. It works just fine and now I tryed to implement an authorization with help of a tutorial.
The login works, but when I try to open /authrequired (so basically a future page which needs a logged in user to work) I get the error message: "TypeError: req.isAuthenticated is not a function"
Here is my index.js file:
const express = require('express');
const fs = require('fs');
const http = require('http');
const https = require('https');
const path = require('path');
const uuid = require('uuid').v4;
const session = require('express-session');
const FileStore = require('session-file-store')(session);
const bodyParser = require('body-parser');
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const users = [
{id: '2f24vvg', email: 'test#test.com', password: 'password'}
]
// configure passport.js to use the local strategy
passport.use(new LocalStrategy(
{ usernameField: 'email' },
(email, password, done) => {
console.log('Inside local strategy callback')
// here is where you make a call to the database
// to find the user based on their username or email address
// for now, we'll just pretend we found that it was users[0]
const user = users[0]
if(email === user.email && password === user.password) {
console.log('Local strategy returned true')
return done(null, user)
}
}
));
// tell passport how to serialize the user
passport.serializeUser((user, done) => {
console.log('Inside serializeUser callback. User id is save to the session file store here')
done(null, user.id);
});
passport.deserializeUser((id, done) => {
console.log('Inside deserializeUser callback')
console.log(`The user id passport saved in the session file store is: ${id}`)
const user = users[0].id === id ? users[0] : false;
done(null, user);
});
const app = express();
app.enable('trust proxy')
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.use(session({
genid: (req) => {
console.log('Inside the session middleware')
console.log(req.sessionID)
return uuid() // use UUIDs for session IDs
},
store: new FileStore(),
secret: 'keyboard cat',
resave: false,
saveUninitialized: true
}))
app.use(passport.session());
app.post('/login', (req, res, next) => {
console.log('Inside POST /login callback')
passport.authenticate('local', (err, user, info) => {
console.log('Inside passport.authenticate() callback');
console.log(`req.session.passport: ${JSON.stringify(req.session.passport)}`)
console.log(`req.user: ${JSON.stringify(req.user)}`)
req.login(user, (err) => {
console.log('Inside req.login() callback')
console.log(`req.session.passport: ${JSON.stringify(req.session.passport)}`)
console.log(`req.user: ${JSON.stringify(req.user)}`)
return res.send('You were authenticated & logged in!\n');
})
})(req, res, next);
})
function isAuthenticated (req, res, next) {
if (req.session.user) next()
else next('route')
}
app.get('/authrequired', isAuthenticated, function (req, res) {
res.send('you hit the authentication endpoint\n')
})
app.use(express.static(path.resolve(__dirname, 'build')));
app.use(express.json());
// Redirect from http port to https
http.createServer(function (req, res) {
res.writeHead(301, { "Location": "https://" + req.headers['host'].replace(80,433) + req.url });
console.log("http request, will go to >> ");
console.log("https://" + req.headers['host'].replace(80,433) + req.url );
res.end();
}).listen(80, () => console.info('Listening on port', 80))
//Start https server
https.createServer({
key: fs.readFileSync('./ssl/privkey.key'),
cert: fs.readFileSync('./ssl/cert.cer'),
keepAlive: true
}, app).listen(443, () => console.info('Listening on port', 443));
Anyone got a clue? I saw similar questions on stackoverflow, but nothing worked for me.
There is no such function isAuthenticated. That's why you get the error.
Try replace it with if(req.session.user) {
Or by the example in express-session
// middleware to test if authenticated
function isAuthenticated (req, res, next) {
if (req.session.user) next()
else next('route')
}
app.get('/', isAuthenticated, function (req, res) {
// this is only called when there is an authentication user due to isAuthenticated
res.send('hello, ' + escapeHtml(req.session.user) + '!' +
' Logout')
})
EDIT: You also need to use passport session middleware, by adding
app.use(passport.session());
Make sure it is coming after the session init.

What does this error mean and how would I fix it: throw new TypeError('app.use() requires a middleware function')?

I am trying to create a login page and sign up page, my app.js gives me this error, I think it is the last line of this code. I can send you the other components(files) for this express app. I cannot understand what is causing this error.
const express = require('express');
const mongoose = require('mongoose');
// Routes
const authRoutes = require('./routes/authRoutes');
const app = express();
// middleware
app.use(express.static('public'));
app.use((err, req, res, next) => {
res.locals.error = err;
res.status(err.status);
res.render('error');
});
// view engine
app.set('view engine', 'ejs');
// database connection
const dbURI = '<database, username and password>';
mongoose.connect(dbURI, { useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex:true })
.then((result) => app.listen(3000))
.catch((err) => console.log(err));
// routes
app.get('/', (req, res) => res.render('home'));
app.get('/smoothies', (req, res) => res.render('smoothies'));
app.use(authRoutes);
authRoutes.js
const { Router } = require('express')
const authController = require('./authController.js')
const router = Router();
router.get('/signup', authController.signup_get);
router.get('/signup', authController.signup_post);
router.get('/login', authController.login_get);
router.get('/login', authController.login_post);
module.export = router;
authController.js
module.exports.signup_get = (req, res) => {
res.render('signup');
}
module.exports.login_get = (req, res) => {
res.render('login');
}
module.exports.signup_post = (req, res) => {
res.send('signup');
}
module.exports.login_post = (req, res) => {
res.send('login');
}
You are exporting incorrectly in authRoutes.js.
Change this:
module.export = router;
to this:
module.exports = router;
FYI, a little debugging on your own by simply doing a console.log(authRoutes) should have been able to show you where to look for the problem. If you get an error when you attempt to use authRoutes, you look at what it is and where it came from to see why it's not working. This is basic debugging and there is an expectation that you've done basic debugging before you post your question here.

req.user is unidentified in session (Node, express, session, passport)

For some reason req.user is undefined, and after 4+ hours of trying to figure out why, I'm asking here. I even copy-pasted the server/index.js file of a friend's server, changed the auth strategy so it worked for mine, and I get the same issue.
Everything else is working. It redirects to auth0, comes back to the correct place, either creates a new user in the DB or finds the user. In passport.serializeUser it has all the data I passed along. But when I hit the '/auth/me' endpoint, req.user is undefined.
server/index.js
require('dotenv').config();
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors')
const session = require("express-session");
const passport = require('passport');
const Auth0Strategy = require('passport-auth0');
const massive = require('massive');
const axios = require('axios');
const process = require("process");
const moment = require('moment');
const app = express();
//app.use(express.static(__dirname + './../build'));
app.use(bodyParser.json());
app.use(cors());
app.use(session({
secret: process.env.SECRET,
cookie: { maxAge: 60000 },
resave: false,
saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());
// Use the session middleware
massive(process.env.CONNECTION_STRING)
.then( (db) => {
console.log('Connected to Heroku')
app.set('db', db);
}).catch(err=>console.log(err))
passport.use(new Auth0Strategy({
domain: process.env.AUTH_DOMAIN,
clientID: process.env.AUTH_CLIENT_ID,
clientSecret: process.env.AUTH_CLIENT_SECRET,
callbackURL: process.env.AUTH_CALLBACK
}, (accessToken, refreshToken, extraParams, profile, done) => {
const db = app.get("db");
const userData = profile._json;
db.find_user([userData.identities[0].user_id]).then(user => {
if (user[0]) {
return done(null, user[0]);
} else {
db.create_user([
userData.given_name,
userData.family_name,
userData.email,
userData.identities[0].user_id
])
.then(user => {
return done(null, user);
});
}
});
}))
passport.serializeUser( (user, done) => {
//console.log('serializeuser', user)
done(null, user);
})
passport.deserializeUser( (id, done) => {
app.get("db").find_session_user([id])
.then(user => {
console.log(user);
done(null, user[0]);
});
})
app.get('/auth', passport.authenticate('auth0'));
app.get('/auth/callback', passport.authenticate('auth0', {
successRedirect: process.env.SUCCESS_REDIRECT
}))
app.get('/auth/me', (req, res) => {
console.log('auth/me endpoint hit')
console.log(req.user)
if(!req.user){
return res.status(401).send('No user logged in.');
}
return res.status(200).send(req.user);
})
app.listen(process.env.PORT, () => console.log(`Listening on port: ${process.env.PORT}`));
server/.env
CONNECTION_STRING=postgres:*****
SECRET=*******
AUTH_DOMAIN=****.auth0.com
AUTH_CLIENT_ID=***
AUTH_CLIENT_SECRET=***
AUTH_CALLBACK=http://localhost:8084/auth/callback
SUCCESS_REDIRECT=http://localhost:3000/
PORT=8084
Try moving the app.get('/auth', passport.authenticate('auth0')); line after the app.get('/auth/me', (req, res) => { block. app.get can do regex matches and goes with the first one that matches (http://expressjs.com/en/api.html#path-examples), and I think it's trying to run the /auth logic for the /auth/me path.

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.

Verify callback for local authentication is not executing

The following code works on my friend's computer but not mine. Does anyone know why????
const request = require('supertest')
const express = require('express')
const bodyParser = require('body-parser')
const app = express()
const passport = require('passport')
const LocalStrategy = require('passport-local').Strategy
passport.use(new LocalStrategy(
(username, password, done) => {
console.log('Verify Called')
done()
}
))
app.use(bodyParser())
app.use(passport.initialize())
app.use(passport.session())
app.post('/login', passport.authenticate('local'), (req, res) => {
console.log('Login route hit')
})
const server = app.listen(3000)
describe('Routes', () => {
it('Responses from /login contain a cookie', () => {
request(server)
.post('/login')
.type('form')
.send({username: 'srpalo'})
.send({password: 'secretpassword'})
})
})
Any help would be much appreciated!! I've been stuck on this problem for a whole day now.

Categories

Resources