Skip to content

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.

License

Notifications You must be signed in to change notification settings

dmkng/fastify-sessions

 
 

Repository files navigation

fastify-sessions

npm version npm total downloads npm monthly downloads npm license
build status dependencies status

Features

Session plugin for fastify supporting both stateless and stateful sessions, fork of @mgcrea/fastify-session adding a lot of features while keeping compatibility.

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, { SessionData, 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: SessionData): Promise<Buffer> => pack(session),
      deserialize: async (session: Buffer): Promise<SessionData> => 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

About

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.

Topics

Resources

License

Stars

Watchers

Forks

Languages

  • TypeScript 100.0%