Secure cookies option in Express - how to access - node.js

In a node app, I want to use cookies to read data. If I want to make a cookie using the options:
res.cookie('user', '123', { signed: true, httpOnly: true, secure: true }
and later read the cookie in a node endpoint/controller:
router.get('/test', testHandler)
function testHandler(req, res){
// how to read the secure cookie here?
}
how can I access this secure cookie on my local machine? Would I have to set up an https server locally to be able to read it?

You can just do req.session
Remember if you set the secure attribute to true, the connection has to be made over HTTPS, otherwise it won't work.

Related

express cookie-session failing on mobile

I am trying to use cookie-session in express / nodejs, my setup works on PCs, but not on mobile:
on Android/Firefox, I can setup the session cookie, but I cannot modify it once set, I can't event erase it by setting req.session=null. Android/chrome is fine.
on iOS (Safari, chrome, firefox), the cookie doesn't seem to ever be set (iOS 15.3).
The setup is as follows:
my website is hosted at "mywebsite.com" (names modified for this forum)
my API setting/using the cookie is at another URL "mywebsite.io" (different extension)
cookie-session options are:
name: 'session',
keys: ['my secret'],
sameSite: 'none',
secure: true,
httpOnly: true,
signed: true,
overwrite: true,
Both website and API implement https. The API is behind a nginx proxy. Express includes this:
app.set('trust proxy', 1); // trust first proxy
to make sure the secure option works behind the proxy.
The web client is created in React, I run API calls using superagent with the .withCredentials() option.
I have tried:
setting the maxAge option
setting the domain option to 'mywebsite.io' or 'mywebsite.com'
setting the 'path' option to '/'
using the should-send-same-site-none module
Whatever I do, the iOS cookie is always empty (req.session = undefined on subsequent calls), and the Android/Firefox combo wont't let me update it.

express-session secure: true

app.use(session({
secret: "testing credentials",
store: sessionStore,
resave: true,
saveUninitialized: true,
cookie : {
httpOnly: true,
//secure: true,
maxAge : 60 * 60 * 1000
}
}));
I'm working on some security problems on my newly developed website. And after done some research online, if secure=true is set, then it will be more secure. However,
If set secure: true, then information inside session will lose every time when the user send another request. Is there a way to solve this problem? If doesn't include "secure: true" in the cookie: , then the session will last for that maxAge.
If a cookie is set with the secure flag, it will only be sent to the server by the browser over https, and not plain http. This should be the default for production environments.
However, when developing an app, you probably use plain http on your dev machine. If you set your session cookie as secure in this case (using plain http), the server will never receive it, and you will experience a new empty session on each request.
So in short, you should only set the cookie as secure if you are using https (that is, in later stages of your development pipeline, and definitely in production).
On another note, if you set maxAge, the cookie will be persisted, which is not the best practice for session cookies. Without maxAge, the cookie will be kept until the user closes the browser and not normally persisted to disk, which is the correct behaviour for session cookies.

Express session-cookie not being sent on openshift with https and secure flag

Got a strange issue, I am using Express and in development we use http and have secure: false for the session cookie, however now we are moving to openshift we have turned https on thinking it would be a simple endeavour but our cookies are not being sent back with the responses. If however we turn off https and revert back to http on openshift it works fine and cookies are sent.
So here is an example of what the cookie config looks like:
var setupSession = function() {
var sessionConfig = {
secret: environmentVars.cookie.secret,
name: environmentVars.cookie.name,
maxAge: environmentVars.cookie.expiry,
domain: environmentVars.cookie.domain,
httpOnly: true,
secure: environmentVars.cookie.secure, // true when using https
secureProxy: environmentVars.cookie.secure, // true when using https
signed: true
};
app.set('trust proxy', 1); // Just added this, still no luck
app.use(session(sessionConfig));
};
So the above is run when the app starts up and as noted in the comments when we are using a secure connection the environment vars are set for us, and when the above is used in conjunction with HTTPS no cookie is sent back from express, however openshift cookies are sent back, like the gears one etc. Again with http and disabling the secure stuff it works fine we all get cookies and rejoice. All responses work and data is sent back its just the set-cookie header is missing for the apps cookies (but as mentioned not openshift ones).
So the actual certificate is not setup within nodejs it is setup on openshift as an alias with a certificate applied. So express really has no idea it is being run in https other than the environmental vars it is passed and the port it is provided by the gear that is running it.
So has anyone else had anything similar or has any ideas on what we can try to solve the problem or diagnose it? I did some reading and people suggested trying the trust proxy and secureProxy, which has been done but still no luck.
So it turns out I was just being an idiot, it should look like:
var setupSession = function() {
var sessionConfig = {
secret: environmentVars.cookie.secret,
name: environmentVars.cookie.name,
maxAge: environmentVars.cookie.expiry,
domain: environmentVars.cookie.domain,
httpOnly: true,
secureProxy: environmentVars.cookie.secure, // true when using https
signed: true,
cookie: {
secure: environmentVars.cookie.secure, // true when using https
}
};
app.set('trust proxy', 1); // Just added this, still no luck
app.use(session(sessionConfig));
};
All works now :)
I had similar problem with express-session and after many trials the culprit for me was setting cookie.domain. Browsers wouldn't save the cookie.
This is how I was setting the value:
cookie: {
...
domain: process.env.OPENSHIFT_CLOUD_DOMAIN,
...
}
Hope it helps anyone going through the same, since at the time this is the best suited stackoverflow question to share this.

Node Express - difference between req.cookies and req.session.cookie

I am trying to find out what the difference is between req.cookies and req.session.cookie. I am using Passport for authentication in Node.js Express.
If I log these two lines in my code:
console.log('cookies',req.cookies);
console.log('session',req.session);
I get this output:
cookies { 'mysite.sid.uid.whatever': 's:Ltko5IdDgsAISG0smrKNYaeIVy8nbBzF.MkGmpnf6uUKITIAgN4ws3YXqxJrMaeeSCzlKdjQnqfI' }
session { cookie:
{ path: '/',
_expires: null,
originalMaxAge: null,
httpOnly: true,
secure: false },
views: 8,
passport: {} }
I am using this configuration:
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(busboyBodyParser());
//app.use(busboy());
app.use(cookieParser('cookie parser secret'));
app.use(session({
secret: process.env["SESSION_SECRET"],
saveUninitialized: true, // (default: true)
resave: true, // (default: true)
store: require('mongoose-session')(mongoose),
maxAge: 60000,
key: "mysite.sid.uid.whatever",
cookie: {secure: false}
}));
I don't really know the difference between using sessions or cookies, except that cookies are client-side only and sessions could be either client or server-side. I have read the documentation from Passport.js a few times, but I still don't really understand what is going on here. Can someone help me out with some explanation? As far as I can tell, it seems best to use server-side session using Redis. But I don't see how you can get away from using client-side data in the end. At some point, you have to rely on the client-side data stored right?
after I login with the express app, the passport object gets populated with a user field, with the MongoDB objectid.
passport: { user: 549290b8246f0e1408e48b13 } }
Typically you will be using cookies when serving browsers. The exception to this being authenticating via an HTTP header or POST parameter token, which are more typical for API requests for example.
It is true you can do client side or server side sessions using cookies, where the entire session data is stored in the cookie in the former (and does not use any storage server-side) or session data is stored server-side (with a session ID stored in a client-side cookie) in the latter.
req.cookies contains cookie values only, no matter if the cookies are session related or not. req.session.cookie contains the Set-Cookie parameters used in the client-side session ID cookie.

Server to server authentication with Node.js, Passport

I have two services running on different sub-domains: 1) Node.js, Express, PassportJS, 2) PHP based. Both services are exposed in same portal, in order to avoid requiring user to enter credentials twice, we call Node.js login API from PHP server. Node returns session cookie (connect.sid), we forward this to client with domain set to <<rootdomain>>.com. Now when client calls Node.js, we can see cookie being sent to Node but still Node fails to authenticate.
I have verified following things:
Login API call from PHP server to Node returns success with connect.sid cookie and adds session entry into Redis server (We are using Redis for storing sessions)
Cookie is set correctly in browser
When browser calls Node.js connect.sid cookie is sent to server
If we call login API directly from client, everything works as expected. Basically stand alone Node app works without any issues.
I am curious whether Node uses User-agent, IP or something to validate connect.sid cookie? Or is it something related to Passport/Express session params values? What might be wrong? FYI, currently site is not running on SSL.
Here are my session params:
store = new RedisStore({
port: 6379,
host: 'localhost',
client : redis
});
var sess = {
store: store,
secret: 'some secret',
rolling: true,
cookie: { maxAge : 36000000, secure: false },
saveUninitialized: true,
resave: true,
sortName: 0,
sortModified:0,
sortSize: 0
};
Thanks in advance

Resources