@fastify/session
A session plugin for fastify. Requires the fastify-cookie plugin.
NOTE: This is the continuation of fastify-session which is unmaintained by now. All work credit till e201f7
commit goes to SerayaEryn and contributors.
Install
npm install @m0dch3n/fastify-session
Usage
const fastify = require('fastify');
const fastifySession = require('@fastify/session');
const fastifyCookie = require('fastify-cookie');
const app = fastify();
app.register(fastifyCookie);
app.register(fastifySession, {secret: 'a secret with minimum length of 32 characters'});
Store data in the session by adding it to the session
decorator at the request
:
app.register(fastifySession, {secret: 'a secret with minimum length of 32 characters'});
app.addHook('preHandler', (request, reply, next) => {
request.session.user = {name: 'max'};
next();
})
NOTE: For all unencrypted (HTTP) connections, you need to set the secure
cookie option to false
. See below for all cookie options and their details.
The sessionStore
decorator of the request
allows to get, save and delete sessions.
app.register(fastifySession, {secret: 'a secret with minimum length of 32 characters'});
app.addHook('preHandler', (request, reply, next) => {
const session = request.session;
request.sessionStore.destroy(session.sessionId, next);
})
Examples
API
session(fastify, options, next)
The session plugin accepts the following options. It decorates the request with the sessionStore
and a session
object. The session data is stored server-side using the configured session store.
options
secret (required)
The secret used to sign the cookie. Must be an array of strings or a string with a length of 32 or greater.
If an array, the first secret is used to sign new cookies and is the first to be checked for incoming cookies. Further secrets in the array are used to check incoming cookies in the order specified.
Note that the rest of the application may manipulate the array during its life cycle. This can be done by storing the array in a separate variable that is later used with mutating methods like unshift(), pop(), splice(), etc. This can be used to rotate the signing secret at regular intervals. A secret should remain somewhere in the array as long as there are active sessions with cookies signed by it. Secrets management is left up to the rest of the application.
cookieName (optional)
The name of the session cookie. Defaults to sessionId
.
cookie
The options object is used to generate the Set-Cookie
header of the session cookie. May have the following properties:
-
path
- ThePath
attribute. Defaults to/
(the root path). -
maxAge
- Anumber
in milliseconds that specifies theExpires
attribute by adding the specified milliseconds to the current date. If bothexpires
andmaxAge
are set, thenmaxAge
is used. -
httpOnly
- Theboolean
value of theHttpOnly
attribute. Defaults to true. -
secure
- Theboolean
value of theSecure
attribute. Set this option to false when communicating over an unencrypted (HTTP) connection. Value can be set toauto
; in this case, theSecure
attribute will be set to false for an HTTP request. In the case of HTTPS, it will be set to true. Defaults to true. -
expires
- The expirationdate
used for theExpires
attribute. If bothexpires
andmaxAge
are set, thenmaxAge
is used. -
sameSite
- Theboolean
orstring
of theSameSite
attribute. UsingSecure
mode withauto
attribute will change the behavior of theSameSite
attribute inhttp
mode. TheSameSite
attribute will automatically be set toLax
with anhttp
request. See this link. -
domain
- TheDomain
attribute.
store
A session store. Needs the following methods:
- set(sessionId, session, callback)
- get(sessionId, callback)
- destroy(sessionId, callback)
Compatible to stores from express-session.
Defaults to a simple in-memory store. Note: The default store should not be used in a production environment because it will leak memory.
saveUninitialized (optional)
Save sessions to the store, even when they are new and not modified— defaults to true
.
Setting this to false
can save storage space and comply with the EU cookie law.
idGenerator(request) (optional)
Function used to generate new session IDs. Defaults to uid(24)
.
Custom implementation example:
idGenerator: (request) => {
if (request.session.returningVisitor) return `returningVisitor-${uid(24)}`
else return uid(24)
}
request.session
Allows to access or modify the session data.
request.destroySession(callback)
Allows to destroy the session in the store
Session#touch()
Updates the expires
property of the session.
Session#regenerate(request)
Regenerates the session by generating a new sessionId
. Don't forget to pass the request
object if the idGenerator
function parameter uses it.
fastify.get('/regenerate', (request, reply) => {
request.session.regenerate(request);
reply.send(request.session.sessionId);
});
Session#get(key)
Gets a value from the session
Session#set(key, value)
Sets a value in the session
fastify.decryptSession(sessionId, request, cookieOptions, next)
This plugin also decorates the fastify instance with decryptSession
in case you want to decrypt the session manually.
const { sessionId } = fastify.parseCookie(cookieHeader);
const request = {}
fastify.decryptSession(sessionId, request, () => {
// request.session should be available here
})
// or decrypt with custom cookie options:
fastify.decryptSession(sessionId, request, { maxAge: 86400 }, () => {
// ...
})
Typescript support:
This plugin supports typescript, and you can extend fastify module to add your custom session type.
declare module "fastify" {
interface Session {
user_id: string
other_key: your_prefer_type
id?: number
}
}
While this plugin can be used with express-session compatible stores, the type definitions of some stores might be tied to express-session, which means that casting to any
might be required. For example:
import fastifySession from '@fastify/session'
import fastify from 'fastify'
import Redis from 'ioredis'
import connectRedis from 'connect-redis'
const RedisStore = connectRedis(fastifySession as any)
const redisClient = new Redis(redisConfig)
const server = fastify()
server.register(fastifySession, {
store: new RedisStore({
client: redisClient,
// ... other options
}) as any,
// ... other options
})