To store confidential session data, we can use the express-session
package. It stores the session data on the server and gives the client a session ID to access the session data.
In this article, we’ll look at how to use it to store temporary user data.
Installation
express-session
is a Node package. We can install it by running:
npm install express-session
Then we can include it in our app by adding:
const session = require('express-session');
Usage
The session
function returns a middleware to let us store sessions. It takes an option object with the following properties:
cookie
Settings object for the session ID cookie. The default value is:
{ path: '/', httpOnly: true, secure: false, maxAge: null }.
It takes the following properties:
cookie.domain
It specifies the value for the Domain Set-Cookie
attribute. No domain is set by default. Most clients will consider the cookie to apply only to the current domain.
cookie.expires
This specifies the Date
object of the value for the Expires Set-Cookie
attribute. No expiration date is set by default. This means the cookie will be deleted when the session ends.
If both expires
and maxAge
are set, then the last one defined if what’s used. expires
shouldn’t be set directly. We should set maxAge
.
cookie.httpOnly
Specifies the boolean value for the HttpOnly Set-Cookie
attribute. When it’s truthy, the HttpOnly
attribute is set. Otherwise, it’s not. By default, only HttpOnly
attribute is set.
cookie.maxAge
The number of milliseconds to use when calculating the Expires Set-Cookie
attribute. This is calculated by taking the current server time and adding maxAge
milliseconds to it to calculate the Expires
datetime. No maximum age is set by default.
cookie.path
Sets the Path Set-Cookie
attribute value. This is set to /
by default which is the root path of the domain.
cookie.sameSite
A boolean or string for the value of the SameSite Set-Cookie
attribute. It can be:
true
— will set theSameSite
attribute toStrict
for strict same site enforcementfalse
— won’t set theSameSite
attribute'lax'
— set theSameSite
attribute toLax
for lax same-site enforcement'strict'
set theSameSite
attribute toStrict
for strict same-site enforcement
cookie.secure
Boolean value for the Secure Set-Cookie
attribute. The Secure
attribute is set. Otherwise, it’s not.
Cookies won’t be sent over HTTP connects if this is set to true
.
However, it’s recommended. If the app is hosted behind a proxy, then trust proxy
must be set if secure
is set to true
.
genid
A function to generate a new session ID. The default value is a function that uses the uid-safe
library to generate IDs.
name
The name of the session ID cookie to set in the response. The default value is 'connect.sid'
.
proxy
Trust the reverse proxy when setting cookies via the X-Forwarded-Proto
header.
The default value is undefined
. Other possibles include:
true
— theX-Forwarded-Proto
header will be usedfalse
— all headers are ignored and the connection is considered secure only if it’s a direct SSL/TLS connectionundefined
— uses the'trust proxy'
setting from Express
resave
Forces the session to be saved back to the session store even if the session was never modified during the request.
This may create race conditions when a client makes 2 parallel requests to our server and changes made to the session on one request may be overwritten when the other request ends.
Defaults to true
, but the default may change in the future. false
makes more sense as the option.
rolling
Force a session identifier cookie to be set on every response. The expiration is reset to the original maxAge
, resetting the expiration countdown.
Defaults to false
.
When this is set to true
and saveUnintialized
option is false
, the cookie won’t be set on a response with uninitialized session
saveUnitialized
Force a session that’s uninitialized to be saved to the store. A session is uninitialized when it’s new but not modified. Setting this to false
reduces server storage usage and comply with laws that require permission before storing cookies.
secret
This is a required option for the secret to sign the session ID cookie. It can be a string or an array of multiple string secrets.
store
The session store instance. It defaults to a new MemoryStore
instance.
unset
Controls the result of unsetting req.session
through delete
, setting to null
, etc.
Defaults to 'keep'
. The possible values are:
'destroy'
— the session will be deleted when the response ends'keep'
— the session will be kept but modifications made during the request aren’t saved.
req.session
We access the session data by using req.session
. The data is typically JSON, so nested objects are fine.
req.session
comes with the following methods:
regenerate(callback)
We call this to regenerate the session. Once it’s called, a new session ID and Session
instance will be initialized at req.session
and the callback
will be called.
destroy(callback)
Destroys a session. req.session
will be unset. Once it’s called, the callback
will be called.
reload(callback)
Reloads the session data from the store and re-populates the req.session
object. Once it’s done, the callback
will be called.
save(callback)
Saves a session back to the store, replacing the contents of the store with the contents in memory.
This usually doesn’t need to be called.
touch()
Updates the maxAge
property. This shouldn’t be called usually as this is done automatically.
id
We can get the session ID with the id
property.
cookie
This property has the cookie content. This also lets us alter the cookie for the user.
Cookie.maxAge
We can set the maxAge
property to change the expiry time in milliseconds.
Cookie.originalMaxAge
We can use this to get the original maxAge
value in milliseconds.
req.sessionID
We can get the session ID of the loaded session with sessionId
.
Implementing our Own Session Store
Session store must implement EventEmitter
with additional methods.
store.all(callback)
An optional method to get all sessions in the store as an array. The callback
signature is callback(error, sessions)
and it’s called once the session is retrieved.
store.destroy(sid, callback)
A required method to delete a session from the store given the session ID. The callback has the signaturecallback(error)
. It’s called once the session is deleted.
store.clear(callback)
An optional method to delete all sessions from the store. The callback signature is callback(error)
and it called once the store is cleared.
store.length(callback)
An optional method to count all the sessions in the store. The callback has the signature callback(error, len)
.
store.get(sid, callback)
A required method to get the session data by the session ID (sid
). The callback has the signature callback(error, session)
.
The session is returned if found, otherwise returns null
or undefined
.
store.set(sid, session, callback)
A required method to set the session given the sid
, which is the session ID. The callback has the signature callback(error)
once the session is set.
store.touch(sid, session, callback)
This method is suggested to be implemented. This is used to signal to the store that the given session is active. The callback has the signature callback(error)
.
Example
An example would be storing the number of views and keep that data for 365 days. We can do that as follows:
const express = require('express');
const bodyParser = require('body-parser');
const session = require('express-session');
const app = express();
app.set('trust proxy', 1)
app.use(session({
secret: 'secret',
resave: true,
cookie: {
maxAge: 24 * 60 * 60 * 365 * 1000
}
}))
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/', (req, res) => {
if (req.session.views) {
req.session.views++;
}
else {
req.session.views = 1;
}
res.send(`${req.session.views} views`);
})
app.listen(3000);
In the code, we have the secret
so that the cookie will be signed. Then in our route handler, we can get and set the data by getting and setting req.session.views
, which we created.
Then we should see the number of views as we keep reloading the /
route. It sets to expire in 365 days by setting maxAge
, so the number will keep going up.
In the response header, we should get that the Set-Cookie
response header has a value like:
connect.sid=s%3Ad6jfPu5awWj3EXPF-MdtU8cPzjOY5NRT.33nyXjKdShPAPyw9WWwY4sywP44IOX5SPSt2WUkH0cs; Path=/; Expires=Mon, 28 Dec 2020 00:47:31 GMT; HttpOnly
We have the value of the session ID and expiry time.
Conclusion
We can use the express-session
package to keep session cookie data on the server-side.
There’re many options like the content of various cookie attributes and the time to expiry.
Other settings like the ID, whether to save cookie only in HTTPS and so on can be set.
The cookies will be stored in a session store. We can also implement our own store if we aren’t satisfied with the existing stores that are available for us to use.