I have this Node API that frontends a backend OAuth server. At the end of the SAML OAuth dance, I set the Bearer Token in a browser cookie.
// need cookieParser middleware before we can do anything with cookies
app.use(express.cookieParser());
// set a cookie
app.use(function (req, res, next) {
// check if client sent cookie
var cookie = req.cookies.cookieName;
if (cookie === undefined)
{
// no: set a new cookie
var randomNumber=Math.random().toString();
randomNumber=randomNumber.substring(2,randomNumber.length);
res.cookie('cookieName',randomNumber, { maxAge: 900000, httpOnly: true });
console.log('cookie created successfully');
}
else
{
// yes, cookie was already present
console.log('cookie exists', cookie);
}
next();
});
app.use(express.static(__dirname + '/public'));
Now I was introduced to a fancy NPM which does pretty much the same thing https://github.com/mozilla/node-client-sessions
While I was almost inclined on using this NPM, I bumped into express-session. https://github.com/expressjs/session - this is for server side sessions. But this also sets a cookie
var express = require('express');
var session = require("express-session");
var app = express();
app.use(session({
resave: true,
saveUninitialized: true,
secret: 'ABC123',
cookie: {
maxAge: 60000
}
}));
app.get("/test", function(req, res) {
req.session.user_agent = req.headers['user-agent'];
res.send("session set");
});
If my need to set only a bearer token in the browser cookie for subsequent API calls, which option should be my choice?
express-session is my go to.
If you look at what it took to accomplish the same thing with the two different methods, I think the answer is clear.
If all you want to do is set a client cookie that will enable the server to correctly authenticate future requests, express-session is awesome.
Here is an example set from another question I answered that uses MongoDB as a backend to store your sessions:
'use strict';
var express = require('express'),
session = require('express-session'),
cookieParser = require('cookie-parser'),
mongoStore = require('connect-mongo')(session),
mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/someDB');
var app = express();
var secret = 'shhh';
app.use(session({
resave: true,
saveUninitialized: true,
secret: secret,
store: new mongoStore({
mongooseConnection: mongoose.connection,
collection: 'sessions' // default
})
}));
// ROUTES, ETC.
var port = 3000;
app.listen(port, function() {
console.log('listening on port ' + port + '.')
});
Related
I have a node express application.
const session = require('express-session');
const config = require('config');
var MemoryStore = require('memorystore')(session);
module.exports = function (app) {
app.use(express.json());
app.use(
session({
saveUninitialized: false,
cookie: { maxAge: 86400000 },
store: new MemoryStore({
checkPeriod: 86400000
}),
resave: false,
secret: config.get('Storagehash')
})
);
app.use('/api/auth', users);
}
I have separated auth route and put it in a separate file like this. When I do console.log(req.session) I'm getting proper output.
const router = express.Router();
router.post('/', async (req, res) => {
....
req.session.isAuth = true;
console.log(req.session);
req.session.customerID = customer;
res.send(token);
}
But when I'm looking in the cookie tab, connect.sid is not getting inserted there.
Do you have a frontend application? If so, whenever you send a request to your backend you need to include withCredentials: true in your request. This will send the cookies to your backend. If you are using axios to make requests it can be done like this:
(Assuming your port is 5000)
axios.post("http://localhost:5000/api/auth/", {}, { withCredentials: true });
I set a session variable called user upon login:
req.session.authenticated_user = user;
When I set the session again later it doesn't update:
req.session.authenticated_user = somenewvalue;
This will still contain the original value of user. App module:
var session = require('express-session');
var redisStore = require('connect-redis')(session);
var redisClient = redis.createClient();
const sessionMiddleware = session({ secret: 'foo' });
app.use(session({
store: new redisStore({ client: redisClient }),
secret: 'secretsession',
resave: false,
saveUninitialized: true,
cookie: { secure: false, sameSite: true, expires: 7200000 }
}))
app.use('/users', sessionChecker, usersRouter);
My router:
var express = require('express');
var router = express.Router();
var user_controller = require('../controllers/userController')
/* GET user update. */
router.get('/user_login/login', user_controller.user_login_get);
/* POST user update. */
router.post('/user_login/login', user_controller.user_login_post);
/* GET user update. */
router.get('/:username/update', user_controller.user_update_get);
/* POST user update. */
router.post('/:username/update', user_controller.user_update_post);
How can I update a session variable in node?
Answered here: Sessions won't save in Node.js without req.session.save()
req.session won't update automatically if req is a Post request. For Post requests, one must call req.session.save() unless data is sent out through res.send, res.redirect, etc.
This is my code:
const functions = require('firebase-functions');
const express = require('express');
const session = require('express-session');
const FirebaseStore = require('connect-session-firebase')(session);
const firebase = require('firebase-admin');
const cookieParser = require('cookie-parser');
const ref = firebase.initializeApp(
functions.config().firebase
);
const app = express();
app.use(cookieParser());
app.set('trust proxy', 1);
app.use(session({
store: new FirebaseStore({
database: ref.database()
}),
secret: 'abigsigrettotheseeiosnofthmbiith765huig',
resave: true,
saveUninitialized: true,
cookie: { maxAge: 60000 }
}));
app.get('/', function(req, res, next) {
console.log(req.session);
req.session.username='xyz';
res.send('Filling the session with data');
});
app.get('/bar', function(req, res, next) {
console.log(req.session);
var sessionData = req.session.username;
res.send(`This will print the attribute I set earlier: ${sessionData}`);
});
exports.app = functions.https.onRequest(app);
When I run this, it creates new session in the DB.
And every time I refresh the page, there is a new session.
I want of course, that only one session would be created,
and that on refresh, this session would only be updated, or to get the data from there. not to create a new one every time.
Checking the cookies - showed me that no cookie is saved / created.
I've been working on this for hours...
this was frustrating when I was using firebase functions and hosting, but can be solved by simply setting name:"__session" in the session.
app.use(session({
store: new FirebaseStore({
database: ref.database()
}),
name:"__session
...
I am using Express Framework and socket.io. I am working on authentication part and I am unable to change the value of cookie. Please see the code.
var session = require('express-session');
app.use(cookieParser());
app.use(session({
secret: "kvkjsdsbj12334",
resave:false,
saveUninitialized: false,
cookie:{
authStatus: "NotLoggedIn",
secure: false
},
rolling: true
}));
app.use(function (req, res, next){
console.log(req.session.cookie.authStatus); // Logs NotLoggedIn after /login.
});
app.post('/login',(req,res)=>{
var body = _.pick(req.body,['email','password']);
var email = body.email;
var password = body.password;
Users.findByCredentials(body.email,body.password).then((user)=>{
req.session.user = user;
req.session.cookie.authStatus = "loggedIn";
req.session.save();
//Redirected from here
});
});
In my production app, saving data to a session then redirecting is completely unreliable. A console.log after saving the session shows the data has been attached. Then on redirect, another console.log shows that the session has been reset. Every 3-5 tries, the session will persist across the redirect, but it is mostly unreliable. In my development app this code works flawlessly...
• I've tried changing the version of express-session
• I've tried moving the static folder above the session middleware in server.js
• I've tried using req.session.save()
UPDATE ******
This is a known issue with the session middleware: https://github.com/expressjs/session/pull/69
Here is my server.js
// Module Dependencies
var express = require('express');
var app = express();
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var session = require('express-session');
var favicon = require('serve-favicon');
var methodOverride = require('method-override');
// Set Environment from ENV variable or default to development
var env = process.env.NODE_ENV = process.env.NODE_ENV || 'development';
var config = require('./config/config');
// Set Port
var port = process.env.PORT || config.app.port;
// Connect to our MongoDB Database
// mongoose.connect(config.db);
// set the static files location /public/img will be /img for users
app.use(express.static(__dirname + '/public'));
// Express Session
app.use(session({
secret: 'asfasfa3asfa',
resave: true,
saveUninitialized: true,
cookie: {
secure: false,
maxAge: 2160000000
}
}));
// Favicon
app.use(favicon(__dirname + '/public/img/favicon.ico'));
// Set Jade as the template engine
app.set('views', './app/views');
app.set('view engine', 'jade');
// Get req.body as JSON when receiving POST requests
app.use(bodyParser.json()); // parse application/json
app.use(bodyParser.json({
type: 'application/vnd.api+json'
})); // parse application/vnd.api+json as json
app.use(bodyParser.urlencoded({
extended: true
})); // parse application/x-www-form-urlencoded
// override with the X-HTTP-Method-Override header in the request. simulate DELETE/PUT
app.use(methodOverride('X-HTTP-Method-Override'));
// routes ==================================================
require('./app/routes')(app); // pass our application into our routes
// start app ===============================================
app.listen(port);
console.log('****** App is now running on port ' + port + ' ******'); // shoutout to the user
exports = module.exports = app; // expose app
Here is the controller where the session is being saved:
// Module dependencies.
var config = require('../../config/config');
// Render Either Home Page or Dashboard Page If User is Logged In
var index = function(req, res) {
console.log("Session At Home Page: ", req.session)
if (req.session.user) {
res.render('dashboard');
} else {
res.render('home');
}
};
// Handle Authentication Callback
var callback = function(req, res) {
// Get Access Token via Service-SDK
Service.getAccessToken(req, function(error, tokens) {
if (error) {
console.log(error);
return res.redirect('/');
}
// Otherwise, Save User Data & API Tokens To Session
req.session.regenerate(function(err) {
req.session.user = tokens.user_id;
req.session.access_token = tokens.access_token;
req.session.client_token = tokens.client_token;
req.session.save(function(err) {
console.log("Session Before Redirect: ", req.session);
res.redirect('/');
})
});
});
};
module.exports = {
index: index,
callback: callback
};
My Routes
app.get('/auth/service/callback', application.callback)
app.get('/logout', application.logout);
app.get('/', application.index);
There is a conflict between the livereload and the express-session in the Express 4. You can read more about it here https://github.com/expressjs/cookie-session/issues/14
But in short, the livereload must be called AFTER the session. As this:
var express = require("express");
var http = require("http");
var session = require("express-session");
var livereload = require("connect-livereload");
var app = express();
app.set("port", 9090);
/**
* First you must config the session
*/
app.use(session({
secret: "keyboardcat",
name: "mycookie",
resave: true,
saveUninitialized: true,
cookie: {
secure: false,
maxAge: 6000000
}
}));
/**
* Then you can config the livereload
*/
app.use(livereload())
/**
* This simple url should create the cookie.
* If you call the livereload first, the cookie is not created.
*/
app.get("/",function(req,res){
req.session.name = "blaine";
res.end("ok");
});
/**
* If you call the livereload first, the session will always return nothing
* because there is no cookie in the client
*/
app.get("/me",function(req,res){
var name = req.session.name;
var message = "Hello [" + name + "]!";
res.end(message);
});
http.createServer( app ).listen(
app.get("port"),
function(){
console.log("server is running in port ", app.get("port"));
}
)
If you call the livereload BEFORE the session config, all will seems to work but the cookie will not persist. This was a tricky bug and I lost a full day into it. I hope this help somebody.