Does anyone know how to send cookies with express 4? - node.js

It seems that express 4 has unbundled cookieparser, so I included it as it details in the docs, but res.cookie() doesn't seem to send the cookie anymore.
I have
var cookieParser = require('cookie-parser');
followed by
res.cookie("token",tokval, { maxAge: 900000, httpOnly: false });
but document.cookie returns nothing.
Express docs: http://expressjs.com/en/api.html#req.cookies
Any thoughts or suggestions (or prayers I suppose) would be much appreciated

You won't see HttpOnly cookies in the browser. They are cookies that are automatically sent by the browser but unavailable to scripts on the page.

Related

Unable to get session cookie using axios and Express Session. But able to with Postman

I have been able to find countless topics of discussion on this, but none of the solutions seem to work for me
Essentially, I have a react client that uses axios to make requests to a node js backend which uses express session
I’m able to log into the application and get a successful response. However, the response header does not include the connect.sid field. And when checking chromes devtools -> application -> cookies folder, I don’t see any cookies there for the site
I also tried testing this using IE and Firefox with the same result
Now when making the same login request via postman, I’m able to see both the connect.sid in the header and the cookie itself in the cookies tab.
In my current situation, the client and server are both running on localhost, with the client running on port 3000 and the server running on port 3001. One difference is that client is http and server is https
From my research online, these are the common things suggested, with neither working in my case
Setting axios withCredential to “true” in react. This appears to have fixed the problem for majority of the people online. I have mine set up as well
import axios from "axios";
axios.defaults.withCredentials = true;
Setting the httpOnly field to false for the session cookie in the server. Below is my session configuration
app.use(session({
secret: 'BSL3562904BVAIHBP53VRFSF',
resave: false,
saveUninitialized: false,
rolling: true,
cookie: {secure: true, httpOnly: false }
}))
Configuring the cors settings in the server. This shouldn’t affect me in this scenario as the client and server are running on the same domain, but I still covered that base anyway
app.use(cors({
credentials: true,
origin: "http://localhost:3000"
}));
For the origin value I tried both “localhost” and “127.0.0.1”
Setting “trust proxy” in server
app.set('trust proxy', 1);// trust first proxy
This isn’t simply an issue of not being able to retrieve cookies in the client, as I can create and attach cookies to the response and see them. It’s just the session cookie that does not appear
At this point, I’m kind of banging my head against a wall. So any help or suggestions would be much appreciated!

Why are my express sessions not persisting and why am I getting a new session (or multiple sessions) created for each request

I have a basic node.js express app using express-sessions.
Please can someone help with why the sessions are not persisting and why a new session is created for every request.
The app itself is quite large so i have added a reduced case of the important settings below.
const express = require('express');
const session = require('express-session');
const MongoDBStore = require('connect-mongodb-session')(session);
// initialise express
const app = express();
// initialise db session store
const store = new MongoDBStore({
uri: MONGODB_URI,
collection: 'sessions',
// can also set expire here for auto cleanup by mongodb
});
app.use(session({
secret: 'secret password',
resave: false,
saveUninitialized: false,
httpOnly: false,
secure: app.get('env') === 'production',
store,
}));
...routes
in a user login route the app sets the request user to the session and saves the session. it is expected that this req,session.user will persist between pages but it does not. on each page request i can see a new session (or sometimes multiple sessions, 1 for each file request) being created.
UPDATE
TL:DR;
- robots.txt causes issues if not dealt with, set DEBUG env to express-session to troubleshoot
After a lot of hair pulling I've found a solution and some useful troubleshooting tips.
when running your app, run it with debug set to express-session.
so for those of you that are quite new to this like myself, run your app with a command similar to this:
DEBUG=express-session node 'bin/www.js'
or
DEBUG=express-session node app.js
depending on how you have your app entry point setup.
Doing this will print session related log msgs so you can troubleshoot if the cookie is actually getting sent with each request or not. the error messages will look like something this:
express-session fetching 0wgmO1264PsVvqeLqaIIXd6T0ink0zts +34s
express-session session found +49ms
To troubleshoot the issue of multiple requests causing multiple sessions per page load, Add a middleware at the top of your app before any other middleware. this will allow us to see the request URL and troubleshoot which requests may be interfering with our sessions.
// see what requests are being sent and which ones contain cookies
app.use((req, res, next) => {
const { url } = req;
const isCookieSent = req.headers.cookie;
console.log({ url });
console.log({ isCookieSent });
next();
});
from doing this I found out that the culprit was robots.txt file, Apparently the only path that is ignored by default is favicon.ico.
Because this robots.txt path wasn't handled properly, nor was it sending a cookie, it was causing the duplicate requests and also causing the cookies not to persist.
to fix this you either need to handle or ignore this request prior to getting to the session middleware.
i did this using this middleware, once again fairly high up.
app.get('/robots.txt', (req, res) => {
res.type('text/plain');
res.send('User-agent: *\nDisallow: /');
});
I am new to node.js so if there is anyone with more knowledge feel free to chip in with extra info or cleaner ways of solving this problem. Hopefully this saves some of you a lot of hassle!

Express-session with passport.js multiple cookies

I'm trying to implement the login functionality with passport.js and express-session, it works well,
var passport = require('passport'),
session = require('express-session'),
MongoDBStore = require('connect-mongodb-session')(session);
var sessionStore = new MongoDBStore({
uri: config.db,
collection: 'sessions'
});
var sessionOptions = {
name: 'very-secure-cookie',
secret: config.secret,
resave: false,
saveUninitialized: true,
cookie: {
secure: true,
maxAge: null
},
store: sessionStore
};
app.use(session(sessionOptions));
app.use(passport.initialize());
app.use(passport.session());
Here, maxAge is null, meaning that the client gets logged out when they close the browser window. However, I want to store an additional cookie with the client's email address in order to pre-fill the <input type="text" name="email"> when they want to log back in if they come later.
I've tried app.use()'ing another session object just to store the email information in another cookie, but for some reason the cookie is set only once (the first one).
app.use(session(returningSessionOptions));
Couldn't find any sensible solution anywhere :(
Oh, and I have to mention that I thought about using cookie-parser middleware alongside with express-session, but the docs state that it may result in conflicts.
As you didn't include the complete code you used, I assume you set the cookie using res.cookie(name, value[, options]); or res.setHeader('set-cookie', serializedCookie);.
There seems to be an issue with the set-cookie header. When adding multiple cookies, they are appended to the header, separated by comma, which doesn't seem to work in most current browsers. The header is only interpreted until the first comma and therefore only the first cookie is saved. In some browsers everything between the first equals sign and the following semicolon is used as value for that first cookie.
Possible solution
I could reproduce the issue with an old version of Express (3.0.0) using the code below. Using Express 4.13.4 (and also 3.21.2) the same code worked fine. If you are working with an old version of Express, I recommend that you update to the latest one as this should fix the problem. If you are already using a current version, please try if the example works for you. If not, please provide the code and the headers sent by your express-app. In some cases with a more complex application the problem exists even when using versions that work with the example code (I tried Express 3.21.2).
If there is any reason for you not to update to the latest version or the update doesn't fix the issue for you, there is an alternative solution for the problem:
Code to reproduce the issue
To eliminate possible side-effects by other code in the application, here is the minimal example that I used to reproduce your issue:
var express = require('express');
var session = require('express-session');
var passport = require('passport');
var app = express();
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());
app.get('/', function (req, res) {
res.cookie('cookie', 'value');
res.send('Hello World!');
});
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
When accessing the express-app (running Express 3.0.x) via the browser, the following response headers are sent:
set-cookie: cookie=value; Path=/
set-cookie: cookie=value; Path=/,connect.sid=s%3ARPkxiLfy0dbeBs5eILYBLK6Yh-sOjABS.ykNXCmaOsxtIAXV%2Ba9GCW6YnBi0cBhvZIGvwlj%2F%2Fsy0; Path=/; HttpOnly
Using Express >=3.21.2 everything works fine for this example:
set-cookie: cookie=value; Path=/
set-cookie: connect.sid=s%3AR6TVTnUe3eyIvlpT0Hl5ikwcH_XMHXId.ouysyG5tGGekaVDxZMXJP4A8SJfsckLE4GZ3%2B1Eyd1o; Path=/; HttpOnly
Alternative fix
Borrowing the code of function setcookie from express-session for setting your cookies could do the trick for you, as it writes an array containing all the cookies to the header while preserving the ones already added to the response. To do this, install the cookie module, add var cookie = require('cookie'); and replace res.cookie('cookie', 'value'); in the above code with the following lines:
var data = cookie.serialize('cookie', 'value');
var prev = res.getHeader('set-cookie') || [];
var header = Array.isArray(prev) ? prev.concat(data)
: Array.isArray(data) ? [prev].concat(data)
: [prev, data];
res.setHeader('set-cookie', header);
Now the following headers are sent to the browser and all cookies are saved (tested using Google Chrome 49 on MacOS):
set-cookie:cookie=value
set-cookie:cookie=value
set-cookie:connect.sid=s%3Aa1ZPDmERtKwUaPjY__SrPtIrpYC7swQl.0KOs83RSmUTG%2FgPoyOLo4u5UFTjC89yS0Ch0ZVXWVo8; Path=/; HttpOnly
Unfortunately the header is duplicated for the first cookie when using Express 3.0.0, which shouldn't be done according to RFC6265 Section 4.1.1:
Servers SHOULD NOT include more than one Set-Cookie header field in
the same response with the same cookie-name. (See Section 5.2 for
how user agents handle this case.)
Helpful resources
The following articles may also be helpful:
Someone facing a similar problem, but with ASP.NET/Web API instead of node.js/express. However, in my opinion this page provides helpful information on the topic: Set-Cookie Header With Multiple Cookies
Another possible solution for setting multiple cookies with node.js/express that might help: http://www.connecto.io/blog/nodejs-express-how-to-set-multiple-cookies-in-the-same-response-object/

Set Cookie fails in ExpressJs

I have a problem in Express 4.x.I can't set any cookies. I want to set a cookie via Ajax request, i do the request, my server-side res.cookie() is executed, in my response headers i can find my 'set-cookie' header with the specific name and value, but nothing happens, the cookie is not registered. I have no HttpOnly or secure flag.
Cookie set example :
res.cookie('my_cookie','value',{maxAge:500,secure:false,httpOnly:false});
What i've noticed is that if i set maxAge 500 for example, my cookie expiration date from response headers is about 5 hours ago, so i tried to add a bigger value, but nothing happened.
It is like my set-cookie header is ignored. I don't use AngularJS, just jQuery.
If i put the set-cookie content in document.cookie from js console, the cookie is registered..
Thanks in advance and sorry for my bad english .
Version 4.0 removed a lot of the convenience middleware from the library for a more modular architecture; in this case you need to reference the cookie-parser middleware. Without it req.cookies is just an empty {}.
$npm install cookie-parser
var express = require('express')
var cookieParser = require('cookie-parser')
var app = express()
app.use(cookieParser())
You also need it to sign 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.

Resources