how to delete cookie on logout in express + passport js? - javascript

I want to "delete cookies on logout". I am not able to do that. I googled for answer and found following ways:
Assign new date of expiration to cookie
res.cookie('connect.sid', '', {expires: new Date(1), path: '/' });
Delete cookie using below lines
res.clearCookie('connect.sid', { path: '/' });
I tried both ways individually but they do not delete the cookie.
Here is my code:
routes.js
module.exports = function(app, passport, session){
app.get('/', function(req, res)
{
res.render('index.ejs');
});
app.get('/login', function(req,res){
res.render('login.ejs',{message:req.flash('loginMessage')});
});
app.get('/signup',checkRedirect , function(req, res) {
res.render('signup.ejs',{message: req.flash('signupMessage')});
});
app.get('/profile', isLoggedIn, function(req,res) {
res.render('profile.ejs', {
user :req.user
});
});
app.post('/signup', passport.authenticate('local-signup', {
successRedirect : '/profile',
failureRedirect : '/signup',
failureFlash : true
}));
app.post('/login', passport.authenticate('local-login', {
successRedirect : '/profile',
failureRedirect : '/login',
failureFlash :true
}));
app.get('/logout',function(req,res){
res.cookie('connect.sid', '', {expires: new Date(1), path: '/' });
req.logOut();
res.clearCookie('connect.sid', { path: '/' });
res.redirect('/');
});
function isLoggedIn(req, res, next){
if(req.isAuthenticated())
return next();
console.log("hiii");
res.redirect('/');
}
};
server.js
var express = require('express');
var app = express();
var port = process.env.PORT || 3000;
var mongoose = require('mongoose');
var passport = require('passport');
var flash=require('connect-flash');
var morgan=require('morgan');
var bodyParser = require('body-parser');
var cookieParser=require('cookie-parser');
//
var session=require('express-session');
var RedisStore = require('connect-redis')(session);
var redis = require("redis");
var redis_client = redis.createClient();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
var configDb=require('./config/database.js');
mongoose.connect(configDb.url);
require('./config/passport')(passport);
app.use(morgan('dev'));
app.use(cookieParser());
app.use(bodyParser());
app.set('view engine', 'ejs');
app.use(session({
store: new RedisStore({
host: '127.0.0.1',
port: 6379,
client: redis_client
}),
secret : 'foo',
resave: false,
saveUninitialized: false
}));
app.use(function (req, res, next) {
if (!req.session) {
return next(new Error('oh no')); // handle error
}
next();
});
});
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
require('./app/routes')(app, passport, session);
app.listen(port, function(){
console.log('server is at port' + port);
});

Please try this:
router.get('/logout', function (req, res) {
req.logOut();
res.status(200).clearCookie('connect.sid', {
path: '/'
});
req.session.destroy(function (err) {
res.redirect('/');
});
});

I was struggling with this issue myself. Previously I tried logout and session.destroy, and none worked for me. Then I found the above answers with the clearCookie addition, and that did the trick.
However, I was wondering if those functions are at all having any effect, given that without clearCookie they didn't. So I omitted them.
Also, as status(200) is overridden by redirect (which sets status to 302), I reckoned I'd omit that too.
As for the options to clearCookie in Will59's solution, they looked like they could be the defaults anyhow, so I tried omitting them as well.
I ended up with two lines of code bellow. They worked for me with Chrome, Firefox and Safari (the most recent versions at time of this writing).
router.get('/logout', function (req, res) {
res.clearCookie('connect.sid');
res.redirect('/');
});

You can use req.session.destroy in logout route to destroy the session below is the code for reference :)
app.get('/logout', function(req,res){
req.logOut();
req.session.destroy(function (err) {
res.redirect('/'); //Inside a callback… bulletproof!
});
});

res.clearCookies is kind of messed up. As an alternative, call res.cookie again with whatever options you used to create the cookie in the first place, along with expires: new Date(1), like this:
// Use the same httpOnly, secure, sameSite settings to "delete" the cookie
res.cookie("jwt", "", {
httpOnly: true,
secure: true,
sameSite: "none",
expires: new Date(1)
});
Essentially you are replacing the old cookie with a new one that expires immediately.

pjiaquan's did not work with chromium for me, the cookie was still around.
The issue comes from the res.clearCookie method, as explained in http://expressjs.com/en/api.html:
Web browsers and other compliant clients will only clear the cookie if the given options is identical to those given to res.cookie(), excluding expires and maxAge.
In my case, the solution ended up being:
router.get('/logout', function (req, res) {
req.logOut();
res.status(200).clearCookie('connect.sid', {
path: '/',
secure: false,
httpOnly: false,
domain: 'place.your.domain.name.here.com',
sameSite: true,
});
req.session.destroy(function (err) {
res.redirect('/');
});
});

So none of the suggestions here worked for me, until I realized I was doing a dumb:
Using Github, I set up an OAuth app (you can do this in your profile settings), and used that for authentication.
Worked a charm! But it was always sending me back the same profile, even when I logged out from my app. Clearing all browser storage didn't fix it.
Then it dawned on me that I was still logged into my github account (and that was the profile I was always getting)... once I logged out of that, then the OAuth app prompted me for my user/pw again.

Related

Can't get socket.io to work

The client library js file is not loading. Trying to load socket.io into my project but the client is not detecting the javascript library that is supposed to be served automatically. here is my code.
var express = require('express')
, passport = require('passport')
, util = require('util')
, session = require('express-session')
, SteamStrategy = require('../../').Strategy
, Steam = require('machinepack-steam')
, path = require('path')
, app = express()
, http = require('http')
, socket = require('socket.io')
;
app.set('port', process.env.PORT || 2053);
var server = http.createServer(app).listen(app.get('port'), function(){
console.log("Express server listening on port " + app.get('port'));
});
var io = socket.listen(server);
io.sockets.on('connection', function () {
console.log('hello world im a hot socket');
});
var steamkey = 'redacted';
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(obj, done) {
done(null, obj);
});
passport.use(new SteamStrategy({
returnURL: 'https://get-a.team/auth/steam/return',
realm: 'https://get-a.team',
apiKey: steamkey
},
function(identifier, profile, done) {
// asynchronous verification, for effect...
process.nextTick(function () {
profile.identifier = identifier;
return done(null, profile);
});
}
));
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(session({
secret: 'your secret',
name: 'name of session id',
resave: true,
saveUninitialized: true}));
app.use(passport.initialize());
app.use(passport.session());
app.use(express.static(path.join('public')));
app.get('/', function(req, res){
if(req.user){
res.redirect('/account');
} else {
res.render('index', { user: req.user });
}
});
app.get('/search/:appid', ensureAuthenticated, function(req, res){
if(Number.isInteger(+req.params.appid)){
res.render('search', { user: req.user, appid: req.params.appid });
} else {
res.render('error', { user: req.user, error: "Wrong url format "+req.params.appid });
}
})
app.get('/account', ensureAuthenticated, function(req, res){
Steam.getOwnedGames({
steamid: req.user.id,
key: steamkey,
include_appinfo: 1,
include_played_free_games: 1,
appids_filter: [],
}).exec({
// An unexpected error occurred.
error: function(err) {
console.error(err);
},
// OK.
success: function(result) {
//console.log(result);
// save every game that isnt already saved
res.render('account', { user: req.user, games: result });
},
});
});
app.get('/logout', function(req, res){
req.logout();
res.redirect('/');
});
app.get('/auth/steam',
passport.authenticate('steam', { failureRedirect: '/' }),
function(req, res) {
res.redirect('/');
});
app.get('/auth/steam/return',
passport.authenticate('steam', { failureRedirect: '/' }),
function(req, res) {
res.redirect('/account');
});
app.listen(3000);
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) { return next(); }
res.redirect('/');
}
Any help will be greatly appreciated
I've tried many different ways to include the socket library online but none works, even code copied directly from the socket.io website.
I tried localhost:2053/socket.io/socket.io.js and it still won't work. Not sure what im doing wrong
Figured it out. Had to reload socket.io to a different port:
...
, app2 = require('express')()
, http2 = require('http').Server(app2)
;
var io = require('socket.io')(http2);
io.on('connection', function(socket){
console.log('a user connected');
});
app2.get('/', function(req, res){
res.send('<h1>Hello world</h1>');
});
http2.listen(2085, function(){
console.log('listening on *:2085');
});
the create a nginx rule to serve the lib from that port:
location /route/ {
rewrite ^/route/?(.*)$ /$1 break;
proxy_pass http://127.0.0.1:2085;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
and finally load it from the client end:
<script src="/route/socket.io/socket.io.js"></script>
if anyone knows the correct way of doing it, please let me know. This works though, feels quite like forcing a round peg in a square hole.

Node.js, express, passport authentication "Bad Request"

I'm using Cloud 9 to setup a basic social media website and I am having trouble with registration and authentication of users. I'm using Node.js, express and passport for authentication, and mongoDB as a database.
// PASSPORT Setup //
app.use(require("express-session")({
secret: "I am the best",
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
// INDEX Page
app.get("/", function(req, res) {
res.render("landing-page");
});
// REGISTER NEW
app.get("/register", function(req, res) {
res.render("user/register");
});
// REGISTER CREATE
app.post("/register", function(req, res) {
var user = req.body.user;
var newUser = new User({
username: user.email,
firstName: user.firstName,
lastName: user.lastName,
});
User.register(newUser, user.password, function(err, user) {
if(err) {
console.log(err);
return res.render("user/register");
}
passport.authenticate("local")(req, res, function() {
res.redirect("/");
});
});
});
// Login routes
app.get("/login", function(req, res) {
res.render("login");
});
app.post("/login", passport.authenticate("local", {
successRedirect: "/",
failureRedirect: "/login"
}) , function(req, res) {
});
// Logout route
app.get("/logout", function(req, res) {
req.logout();
res.redirect("/");
});
However whenever I run this, when I sign up a new user, it gives me a webpage with just "Bad Request", however the user is created in the database.
Look at this answer; the bad request is not a problem with your passport method: that indicates the request you try to make is not correct:
Did you set the head at: Content-Type: application-json?
Also update the bodyParser to the last version. This solved a similar problem I had.

Passport-cas2 always redirecting to failureRedirect

I'm quite new to Node.js and I'm trying to implement an authentication system through an external CAS server. I'm using Passport.js + passport-cas2 but it's always redirecting me to the failureRedirect page even though the CAS correctly authenticated me. Here is my code:
var SocketIOFileUpload = require('socketio-file-upload'),
socketio = require('socket.io'),
express = require('express'),
path = require('path'),
express = require('express'),
passport = require('passport'),
session = require('express-session'),
bodyParser = require('body-parser');
var CasStrategy = require('passport-cas2').Strategy;
var cas = new CasStrategy({
casURL: 'https://my.cas.server'
},
function(username, profile, done) {
console.log("authenticating");
done(null, new User());
});
var app = express()
.use(bodyParser.urlencoded({ extended: true }))
.use(SocketIOFileUpload.router)
.use(passport.initialize());
passport.use(cas);
app.use(session({ secret: 'my secret phrase' }))
.use(passport.session())
.get('/', function(req, res){
res.redirect('/auth/cas');
})
.get('/auth/cas',
passport.authenticate('cas', { failureRedirect: '/error', successRedirect: '/upload' }),
function(req, res) {
// Successful.
res.redirect('/upload');
})
.use('/upload', function(req, res, next){
if (req.user)
return express.static(path.join(__dirname, 'html'));
else
res.redirect('/auth/cas');
})
.get('/error', function(req, res) {
res.send('Error in authentication. Please Try Again.');
})
.listen(8080, function () {
console.log('Upload Server started on http://localhost:8080');
});
The console.log("authenticating") isn't even executed at all!
Thanks for your help.
Okay, I fixed it, my CAS server certificated was self-signed and I had to edit the passport-cas2 source in order for it to accept the certificate.

How do I set a session cookie to secure and use CSRF tokens?

I have an express application where I am trying to set the session cookie to secure. So far I have tried the code below:
app.use(express.cookieParser());
sessionOptions = definitions.REDIS;
sessionOptions.ttl = definitions.session.expiration;
app.use(express.session({
secret: definitions.session.secret,
cookie: { <---------------------------- Added this
secure: true
},
store: new RedisStore(sessionOptions)
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(express.bodyParser());
app.use(express.csrf());
app.use(function(req, res, next) {
res.locals.token = req.session._csrf;
return next();
});
But now when I try to log in the CSRF token does not validate and I get a forbidden error. How can I make the session cookie secure AND use a CSRF token?
Here's what I use. I don't think you need the return before next(), but I'm not sure if that's your issue.
app
.set('view engine', 'jade')
.set('views', __dirname + '/../views')
.set('json spaces', 2)
.use(express.compress())
.use(express.cookieParser('our secret'))
.use(express.session({
store: new RedisStore({
port: config.redisPort,
host: config.redisHost,
db: config.redisDatabase,
pass: config.redisPassword
}),
proxy: true,
cookie: { httpOnly: true, secure: true }
}))
.use(express.bodyParser())
.use(express.methodOverride())
.use(express.csrf())
.use(function (req, res, next) {
res.cookie('XSRF-TOKEN', req.csrfToken());
res.locals.csrftoken = req.csrfToken();
next();
})
.use(everyauth.middleware());
The proxy: true is necessary for Heroku. Note that req.session._csrf has been obsoleted in the latest version of Express.

Cannot GET /auth/twitter/callback while using twitter oauth in nodejs

I'm trying to do twitter oauth in nodejs using passportjs but getting error
Cannot GET /auth/twitter/callback?oauth_token=alksdkalsjdsjd23232378skjdfjsdhf&oauth_verifier=234jjh23j4k234k23h4j2h342k34hj
Here is my node js code
var express = require('express')
, passport = require('passport')
, util = require('util')
, GoogleStrategy = require('passport-google').Strategy
, TwitterStrategy = require('passport-twitter').Strategy;
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(obj, done) {
done(null, obj);
});
passport.use(new TwitterStrategy({
consumerKey: 'xxxxxxxxxxxxxxxxxxxx',
consumerSecret: 'xxxxxxxxxxxxxxxxxxxxxxxxxx',
callbackURL: 'http://127.0.0.1:3000/auth/twitter/callback'
},
function(token, tokenSecret, profile, done) {
process.nextTick(function () {
return done(null, profile);
});
}
));
var app = express();
// configure Express
app.configure(function() {
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(express.logger());
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.session({ secret: 'keyboard cat' }));
// Initialize Passport! Also use passport.session() middleware, to support
// persistent login sessions (recommended).
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
app.use(express.static(__dirname + '/../../public'));
});
app.get('/', function(req, res){
res.render('index', { user: req.user });
});
app.get('/login', function(req, res){
res.sendfile('./views/auth.html');
});
app.get('/auth/twitter', passport.authenticate('twitter'));
app.get('auth/twitter/callback',
passport.authenticate('twitter', { successRedirect: '/success',
failureRedirect: '/login' }));
app.get('/success', function(req, res){
res.send("success logged in");
});
app.listen(process.env.PORT || 3000);
EDIT
There is missing / in auth/twitter/callback route definition.
Also for the routers /auth/twitter and auth/twitter/callback, passport.authenticate() as middleware will do the authentication, and you should have route handling functions.
So the definition of your routes should look something like:
app.get('/auth/twitter',
passport.authenticate('twitter'),
function(req, res) {}); // empty route handler function, it won't be triggered
app.get('/auth/twitter/callback',
passport.authenticate('twitter', {
successRedirect: '/success',
failureRedirect: '/login' }),
function(req, res) {}); // route handler
You don't need the empty route handler function(req, res) {} - you can just leave the argument out and express will understand you don't plan on ever using the handler

Categories