To store sessions in our Express apps, we can use the cookie-session
middleware.
It’s a cookie-based session middleware that stores user sessions on the client within a cookie.
In this article, we’ll look at how to store sessions within an Express app with the cookie-session
middleware.
How Cookie-Session Stores Sessions?
cookie-session
doesn’t require any database or other server-side resources to store sessions. The session data can’t exceed the browser’s max cookie side.
It can also simplify certain load-balanced scenarios. It can also store a light session and include an identifier to look up a database-backed secondary store to reduce database lookups.
Adding the Library
We can install cookie-session
by running:
npm i cookie-session
Then we can use it as follows:
const cookieSession = require('cookie-session')
const express = require('express')
const app = express()
app.use(cookieSession({
name: 'session',
keys: 'secret',
maxAge: 24 * 60 * 60 * 1000
}))
Options
The cookie-session
middleware lets us pass in an options
object with various properties to set the value.
This middleware will automatically add a Set-Cookie
header to the response if the contents of the req.session
were altered.
The Set-Cookie
header won’t be in the response unless there are contents in the session, so we should add something to req.session
as soon as we have identifying information to store the session.
The following options are available:
name
Name of the cookie to be set and defaults to session
.
keys
The list of keys to sign and verify cookie values, or a Keygrip
instance. Set cookies are always signed with keys[0]
, and other keys are valid for verification.
This allows for key rotation. It can be used to change signature parameters like the algorithm of the signature.
secret
The string will be used as a single key if keys
isn’t provided.
Cookie Options
The cookie
object within the options have the following properties:
maxAge
— a number of milliseconds fromDate.now()
for expiryexpires
— aDate
object indicating the cookie’s expiration datepath
— a string indicating the path of the cookie, which defaults to/
domain
— a sting indication the domain of the cookiesameSite
— boolean or string indicating whether the cookie is a ‘same site’ cookie. The default value isfalse
,'strict'
,'lax'
ortrue
are other possible valuessecure
— boolean indicating whether the cookie is only sent over HTTPS. If this istrue
and communication isn’t through TLS, then the cookie may not be set correctlyhttpOnly
— boolean indicating whether the cookie is sent over HTTP(S) and not available to client JavaScriptsigned
— boolean indicating whether the cookie is signed. Default value istrue
. If it’strue
, then the cookie is appended with a.sig
suffix.overwrite
— boolean indicating whether to overwrite previously set cookies of the same name
req.session
req.session
holds the session for the given request.
.isChanged
A method that returns trie
is the session has been changed during the request.
.isNew
A method that returns true
if the session is new.
.isPopulated
A method that returns true
is the session has been populated with data.
req.sessionOptions
We can set the sessionOptions
object to change cookie settings.
Destroying a Session
We can set req.session
to null
to destroy a session.
Example
We can track the number of views a user made as follows:
const express = require('express');
const bodyParser = require('body-parser');
const cookieSession = require('cookie-session');
const app = express();
app.set('trust proxy', 1);
app.use(cookieSession({
name: 'session',
keys: ['key1', 'key2']
}))
app.get('/', (req, res, next) => {
req.session.numViews = (req.session.numViews || 0) + 1
res.end(`${req.session.numViews} views`);
})
app.listen(3000);
In the code above, we just set req.session
with the properties that we want to add and set the values the way we want.
The numViews
property is added to track the number of views and increments as more request to the /
is made.
Setting Max Age
We can set the maxAge
as follows:
const express = require('express');
const bodyParser = require('body-parser');
const cookieSession = require('cookie-session');
const app = express();
app.set('trust proxy', 1);
app.use(cookieSession({
name: 'session',
keys: ['key1', 'key2'],
maxAge: 1000,
}))
app.use((req, res, next) => {
req.sessionOptions.maxAge = req.session.maxAge || req.sessionOptions.maxAge
next()
})
app.get('/', (req, res, next) => {
req.session.numViews = (req.session.numViews || 0) + 1
res.end(`${req.session.numViews} views`);
})
app.listen(3000);
We set maxAge
to 1000 milliseconds above, then we’ll see that the values reset to 1 as the session expires.
In both cases, the Set-Cookie
response header will be set as the session is set for the client.
We have multiple keys with the first one for encryption and the second one for verification.
Keygrip Integration
We can use keygrip
as follows for encrypting our sessions:
const express = require('express');
const bodyParser = require('body-parser');
const cookieSession = require('cookie-session');
const Keygrip = require('keygrip');
const app = express();
app.set('trust proxy', 1);
app.use(cookieSession({
name: 'session',
keys: new Keygrip(['key1', 'key2'], 'SHA384'),
maxAge: 60 * 60 * 1000,
}))
app.use((req, res, next) => {
req.sessionOptions.maxAge = req.session.maxAge || req.sessionOptions.maxAge
next()
})
app.get('/', (req, res, next) => {
req.session.numViews = (req.session.numViews || 0) + 1
res.end(`${req.session.numViews} views`);
})
app.listen(3000);
In the code above, we set the encryption algorithm to SHA384
for secure encryption.
Conclusion
The cookie-session
lets us store sessions securely. We can use it to store identifying information about a user securely by encrypting the content with keys.
Then we can get and set the data via req.session
.
Various options are also available for sessions. We can set maxAge
to set when the session expires.
We can use domain
, path
, sameSite
, secure
, and httpOnly
to control what kind of domain and path to set in our cookies, and also set what sites the cookies will be set for.
cookie-session
also works with Keygrip for encryption.