How can I set cookie in node js using express framework? - node.js

In my application, I need to set a cookie using the express framework. I have tried the following code but it's not setting the cookie.
var express = require('express'), http = require('http');
var app = express();
app.configure(function(){
app.use(express.cookieParser());
app.use(express.static(__dirname + '/public'));
app.use(function (req, res) {
var randomNumber=Math.random().toString();
randomNumber=randomNumber.substring(2,randomNumber.length);
res.cookie('cokkieName',randomNumber, { maxAge: 900000, httpOnly: true })
console.log('cookie have created successfully');
});
});
var server = http.createServer(app);
var io = require('socket.io').listen(server);
server.listen(5555);

The order in which you use middleware in Express matters: middleware declared earlier will get called first, and if it can handle a request, any middleware declared later will not get called.
If express.static is handling the request, you need to move your middleware up:
// 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(); // <-- important!
});
// let static middleware do its job
app.use(express.static(__dirname + '/public'));
Also, middleware needs to either end a request (by sending back a response), or pass the request to the next middleware. In this case, I've done the latter by calling next() when the cookie has been set.
Update
As of now the cookie parser is a seperate npm package, so instead of using
app.use(express.cookieParser());
you need to install it separately using npm i cookie-parser and then use it as:
const cookieParser = require('cookie-parser');
app.use(cookieParser());

Set Cookie?
res.cookie('cookieName', 'cookieValue')
Read Cookie?
req.cookies
Demo
const express('express')
, cookieParser = require('cookie-parser'); // in order to read cookie sent from client
app.get('/', (req,res)=>{
// read cookies
console.log(req.cookies)
let options = {
maxAge: 1000 * 60 * 15, // would expire after 15 minutes
httpOnly: true, // The cookie only accessible by the web server
signed: true // Indicates if the cookie should be signed
}
// Set cookie
res.cookie('cookieName', 'cookieValue', options) // options is optional
res.send('')
})

Not exactly answering your question, but I came across your question, while looking for an answer to an issue that I had. Maybe it will help somebody else.
My issue was that cookies were set in server response, but were not saved by the browser.
The server response came back with cookies set:
Set-Cookie:my_cookie=HelloWorld; Path=/; Expires=Wed, 15 Mar 2017 15:59:59 GMT
This is how I solved it.
I used fetch in the client-side code. If you do not specify credentials: 'include' in the fetch options, cookies are neither sent to server nor saved by the browser, even though the server response sets cookies.
Example:
var headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Accept', 'application/json');
return fetch('/your/server_endpoint', {
method: 'POST',
mode: 'same-origin',
redirect: 'follow',
credentials: 'include', // Don't forget to specify this if you need cookies
headers: headers,
body: JSON.stringify({
first_name: 'John',
last_name: 'Doe'
})
})

Set a cookie:
res.cookie('cookie', 'monster')
https://expressjs.com/en/4x/api.html#res.cookie
Read a cookie:
(using cookie-parser middleware)
req.cookies['cookie']
https://expressjs.com/en/4x/api.html#req.cookies

Setting cookie in the express is easy
first install cookie-parser
npm install cookie-parser
using middleware
const cookieParser = require('cookie-parser');
app.use(cookieParser());
Set cookie know more
res.cookie('cookieName', '1', { expires: new Date(Date.now() + 900000), httpOnly: true })
Accessing that cookie know more
console.dir(req.cookies.cookieName)
Done!

setting a cookie can be done as such:
res.cookie('cookie name', 'cookie value', [options])
where cookie_name is the name(String) of the cookie you wish to set, for example - "token", and the cookie value is the value(String) you wish to store in the said cookie.
as far as options go, you can read more about them here:
https://expressjs.com/en/api.html
one example of an option is 'maxAge' which indicates how long a cookie is valid, this is used for example when assigning an authentication token and you wish to limit the time a user can stay logged in before having to re-login.
Reading a cookie can be done as such:
req.cookies['cookie name']
which will return the value of the cookie.

Isomorphic Read cookie helper:
function getCookieValue(cookieName = '', cookie = '') {
const matches = cookie.match(`(^|[^;]+)\\s*${cookieName}\\s*=\\s*([^;]+)`)
return matches ? matches.pop() : ''
}
// Node with express:
getCookieValue('cookieName', req.headers.cookie)
// Browser:
getCookieValue('cookieName', document.cookie)
Write in Node with express:
res.cookie('cookieName', 'cookieValue')
Write in the browser:
function setCookie(
cname,
cvalue,
exdays = 100 * 365 /* 100 days */
) {
const now = new Date()
const expireMs = exdays * 24 * 60 * 60 * 1000
now.setTime(now.getTime() + expireMs)
document.cookie = `${cname}=${cvalue};expires=${now.toUTCString()};path=/`
}
// Example of usage
setCookie('cookieName', 'cookieValue')

If you have a problem with setting multiple cookies for one request
Try this way:
res.setHeader('Set-Cookie', [
`accessToken=${accessToken}; HttpOnly; Path=/; Max-Age=${60 * 60}; Secure=True;`,
`refreshToken=${refreshToken}; HttpOnly; Path=/; Max-Age=${60 * 60 * 24 * 7 * 2}; Secure=True;`
]);

Related

Node : How to identify if any user is opening the website more than one time

How can I identify if the same user is opening the website or not with node/express backend?
I've tried to set a cookie but don't know why it's removed automatically
Here's just a sample of how you can achieve it.
First install this npm package:
npm install express cookie-parser
Then a general setup:
const express = require('express')
const cookieParser = require('cookie-parser')
//to setup express app
const app = express()
app.use(cookieParser());
Bootstrap the rest of your liking.
Here's the important part for the cookies:
//an example route for setting cookies
app.get('/setcookie', (req, res) => {
res.cookie(`Cookie token name`,`encrypted cookie string Value`,{
maxAge: 5000,
// expires works the same as the maxAge
expires: new Date('01 12 2021'),
secure: true,
httpOnly: true,
sameSite: 'lax'
});
res.send('Cookie have been saved successfully');
});
If you want you may use this route to check the cookies from your browser (or look into the developer tools if your cookie name is set):
// get the cookie incoming request
app.get('/getcookie', (req, res) => {
//show the saved cookies
console.log(req.cookies)
res.send(req.cookies);
});
So in a nutshell this should do the trick :)
More details and examples of this approach can be found here.

How to create a cookie with node cookie-session

I am running a small node app. And I am trying to get it to create a cookie for each visitor, called 'session' that contains - for example - the session id. But I cannot seem to get node to create a cookie through cookie-session. My code so far:
const fs = require('fs');
const http = require('http');
const https = require('https');
const privateKey = fs.readFileSync('PATHTOKEY');
const certificate = fs.readFileSync('PATHTOKEY');
const credentials = {key: privateKey, cert: certificate};
const Keygrip = require("keygrip");
const express = require('express');
const app = express();
const port = APORTNUMBER;
const secureport = APORTNUMBER;
const helmet = require('helmet');
const options = {
dotfiles: 'deny',
etag: true,
extensions: ['html', 'htm'],
index: 'index.html',
lastModified: true,
maxAge: 0,
redirect: true,
setHeaders: function (res, path, stat) {
res.set('x-timestamp', Date.now())
}
};
app.use(express.static('public', options), helmet());
So far, no problems. But then comes the middleware cookie-session.
const session = require('cookie-session');
const expiryDate = new Date(Date.now() + 60 * 60 * 1000); // 1 hour
app.use(
session({
name: 'session',
keys: new Keygrip(["MYSECRET1", "MYSECRET2"]),
cookie: {
secure: true,
httpOnly: true,
expires: expiryDate
}
})
);
Above, I've specified the middleware to use these cookie-session parameters, but how do I proceed from here to actually get it to create this cookie?
const httpServer = http.createServer(app);
const httpsServer = https.createServer(credentials, app);
httpServer.listen(port);
httpsServer.listen(secureport);
console.log("Node server started");
Well, after trying this myself I manages to successfully use the cookie-session middleware. yay
I'm using the middleware like this:
app.use(cookieSession({
name: 'session', // replace this with your own name to suit your needs
keys: [ 'your-secret-key-goes-here', 'your-secret-key-goes-here' ]
})
About the duplicate values in keys option - the docs and related examples always use 2 different keys, despite the TypeScript #types lib declares that
The list of keys to use to sign & verify cookie values. Set cookies
are always signed with keys[0], while the other keys are valid for
verification, allowing for key rotation.
So.. I've used only one key.. twice... and it works as excepted
Note that I'm using this middleware before I'm registering the express app routes in order for this middleware to take effect before the router is executed (per request)
In each of my routes I can use the middleware using something like this
app.get('/test', (req, res) => {
req.session.test = { a: 5, b: 7} // yes - JSON payload are valid :)
})
To verify - ensure that your initial request got the following headers
Set-Cookie: session=eyJ0ZXN0Ijp7ImEiOjUsImIiOjd9fQ==; path=/; secure; httponly
Set-Cookie: session.sig=D4VVF4XSbBEWXI4b04ZvybAxppw; path=/; secure; httponly
This is only an example where the session is the name of the cookie as I've defined earlier. Cheers
Your current code looks right, based also on the documentation # http://expressjs.com/en/resources/middleware/cookie-session.html
I would suggest defining an app.get and testing everything with a tool like postman or fidler.
e.g.
app.get('/test', function (req, res, next) {
// Update views
req.session.views = (req.session.views || 0) + 1
// Write response
res.end(req.session.views + ' views')
})
I've not been able to figure out how to work with neither express-cookie nor cookie-session. However, I have been able to create cookies with cookie-parser middleware.
dependency:
const cookieParser = require('cookie-parser');
config:
const cookieConfig = {
httpOnly: true,
secure: true,
maxAge: 1800,
signed: true
};
Express:
app.use(cookieParser('MYSECRET'));
app.use(function (req, res, next) {
let cookie = req.cookies.cookieName;
if (cookie === undefined) {
let randomNumber=LOGICFORRANDOMNUMBER
res.cookie('COOKIENAME', randomNumber, cookieConfig);
};
next();
});

Renewing Cookie-session for express.js

I'm using the cookie-session module for Expresss.js to deal with sessions.
I would like the sessions to be renewed on every page load (or ajax call). That's how they usually work anywhere.
The documentation doesn't say a word about it.
I've tried doing this, but without success:
app.use(function(req,res,next ){
req.sessionOptions.maxAge = 20*1000;
return next();
});
I suspect that you are not sending the response cookie to the client. I solved the same problem (using express and cookie-session) with a middleware that sends a cookie containing a different value for each get:
var cookieSession = require('cookie-session')
app.use(cookieSession({
key: cookieKey,
secret: cookieSecret,
maxAge: 1 * 60 * 60 * 1000 // 1 hour (rolling)
})
);
app.get('*', function(req, res, next) {
// To update the session expiration time we need to send the new
// expiration in the response cookie.
// To send again the response cookie to the client we need to
// update the session object.
req.session.fake = Date.now();
next();
});
Indeed, if the session object does not change, cookie-session v. 1.2.0 does not set the Set-Cookie header to send the response cookie to the client.

Session variables in node express-session don't persist to the next request

I am using a basic node express-session setup with memory store and I have this code on the server:
app.use(require('express-session')({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true,
cookie: { secure: true }
}));
app.post('/api/logIn', function(req, res) {
req.session.userName = req.body.userName;
}
app.get('/api/getProfile', function(req, res) {
User.findOne({'userName' : req.session.userName},
function (err, userProfile) {
console.log('getProfile executed for user:' + req.session.userName);
if (err) throw err;
console.log(userProfile);
});
});
The problem is that req.session.userName from getProfile route is undefined, although it is not in the previous request to logIn route. I inspected HTTP headers and strangely there are no headers dealing with cookies, from the server or from the client. Right now I have no idea what could be the problem.
You say cookie: { secure: true }, but is your web server actually on a secure connection? If not, then the cookie won't be written.
From the docs:
Please note that secure: true is a recommended option. However, it
requires an https-enabled website, i.e., HTTPS is necessary for secure
cookies. If secure is set, and you access your site over HTTP, the
cookie will not be set.
Also its important to note if you are using fetch() to make your API calls to include { credentials: 'include' } in the options of your fetch() call. Otherwise the cookie will not set properly and your session will not persist. Make sure that on your server side you do something like:
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Credentials', true);
next();
});
so that your headers are set properly and cors wont be an issue. Took me awhile to figure this out but its working now!
The session need is stored in a cookie, so we use this to parse it, some like this:
var cookieParser = require('cookie-parser');
// must use cookieParser before expressSession
app.use(cookieParser());
Full example: http://code.runnable.com/U0tEnHwraXYyp-JG/simple-usage-of-express-session-and-cookie-parser-with-express-for-node-js

Set individual maxAge for sessions when using cookieSession() in connect/express

I am trying to use connect/express cookieSession() in order to store my node.js sessions in cookies (and thus, avoiding a server-side session store). This would help me to 'remember' the user when they log in and keep sessions alive even after server restarts.
I would like to do this with cookieSession():
app.use( express.cookieSession( { secret: 'secret_key' } ) );
app.use( function (req, res, next) {
if ( req.method == 'POST' && req.url == '/login' ) {
if ( req.body.remember ) {
req.session.cookie.maxAge = 30*24*60*60*1000; // Rememeber 'me' for 30 days
} else {
req.session.cookie.expires = false;
}
}
next();
});
However, this does not work, because req.session.cookie is undefined. I also tried the following, but it didn't seem to work:
app.use( express.session( { secret: 'secret_key' } ) );
app.use( function (req, res, next) {
if ( req.method == 'POST' && req.url == '/login' ) {
if ( req.body.remember ) {
req.cookies['connect.sess'].maxAge = 30*24*60*60*1000; // Rememeber 'me' for 30 days
} else {
rreq.cookies['connect.sess'].expires = false;
}
}
next();
});
Starting out with
app.use(express.cookieSession({ secret: config.server.cookieSecret }));
And changing it to
app.use(function(req, res, next) {
express.cookieSession({
secret: config.server.cookieSecret,
cookie: {
maxAge: req.param('remember') ? 20000 : 3000
},
})(req, res, next);
})
So, we create our own middleware, wrapped around the cookieSession middleware, changing the maxAge based on a param.
So, whenever you change the session you'll need to pass a remember in the body, query, or params( that's where req.param() looks ). In most cases, you only set a user_id to the session once, at login.
It's 3 seconds or 20 seconds to test and ensure it works.
And again, it might be not very helpful if you're setting stuff to your session a lot, but if you just set a user_id to session at login, this is all you need.
If you are setting lots of stuff to your session, you should know that data get passed around at every request, and you should save only the minimum to the session, like user_id, then look up the data you need for each request, to keep the overhead down on the user.
I think this does what you want:
// Using express.session instead of express.cookieSession
app.use(express.session({ secret : 'secret_key' }));
app.use( function (req, res, next) {
if ( req.method === 'POST' && req.url === '/login' ) {
if ( req.body.remember )
{
req.session.cookie.maxAge = 30*24*60*60*1000;
// needed to make the session `dirty` so the session middleware re-sets the cookie
req.session.random = Math.random();
}
else
{
req.session.cookie.expires = false;
}
}
next();
});
cookieSession does some funky stuff, like del req.session.cookie (not sure why).
You have to first set req.session.cookie so that you can set maxAge. Trying to use it before you set it gives req.session.cookie is undefined
express.cookieSession has default values which it accepts, see here. You should mention all the parameters you are going to use. You can set cookie via the following :
app.use(express.cookieSession({ secret: 'secret_key', cookie :{ path: '/', httpOnly: true, maxAge: 30*24*60*60*1000} });
A little late to the table but I thought this answer may help people going forward...
I was using cookie-session which doesn't create a cookie object on request.session. To properly implement rememberMe functionality using request.session.cookie I switched cookie-session to express-session and that solved everything. So now there is a cookie object on session and doing this inside of a request is possible...
npm install express-session
app.post('/login', function(request, response, next) {
passport.authenticate('local', function(err, user, info) {
if(err) return next(err);
if(!user) {
request.flash('loginMessage', info.message);
return response.redirect('/account/login');
}
request.login(user, function(err) {
if(err) return next(err);
if(request.body.rememberMe)
request.session.cookie.maxAge = 2592000000;
else
request.session.cookie.expires = false;
return response.redirect(options.redirect);
});
})(request, response, next);
});
This is also pretty late but it might help other people.
It seems like to me the best way to persist your session data is to store it in something like redis. The question asked for a way that didn't use server storage, but I think he was referring more to MemoryStore. Maybe not but either way this is what I did.
I used express-session and connect-redis
npm install -g connect-redis
npm install -g express-session
Then you configure stuff.
// session modules
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session')
var redisStore = require('connect-redis')(session); // this sets up Redis to work with your session cookies
var app = express();
Then you just initiate your session with the store option set to your redisStore.
The maxAge part sets the lifetime of each session to an hour, the session middleware resets it when it's accessed.
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(session({
store: new RedisStore({
host:'127.0.0.1',
port:6380,
prefix:'sess'
}),
cookie: {maxAge: 3600000 },
secret: 'session_secret'
}));
Now when a client connects, express should store the session data automatically in a Redis data structure. Since it's not just cached in memory, your server can crash and still have all the relevant session data still available at the IP address and and port specified.
Yummy seems to allow modifying cookies expiry after creation.

Resources