fastify-sessions
v1.0.0
Published
Session plugin for fastify written in TypeScript supporting both stateless and stateful sessions, fork of @mgcrea/fastify-session adding a lot of features while keeping compatibility.
Downloads
4
Readme
fastify-sessions
Features
Session plugin for fastify supporting both stateless and stateful sessions, fork of @mgcrea/fastify-session adding a lot of features while keeping compatibility.
Requires @fastify/cookie to handle cookies.
Works with fastify
^4.0.0
starting from>=0.16.0
.Can leverage crypto addons like @mgcrea/fastify-session-sodium-crypto to perform crypto.
Can leverage store addons like:
Built with TypeScript for static type checking with exported types along the library.
Install
npm install fastify-sessions @fastify/cookie
# or
pnpm add fastify-sessions @fastify/cookie
Quickstart
Basic example (signed session with hmac stored in a volatile in-memory store)
Defaults to a volatile in-memory store for sessions (great for tests), with HMAC for signature.
import createFastify, { FastifyInstance, FastifyServerOptions } from "fastify";
import fastifyCookie from "@fastify/cookie";
import fastifySessions from "fastify-sessions";
const SESSION_SECRET = "a secret with minimum length of 32 characters";
const SESSION_TTL = 86400; // 1 day in seconds
export const buildFastify = (options?: FastifyServerOptions): FastifyInstance => {
const fastify = createFastify(options);
fastify.register(fastifyCookie);
fastify.register(fastifySessions, {
secret: SESSION_SECRET,
cookie: { maxAge: SESSION_TTL },
});
return fastify;
};
Production example (signed session with sodium stored in redis)
For better performance/security, you can use the @mgcrea/fastify-session-sodium-crypto addon:
Leveraging an external redis store, the session id (generated with nanoid) is signed using a secret-key with libsodium's crypto_auth
import createFastify, { FastifyInstance, FastifyServerOptions } from "fastify";
import fastifyCookie from "@fastify/cookie";
import fastifySessions from "fastify-sessions";
import { SODIUM_AUTH } from "@mgcrea/fastify-session-sodium-crypto";
const SESSION_KEY = "Egb/g4RUumlD2YhWYfeDlm5MddajSjGEBhm0OW+yo9s=";
const SESSION_TTL = 86400; // 1 day in seconds
const REDIS_URI = process.env.REDIS_URI || "redis://localhost:6379/1";
export const buildFastify = (options?: FastifyServerOptions): FastifyInstance => {
const fastify = createFastify(options);
fastify.register(fastifyCookie);
fastify.register(fastifySessions, {
key: Buffer.from(SESSION_KEY, "base64"),
crypto: SODIUM_AUTH,
store: new RedisStore({ client: new Redis(REDIS_URI), ttl: SESSION_TTL }),
cookie: { maxAge: SESSION_TTL },
});
return fastify;
};
Stateless example (encrypted session with sodium not using a store)
No external store required, the entire session data is encrypted using a secret-key with libsodium's crypto_secretbox_easy
Here we used a secret
instead of providing a key
, key derivation will happen automatically on startup.
import createFastify, { FastifyInstance, FastifyServerOptions } from "fastify";
import fastifyCookie from "@fastify/cookie";
import fastifySessions from "fastify-sessions";
import { SODIUM_SECRETBOX } from "@mgcrea/fastify-session-sodium-crypto";
const SESSION_TTL = 86400; // 1 day in seconds
export const buildFastify = (options?: FastifyServerOptions): FastifyInstance => {
const fastify = createFastify(options);
fastify.register(fastifyCookie);
fastify.register(fastifySessions, {
secret: "a secret with minimum length of 32 characters",
crypto: SODIUM_SECRETBOX,
cookie: { maxAge: SESSION_TTL },
});
return fastify;
};
Stateless example with custom data serialization
Here we used msgpackr to serialize the data instead of the default JSON and also disabled generating/saving the session ID.
import createFastify, { FastifyInstance, FastifyServerOptions } from "fastify";
import fastifyCookie from "@fastify/cookie";
import fastifySessions, { StatelessStore } from "fastify-sessions";
import { SODIUM_SECRETBOX } from "@mgcrea/fastify-session-sodium-crypto";
import { pack, unpack } from "msgpackr";
const SESSION_KEY = 'Egb/g4RUumlD2YhWYfeDlm5MddajSjGEBhm0OW+yo9s=';
const SESSION_TTL = 86400; // 1 day in seconds
export const buildFastify = (options?: FastifyServerOptions): FastifyInstance => {
const fastify = createFastify(options);
fastify.register(fastifyCookie);
fastify.register(fastifySessions, {
key: Buffer.from(SESSION_KEY, 'base64'),
crypto: SODIUM_SECRETBOX,
store: new StatelessStore({
serialize: async (session: T): Promise<Buffer> => pack(session),
deserialize: async (session: Buffer): Promise<T> => unpack(session),
useId: false
}),
cookie: { maxAge: SESSION_TTL },
});
return fastify;
};
Benchmarks
Session crypto sealing
npm run benchmark:cryptoSeal
SODIUM_SECRETBOX#sealMsgpack x 653,658 ops/sec ±0.25% (90 runs sampled)
SODIUM_SECRETBOX#sealJson x 647,044 ops/sec ±0.25% (93 runs sampled)
SODIUM_AUTH#sealJson x 421,055 ops/sec ±0.18% (95 runs sampled)
HMAC#sealJson x 195,364 ops/sec ±0.35% (92 runs sampled)
Fastest is SODIUM_SECRETBOX#sealMsgpack
Session crypto unsealing
npm run benchmark:cryptoUnseal
SODIUM_SECRETBOX#unsealMsgpack x 527,228 ops/sec ±0.36% (89 runs sampled)
SODIUM_SECRETBOX#unsealJson x 507,172 ops/sec ±0.29% (92 runs sampled)
SODIUM_AUTH#unsealJson x 347,371 ops/sec ±0.24% (93 runs sampled)
HMAC#unsealJson x 108,809 ops/sec ±0.76% (92 runs sampled)
Fastest is SODIUM_SECRETBOX#unsealMsgpack
Session crypto serializing
npm run benchmark:cryptoSerialize
SODIUM_SECRETBOX#serializeMsgpack x 473,983 ops/sec ±0.31% (93 runs sampled)
SODIUM_SECRETBOX#serializeJson x 327,130 ops/sec ±0.26% (92 runs sampled)
Fastest is SODIUM_SECRETBOX#serializeMsgpack
Session crypto deserializing
npm run benchmark:cryptoDeserialize
SODIUM_SECRETBOX#deserializeMsgpack x 372,287 ops/sec ±0.24% (91 runs sampled)
SODIUM_SECRETBOX#deserializeJson x 318,034 ops/sec ±0.24% (89 runs sampled)
Fastest is SODIUM_SECRETBOX#deserializeMsgpack
Authors
Credits
Heavily inspired from