Hello here I have a server, I am trying to send the user to google auth screen when the path /auth/google is called. But instead I get my 404 screen. I am routing using both express routers and some react routes on the frontend.
Server:
require("dotenv").config();
const express = require("express");
const mongoose = require("mongoose");
var session = require("express-session");
const passport = require("passport");
const path = require("path");
const GoogleStrategy = require("passport-google-oauth20").Strategy;
const app = express();
const port = process.env.PORT || 5000;
app.use(session({
secret: "temp",
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
mongoose.connect("mongodb://localhost:27017/bindrake", {useNewUrlParser: true});
//Models
const User = require("./models/user");
const Key = require("./models/key");
//ROUTES
const userRoute = require("./routes/userRoutes");
passport.use(User.createStrategy());
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
passport.use(new GoogleStrategy({
clientID: process.env.GOOGLE_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: "http://localhost:3000/auth/google/bindrake",
userProfileURL: 'https://www.googleapis.com/oauth2/v3/userinfo'
},
function(accessToken, refreshToken, profile, cb) {
User.findOrCreate({ googleId: profile.id }, function (err, user) {
return cb(err, user);
});
}
));
app.use(express.json());
app.use(express.urlencoded());
app.use("/api", userRoute);
app.get('/auth/google',
passport.authenticate('google', { scope: ['profile'] }));
if (true){
app.use(express.static("./public/build"));
app.get("*", (req, res) => {
res.sendFile(path.resolve(__dirname, "public", "build", "index.html"));
})
}
app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`));
Is there any idea why, please let me know if you need to see more of the code. Maybe I am doing something wrong while routing it?
Ohh okey, it just worked. I just needed to wait after creating the credentials.
Related
I´m trying to use local authentication with passport. According to the passport doc everything seems easy, but for some reason when I call the passport.authenticate the middleware is not running. Just nothing happens.
When I submit the signup form, the post signup function is called.I got the "Received" in my browser, however, I cannot see any console.log that I have in the passport.use callback.
Server:
const express = require('express');
const morgan = require('morgan');
const expressHandleBars = require('express-handlebars');
const path = require('path');
const flash = require('connect-flash');
const session = require('express-session');
const mysqlStore = require('express-mysql-session');
const passport = require('passport');
const { database } = require('./keys');
// Initializations
const app = express();
require('./lib/passport');
// Setting
app.set('port', process.env.PORT || 4000);
app.set('views', path.join(__dirname, 'views'));
app.engine('.hbs', expressHandleBars({
defaultLayout: 'main',
layoutsDir: path.join(app.get('views'), 'layouts'),
partialsDir: path.join(app.get('views'), 'partials'),
extname: '.hbs',
helpers: require('./lib/handlebars')
}));
app.set('view engine', '.hbs')
// Middleware
app.use(session({
secret: 'whatever',
resave: false,
saveUninitialized: false,
store: new mysqlStore(database)
}));
app.use(morgan('dev'));
app.use(express.urlencoded({extended: false}));
app.use(express.json());
app.use(flash());
app.use(passport.initialize());
app.use(passport.session());
// Global variables
app.use((req, res, next) => {
app.locals.success = req.flash('success');
next();
});
// Routes
app.use(require('./routes'));
app.use(require('./routes/authentication'));
app.use('/links', require('./routes/links'));
// Public
app.use(express.static(path.join('__dirname', 'public')));
// Starting the server
app.listen(app.get('port'), () => {
console.log('Server on port', app.get('port'));
});
Passport config file (lib/passport.js):
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const pool = require('../database');
const helpers = require('./helpers');
passport.use('local-signup', new LocalStrategy({
usernameField: 'username',
passwordField: 'password',
passReqToCallback: true
}, async function(req, username, password, done) {
console.log("Authenticated!!");
console.log(req.body);
}
));
Router calling authenticate (routes/authenticate.js):
const express = require('express');
const passport = require('passport');
const router = express.Router();
router.get('/signup', (req, res) => {
res.render('auth/signup');
});
router.post('/signup', (req, res) => {
passport.authenticate('local-signup', {
successRedirect: '/profile',
failureRedirect: '/signupFailure',
failureFlash: true
}, (req, res) => {
res.send("Authenticating");
});
//console.log(req.body);
res.send('Received');
});
router.get('/profile', (req, res) => {
res.send('This is your profile');
});
module.exports = router;
Passport.authenticate() returns a middleware function, you're not calling it.
passport.authenticate('local-signup', {
successRedirect: '/profile',
failureRedirect: '/signupFailure',
failureFlash: true
}, (req, res) => {
res.send("Authenticating");
})(req, res)
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)
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.
In my Node app I am using Passport.js Facebook Strategy. I have successfully deplayed my app on heroku and also have made my app public. But only if I login it works. If someone else logs in it promts Internal Server Error.
To check, I checked my mlab database but no data of the logged in user displays.
app.js
const express = require('express');
const exphbs = require('express-handlebars');
const mongoose = require('mongoose');
const passport = require('passport');
const session = require('express-session');
const methodOverride = require('method-override');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
var path = require("path");
// var path = require("path");
//jade
// const jade = require('jade');
//Load Models
require('./models/User');
require('./models/Story');
//Passport config
require('./config/passport')(passport);
//Load Routes
const index = require('./routes/index');
const auth = require('./routes/auth');
const stories = require('./routes/stories');
//Load Keys
const keys = require('./config/keys');
//handlebars helpers
const {
truncate,
stripTags,
formatDate,
select,
editIcon
} = require('./helpers/hbs');
//Load Global Promise
mongoose.Promise = global.Promise;
//Mongoose Connect
mongoose.connect(keys.mongoURI,{
useMongoClient: true,
})
.then(()=>console.log('MongoDB Connected............'))
.catch(err => console.log(err))
const app = express();
// body-parser middleware
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.use(express.static(path.join(__dirname, '/public')));
app.engine('handlebars', exphbs({
helpers: {
truncate: truncate,
stripTags: stripTags,
formatDate: formatDate,
select: select,
editIcon: editIcon
},
defaultLayout: 'main'
}));
app.set('view engine', 'handlebars');
// app.use(express.static(path.join(__dirname, '/public')));
// app.set('view engine', 'jade');
//Session n cookieParser Middleware
app.use(cookieParser());
app.use(session({
secret: 'secrethaibc',
resave: true,
saveUninitialized: true,
// cookie: {secure: true} //if using https only
cookie: {maxAge: 5*60*60*1000 }, //5 hours of inactivity
rolling: true
}));
//Passport Middleware
app.use(passport.initialize());
app.use(passport.session());
//method-override Middleware
app.use(methodOverride('_method'));
//Set Global vars
app.use((req,res,next) => {
res.locals.user = req.user || null;
next();
});
//Use routes
app.use('/',index);
app.use('/auth',auth);
app.use('/stories',stories);
const port = process.env.PORT || 9000; //process.env.PORT for production port
app.listen(port,()=>console.log(`Server set at ${port}`));
passport.js
const FacebookStrategy = require('passport-facebook').Strategy;
const mongoose = require('mongoose');
const keys = require('./keys');
//Load User model
const User = mongoose.model('users');
module.exports = function(passport){
//FacebookStrategy
passport.use(new FacebookStrategy({
clientID: keys.facebookAppID,
clientSecret: keys.facebookAppSecret,
callbackURL: '/auth/facebook/callback',
profileFields: ['id','displayName','photos','emails'], //did long method could have used 'name'
proxy: true //not sure about this
}, (accessToken, refreshToken, profile, done)=>{
// console.log(accessToken);
// console.log(profile);
const image = `https://graph.facebook.com/${profile.id}/picture?`;
// console.log(image);
const name = profile.displayName.split(' ');
const newUser ={
ID: profile.id,
firstName: name[0],
lastName: name[1],
// firstName: profile.displayName.value.substring(0, profile.displayName.value.indexOf(' ')),
// lastName: profile.displayName.value.substring(profile.displayName.value.indexOf(' '+ 1),),
email: profile.emails[0].value,
image: image
}
// console.log(newUser); for debugging
//Check for existing user
User.findOne({
ID: profile.id
})
.then(user => {
if(user){
//Return User
done(null,user);
}
else{
//Create User
new User(newUser)
.save()
.then(user => done(null,user));
}
})
})
);
//Serialize and Deserialize User
passport.serializeUser((user,done)=>{
done(null,user.id);
});
passport.deserializeUser((id,done)=>{
User.findById(id, (err,user)=>{
done(err,user);
});
});
}
auth.js
const express = require('express');
const router = express.Router();
const passport = require('passport');
//Google Authentication
router.get('/google',
passport.authenticate('google',{scope: ['profile','email'] }));
router.get('/google/callback',
passport.authenticate('google',{ failureRedirect: '/'}),(req,res)=>{
// Successful authentication, redirect home.
res.redirect('/dashboard')
});
//Facebook Authentication
router.get('/facebook',
passport.authenticate('facebook'));
router.get('/facebook/callback',
passport.authenticate('facebook',{failureRedirect:'/'}),(req,res)=>{
// Successful authentication, redirect home.
res.redirect('/dashboard');
});
router.get('/verify',(req,res)=>{
if(req.user){
console.log(req.user);
} else {
console.log('!!!!!!!! Not Auth !!!!!!!!!');
}
});
router.get('/logout',(req,res)=>{
req.logout();
res.redirect('/');
});
module.exports = router;
If you want to try login: App URL
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.