Logout in ExpressJS, PassportJS and MongoStore - mongodb

Im using PassportJS for authentication and MongoDB for session
In app.js:
app.use(express.session({
store: new MongoStore({
db: mongoose.connection.db
})
}));
For logout:
app.get('/logout', function(req, res){
req.session.destroy(function (err) {
res.redirect('/');
});
});
In logout, do I need to remove session document in mongo?

PassportJS added a logout() function to req.

Related

Passport OAuth2 strategy / facebook strategy is loosing user

I am trying to authorize a pre logged in user with a Facebook account. I want to store the auth token of Facebook to later post stuff using my CMS.
I am using Express/NodeJS and Passport JS.
My FacebookStrategy looks like this:
module.exports = new FacebookStrategy(
{
clientID,
clientSecret,
callbackURL: `${config.apiUrl}/v1/auth/connect/facebook/callback`,
passReqToCallback: true
},
async function(req, token, tokenSecret, profile, done) {
console.log("SESSION?", req.session)
console.log("THIS SHOULD BE SET!", req.user) // But is not!
// Stuff is done.
done(null, token, {savedConnectionForLaterUse});
}
I also have two routes:
router.get('/connect/facebook',
API_KEY_OR_JWT_AUTH_MIDDLEWARE,
(req, res, next) => {
// Save authInfo in session
Object.assign(req.session, {account: req.authInfo.account._id, user: req.user._id})
passport.authorize('facebookConnect', {
failureRedirect: `${frontUrl}/settings/connections`,
scope: facebookOAuthScopes, // This is an array of scopes I need
})(req, res, next)
},
);
router.get('/connect/facebook/callback',
passport.authorize('facebookConnect', {
failureRedirect: `${apiUrl}/v1/auth/connect/facebook/failure`,
}),
(req, res) => {
const { session: {connection} } = req;
res.redirect(`${frontUrl}/settings/connections/edit/${connection}`);
}
);
When I am running this on my local machine it works due to the fact that the session is there and in the session I can find my user for later use. As soon as I am deploying this on a server (with kubernetes) the session is gone.
The configuration of the express session looks like this:
app.use(
expressSession({
secret: config.security.secret,
resave: true,
saveUninitialized: true,
cookie: {
sameSite: 'none', // This was something I tried.. didn't help thou
secure: true,
},
})
)
Can anyone point me into the right direction? What am I doing wrong?
Thank you all for your help in advance. I am really at the end of my knowledge. The struggle is real! :D

Cannot get value of req.user for Passport.js

I spent hours figuring things out why I cannot get the value of req.user when Passport.js serialized a user. But magically, when I deleted the database collection that holds the session, it worked again.
My stack:
Vue.js
Express
Mongoose MongoDb (I store my data on Atlas)
Node.js
I use express-session and connect-mongo to create and save session data and use it to serialize and deserialize user using Passport.js
App.js:
const session = require("express-session");
const passport = require("passport");
const MongoStore = require("connect-mongo")(session);
// Sessions
app.use(
session({
secret: "this is a sample secret",
resave: false,
saveUninitialized: false,
store: new MongoStore({ mongooseConnection: mongoose.connection }),
})
);
//Passport Middleware
app.use(passport.initialize());
app.use(passport.session());
Then I call req.user on a route like this:
router.get("/users", async (req, res) => {
try {
if (req.user) {
res.send(req.user)
} else {
res.send("no-user-found",)
}
} catch (err) {
console.error(err);
}
});
I'm calling /api/users on the front-end with Vue.js and Axios hosted on localhost port 8080. Also, tested on the server itself by calling http://localhost:3000/api/users
Now it works, now that I have deleted the sessions database collection on MongoDb Atlas.
I'm just wondering why this happens? Will it repeat again in the future?

Express session, passport and connect-pg-simple issue in production

This is my first time posting a question up here. I hope you guys can help me out with this. I am fairly new to node.js, express, so sorry in advance for my inexperience.
I am currently having a problem with my authentication session in my node.js, express app. I use Passport.js to handle my authentication, I store the login session with connect-pg-simple (a PostgreSQL session store). After clicking the login button, the session was stored inside my PostgreSQL database, but somehow express couldn't find it. In fact, it stores the session twice in the database, but only one of them got the passport cookie in it.
This issue was not present when the server was still on localhost. It appears when I host my server on Heroku.
Also, whenever I push to heroku repo, it shows this warning:
"connect.session() MemoryStore is not designed for a production environment, as it will leak memory, and will not scale past a single process."
My guess is I didn't connect express session to the PostgreSQL express store properly. Below is my code:
This is how I set up the PostgreSQL database:
const Pool = require("pg").Pool;
const pool = new Pool({
user: process.env.PGUSER,
password: process.env.PGPASSWORD,
host: process.env.PGHOST,
port: process.env.PGPORT,
database: process.env.PGDATABASE
});
module.exports = pool
This is how I set up the session:
const poolSession = new (require('connect-pg-simple')(session))({
pool : pool
})
app.set('trust proxy', 1);
app.use(session({
store: poolSession,
secret: process.env.SESSION_SECRET,
saveUninitialized: true,
resave: false,
cookie: {
secure: true,
maxAge: 30 * 24 * 60 * 60 * 1000
} // 30 days
}));
app.use(passport.initialize());
app.use(passport.session());
This is the image of 2 sessions were store in the database when clicking the login button
https://i.stack.imgur.com/lzAby.png
This is my login route (when click the login button):
router
.route("/signin")
.post((req, res, next) => {
console.log("Signing in...")
passport.authenticate('local', function(err, user, info) {
//code....
req.logIn(user, function(err) {[enter image description here][1]
console.log(user);
if (err) {
console.log(err);
res.send(apiResponse(500, err.message, false, null))
return next(err);
}
console.log(req.sessionID); //The id of the 1st session store in db
console.log(req.isAuthenticated()) //True
res.redirect('/auth');
});
})(req, res, next);
})
This is the route that is redirected to when login successfully:
router.get("/", (req, res) => {
console.log("/ ", req.isAuthenticated()); //False
console.log("/ ", req.sessionID); //The Id of the 2nd session store in db
if(req.isAuthenticated()){
//Notify user login success
}
});
I have been stuck here for a few days now. Please tell me if you need more code!

Connecting Vue to Express - 404 Not Found

I'm creating a simple app to practice connecting Vue to an Express server. I have a form that I'm attempting to send to the back end, but I can't seem to get my data to the back-end.
The error I'm receiving is:
POST http://localhost:8080/login 404 (Not Found)
My best guess is that the method in my Vue can't find a matching route on my server? If so, I'm confused as I have a route for login.
In my Vue script:
const axios = require('axios');
export default {
data: function() {
return {
user: {
email: '',
password: ''
}
}
},
methods: {
sub() {
var user = {
email: this.user.email,
password: this.user.password
}
axios.post('/login', user)
.then(res => console.log(res))
.catch(err => console.log(err))
}
}
}
On by back-end:
const path = require('path');
const express = require('express');
const app = express();
app.use(express.static(path.join(__dirname, '..')));
app.post('/login', function(req, res) {
console.log("Server HIT!!!!!!!!!!!!!!!!!!!!")
})
app.get('*', function (req, res) {
return res.sendFile('../index.html');
});
app.listen(3000);
console.log('Express server listening on port 3000');
Express is running on another port than your vue application. Vue is standard http which is 8080, but express runs on 3000 with this line:
app.listen(3000);
You are sending the request to /login, which from the point of view of your frontend is http://localhost:8080, but that's not where express is available.
Basically all you have to do is send the request to http://localhost:3000/login, simple as that.
By default express do not allow cross origin request i.e CORS. You have to enable it by setting middleware. add below lines in you server file and must be before declaring any routes
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});

Sails.JS + sails-auth + passport-openidconnect

I'm trying to implement passport-openidconnect into my Sails app. I've installed sails-auth, passport, passport-local, passport-http, and passport-openidconnect, all of which are required to start the sails app. I copied the contents of this file to get a passport config since the sails app was already started when I began implementing. This is my config file so far:
module.exports.passport = {
openid_connect: {
name: 'OpenID Connect',
protocol: 'oauth2',
strategy: require('passport-openidconnect').OAuth2Strategy,
options: {
clientID: '',
clientSecret: ''
}
}
};
I based this off some of the default options that were in the config/passport.js file mentioned above.
I've searched for setup examples for the OpenID Connect, but haven't been able to find anything so far. Has anyone implemented this in their own project and could give me some pointers? Thanks!
I've implemented passport in sails, with passport-local, passport for Google/FB/Twitter, but without sails-auth !
I don't know passport-openID but this should be nearly the same.
First you need to add passport middleware like this in your config/http.js
Then you have to create the different strategy in config/passport.js (exemple with FacebookStrategy, it should
var passport = require('passport')
, LocalStrategy = require('passport-local').Strategy
, FacebookStrategy = require('passport-facebook').Strategy
var verifyExtHandler = function (token, tokenSecret, profile, done) {
checkAuthExt(profile, done);
};
var verifyHandler = function (mail, password, done) {
checkAuth(mail, password, done);
};
// Passport session setup.
// To support persistent login sessions, Passport needs to be able to
// serialize users into and deserialize users out of the session. Typically,
// this will be as simple as storing the user ID when serializing, and finding
// the user by ID when deserializing.
passport.serializeUser(function (user, done) {
user.password = null;
done(null, user);
});
passport.deserializeUser(function (user, done) {
done(null, user);
});
// Use the LocalStrategy within Passport.
// Strategies in passport require a `verify` function, which accept
// credentials (in this case, a username and password), and invoke a callback
// with a user object.
passport.use(new LocalStrategy({
usernameField: 'mail',
passwordField: 'password'
}, verifyHandler));
// Remplacer les 'XXXXX' par vos clés et 'yourhost.com' par votre nom de domaine
passport.use(new FacebookStrategy({
clientID: "XXXXXX",
clientSecret: "XXXXXX",
callbackURL: "http://yourhost.com/auth/facebook"
}, verifyExtHandler));
And you need to configure your routes (config/routes.js) :
'/auth/facebook': 'AuthController.facebook',
'/auth/facebook/callback': 'AuthController.facebook'
Then in your controller :
facebook: function (req, res) {
passport.authenticate('facebook', {
failureRedirect: '/auth/login'
}, function (err, user) {
if (err) {
return console.log(err);
}
req.logIn(user, function (err) {
if (err) {
console.log(err);
res.serverError();
return;
}
return res.redirect('/');
});
})(req, res);
}
Hope that helps !