Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@auth0/auth0-fastify

Package Overview
Dependencies
Maintainers
44
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@auth0/auth0-fastify - npm Package Compare versions

Comparing version
1.0.2
to
1.1.0
+55
-232
dist/index.cjs

@@ -33,3 +33,3 @@ "use strict";

__export(index_exports, {
CookieTransactionStore: () => CookieTransactionStore,
CookieTransactionStore: () => import_auth0_server_js2.CookieTransactionStore,
default: () => index_default

@@ -39,7 +39,27 @@ });

var import_fastify_plugin = __toESM(require("fastify-plugin"), 1);
var import_auth0_server_js4 = require("@auth0/auth0-server-js");
// src/store/cookie-transaction-store.ts
var import_auth0_server_js = require("@auth0/auth0-server-js");
// src/utils.ts
function ensureTrailingSlash(value) {
return value && !value.endsWith("/") ? `${value}/` : value;
}
function ensureNoLeadingSlash(value) {
return value && value.startsWith("/") ? value.substring(1, value.length) : value;
}
function createRouteUrl(url, base) {
return new URL(ensureNoLeadingSlash(url), ensureTrailingSlash(base));
}
function toSafeRedirect(dangerousRedirect, safeBaseUrl) {
let url;
try {
url = createRouteUrl(dangerousRedirect, safeBaseUrl);
} catch {
return void 0;
}
if (url.origin === new URL(safeBaseUrl).origin) {
return url.toString();
}
return void 0;
}
// src/errors/index.ts

@@ -54,233 +74,36 @@ var MissingStoreOptionsError = class extends Error {

// src/store/cookie-transaction-store.ts
var CookieTransactionStore = class extends import_auth0_server_js.AbstractTransactionStore {
async set(identifier, transactionData, removeIfExists, options) {
if (!options) {
// src/store/fastify-cookie-handler.ts
var FastifyCookieHandler = class {
setCookie(name, value, options, storeOptions) {
if (!storeOptions) {
throw new MissingStoreOptionsError();
}
const maxAge = 60 * 60;
const cookieOpts = { httpOnly: true, sameSite: "lax", path: "/", maxAge };
const expiration = Math.floor(Date.now() / 1e3 + maxAge);
const encryptedStateData = await this.encrypt(identifier, transactionData, expiration);
options.reply.setCookie(identifier, encryptedStateData, cookieOpts);
storeOptions.reply.setCookie(name, value, options || {});
}
async get(identifier, options) {
if (!options) {
getCookie(name, storeOptions) {
if (!storeOptions) {
throw new MissingStoreOptionsError();
}
const cookieValue = options.request.cookies[identifier];
if (cookieValue) {
return await this.decrypt(identifier, cookieValue);
}
return storeOptions.request.cookies?.[name];
}
async delete(identifier, options) {
if (!options) {
getCookies(storeOptions) {
if (!storeOptions) {
throw new MissingStoreOptionsError();
}
options?.reply.clearCookie(identifier);
return storeOptions.request.cookies;
}
};
// src/store/stateless-state-store.ts
var import_auth0_server_js3 = require("@auth0/auth0-server-js");
// src/store/abstract-session-store.ts
var import_auth0_server_js2 = require("@auth0/auth0-server-js");
var AbstractSessionStore = class extends import_auth0_server_js2.AbstractStateStore {
#rolling;
#absoluteDuration;
#inactivityDuration;
constructor(options) {
super(options);
this.#rolling = options.rolling ?? true;
this.#absoluteDuration = options.absoluteDuration ?? 60 * 60 * 24 * 3;
this.#inactivityDuration = options.inactivityDuration ?? 60 * 60 * 24 * 1;
}
/**
* calculateMaxAge calculates the max age of the session based on createdAt and the rolling and absolute durations.
*/
calculateMaxAge(createdAt) {
if (!this.#rolling) {
return this.#absoluteDuration;
}
const now = Date.now() / 1e3 | 0;
const expiresAt = Math.min(now + this.#inactivityDuration, createdAt + this.#absoluteDuration);
const maxAge = expiresAt - now;
return maxAge > 0 ? maxAge : 0;
}
};
// src/store/stateless-state-store.ts
var StatelessStateStore = class extends AbstractSessionStore {
#cookieOptions;
constructor(options) {
super(options);
this.#cookieOptions = options.cookie;
}
async set(identifier, stateData, removeIfExists, options) {
if (!options) {
deleteCookie(name, storeOptions) {
if (!storeOptions) {
throw new MissingStoreOptionsError();
}
const maxAge = this.calculateMaxAge(stateData.internal.createdAt);
const cookieOpts = {
httpOnly: true,
sameSite: this.#cookieOptions?.sameSite ?? "lax",
path: "/",
secure: this.#cookieOptions?.secure ?? "auto",
maxAge
};
const expiration = Math.floor(Date.now() / 1e3 + maxAge);
const encryptedStateData = await this.encrypt(identifier, stateData, expiration);
const chunkSize = 3072;
const chunkCount = Math.ceil(encryptedStateData.length / chunkSize);
const chunks = [...Array(chunkCount).keys()].map((i) => ({
value: encryptedStateData.substring(i * chunkSize, (i + 1) * chunkSize),
name: `${identifier}.${i}`
}));
chunks.forEach((chunk) => {
options.reply.setCookie(chunk.name, chunk.value, cookieOpts);
});
const existingCookieKeys = this.getCookieKeys(identifier, options);
const cookieKeysToRemove = existingCookieKeys.filter((key) => !chunks.some((chunk) => chunk.name === key));
cookieKeysToRemove.forEach((key) => {
options.reply.clearCookie(key);
});
storeOptions.reply.clearCookie(name);
}
async get(identifier, options) {
if (!options) {
throw new MissingStoreOptionsError();
}
const cookieKeys = this.getCookieKeys(identifier, options);
const encryptedStateData = cookieKeys.map((key) => ({ index: parseInt(key.split(".")[1], 10), value: options.request.cookies[key] })).sort((a, b) => a.index - b.index).map((item) => item.value).join("");
if (encryptedStateData) {
return await this.decrypt(identifier, encryptedStateData);
}
}
async delete(identifier, options) {
if (!options) {
throw new MissingStoreOptionsError();
}
const cookieKeys = this.getCookieKeys(identifier, options);
for (const key of cookieKeys) {
options?.reply.clearCookie(key);
}
}
deleteByLogoutToken() {
throw new import_auth0_server_js3.BackchannelLogoutError(
"Backchannel logout is not available when using Stateless Storage. Use Stateful Storage by providing a `sessionStore`"
);
}
getCookieKeys(identifier, options) {
return Object.keys(options.request.cookies).filter((key) => key.startsWith(identifier));
}
};
// src/store/stateful-state-store.ts
var generateId = () => {
const bytes = new Uint8Array(16);
crypto.getRandomValues(bytes);
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
};
var StatefulStateStore = class extends AbstractSessionStore {
#store;
#cookieOptions;
constructor(options) {
super(options);
this.#store = options.store;
this.#cookieOptions = options.cookie;
}
async set(identifier, stateData, removeIfExists, options) {
if (!options) {
throw new MissingStoreOptionsError();
}
let sessionId = await this.getSessionId(identifier, options);
if (sessionId && removeIfExists) {
await this.#store.delete(sessionId);
sessionId = generateId();
}
if (!sessionId) {
sessionId = generateId();
}
const maxAge = this.calculateMaxAge(stateData.internal.createdAt);
const cookieOpts = {
httpOnly: true,
sameSite: this.#cookieOptions?.sameSite ?? "lax",
path: "/",
secure: this.#cookieOptions?.secure ?? "auto",
maxAge
};
const expiration = Date.now() / 1e3 + maxAge;
const encryptedStateData = await this.encrypt(
identifier,
{
id: sessionId
},
expiration
);
await this.#store.set(sessionId, stateData);
options.reply.setCookie(identifier, encryptedStateData, cookieOpts);
}
async get(identifier, options) {
if (!options) {
throw new MissingStoreOptionsError();
}
const sessionId = await this.getSessionId(identifier, options);
if (sessionId) {
const stateData = await this.#store.get(sessionId);
if (!stateData) {
options?.reply.clearCookie(identifier);
}
return stateData;
}
}
async delete(identifier, options) {
if (!options) {
throw new MissingStoreOptionsError();
}
const sessionId = await this.getSessionId(identifier, options);
if (sessionId) {
await this.#store.delete(sessionId);
}
options?.reply.clearCookie(identifier);
}
async getSessionId(identifier, options) {
const cookieValue = options.request.cookies[identifier];
if (cookieValue) {
const sessionCookie = await this.decrypt(identifier, cookieValue);
return sessionCookie.id;
}
}
deleteByLogoutToken(claims, options) {
return this.#store.deleteByLogoutToken(claims, options);
}
};
// src/utils.ts
function ensureTrailingSlash(value) {
return value && !value.endsWith("/") ? `${value}/` : value;
}
function ensureNoLeadingSlash(value) {
return value && value.startsWith("/") ? value.substring(1, value.length) : value;
}
function createRouteUrl(url, base) {
return new URL(ensureNoLeadingSlash(url), ensureTrailingSlash(base));
}
function toSafeRedirect(dangerousRedirect, safeBaseUrl) {
let url;
try {
url = createRouteUrl(dangerousRedirect, safeBaseUrl);
} catch {
return void 0;
}
if (url.origin === new URL(safeBaseUrl).origin) {
return url.toString();
}
return void 0;
}
// src/index.ts
var import_auth0_server_js2 = require("@auth0/auth0-server-js");
var index_default = (0, import_fastify_plugin.default)(async function auth0Fastify(fastify, options) {
const callbackPath = "/auth/callback";
const callbackPath = options.routes?.callback ?? "/auth/callback";
const redirectUri = createRouteUrl(callbackPath, options.appBaseUrl);
const auth0Client = new import_auth0_server_js4.ServerClient({
const auth0Client = new import_auth0_server_js.ServerClient({
domain: options.domain,

@@ -295,11 +118,11 @@ clientId: options.clientId,

},
transactionStore: new CookieTransactionStore({ secret: options.sessionSecret }),
stateStore: options.sessionStore ? new StatefulStateStore({
transactionStore: new import_auth0_server_js.CookieTransactionStore({ secret: options.sessionSecret }, new FastifyCookieHandler()),
stateStore: options.sessionStore ? new import_auth0_server_js.StatefulStateStore({
...options.sessionConfiguration,
secret: options.sessionSecret,
store: options.sessionStore
}) : new StatelessStateStore({
}, new FastifyCookieHandler()) : new import_auth0_server_js.StatelessStateStore({
...options.sessionConfiguration,
secret: options.sessionSecret
}),
}, new FastifyCookieHandler()),
stateIdentifier: options.sessionConfiguration?.cookie?.name,

@@ -314,3 +137,3 @@ customFetch: options.customFetch

fastify.get(
"/auth/login",
options.routes?.login ?? "/auth/login",
async (request, reply) => {

@@ -329,3 +152,3 @@ const dangerousReturnTo = request.query.returnTo;

);
fastify.get("/auth/callback", async (request, reply) => {
fastify.get(options.routes?.callback ?? "/auth/callback", async (request, reply) => {
const { appState } = await auth0Client.completeInteractiveLogin(

@@ -337,3 +160,3 @@ createRouteUrl(request.url, options.appBaseUrl),

});
fastify.get("/auth/logout", async (request, reply) => {
fastify.get(options.routes?.logout ?? "/auth/logout", async (request, reply) => {
const returnTo = options.appBaseUrl;

@@ -344,3 +167,3 @@ const logoutUrl = await auth0Client.logout({ returnTo: returnTo.toString() }, { request, reply });

fastify.post(
"/auth/backchannel-logout",
options.routes?.backchannelLogout ?? "/auth/backchannel-logout",
async (request, reply) => {

@@ -363,3 +186,3 @@ const logoutToken = request.body.logout_token;

fastify.get(
"/auth/connect",
options.routes?.connect ?? "/auth/connect",
async (request, reply) => {

@@ -375,3 +198,3 @@ const { connection, connectionScope, returnTo } = request.query;

const sanitizedReturnTo = toSafeRedirect(dangerousReturnTo || "/", options.appBaseUrl);
const callbackPath2 = "/auth/connect/callback";
const callbackPath2 = options.routes?.connectCallback ?? "/auth/connect/callback";
const redirectUri2 = createRouteUrl(callbackPath2, options.appBaseUrl);

@@ -394,3 +217,3 @@ const linkUserUrl = await fastify.auth0Client.startLinkUser(

);
fastify.get("/auth/connect/callback", async (request, reply) => {
fastify.get(options.routes?.connectCallback ?? "/auth/connect/callback", async (request, reply) => {
const { appState } = await fastify.auth0Client.completeLinkUser(

@@ -406,3 +229,3 @@ createRouteUrl(request.url, options.appBaseUrl),

fastify.get(
"/auth/unconnect",
options.routes?.unconnect ?? "/auth/unconnect",
async (request, reply) => {

@@ -418,3 +241,3 @@ const { connection, returnTo } = request.query;

const sanitizedReturnTo = toSafeRedirect(dangerousReturnTo || "/", options.appBaseUrl);
const callbackPath2 = "/auth/unconnect/callback";
const callbackPath2 = options.routes?.unconnectCallback ?? "/auth/unconnect/callback";
const redirectUri2 = createRouteUrl(callbackPath2, options.appBaseUrl);

@@ -436,3 +259,3 @@ const linkUserUrl = await fastify.auth0Client.startUnlinkUser(

);
fastify.get("/auth/unconnect/callback", async (request, reply) => {
fastify.get(options.routes?.unconnectCallback ?? "/auth/unconnect/callback", async (request, reply) => {
const { appState } = await fastify.auth0Client.completeUnlinkUser(

@@ -439,0 +262,0 @@ createRouteUrl(request.url, options.appBaseUrl),

+1
-1

@@ -1,1 +0,1 @@

{"version":3,"sources":["../src/index.ts","../src/store/cookie-transaction-store.ts","../src/errors/index.ts","../src/store/stateless-state-store.ts","../src/store/abstract-session-store.ts","../src/store/stateful-state-store.ts","../src/utils.ts"],"sourcesContent":["import type { FastifyInstance, FastifyRequest } from 'fastify';\nimport fp from 'fastify-plugin';\nimport { ServerClient } from '@auth0/auth0-server-js';\nimport type { SessionConfiguration, SessionStore, StoreOptions } from './types.js';\nimport { CookieTransactionStore } from './store/cookie-transaction-store.js';\nimport { StatelessStateStore } from './store/stateless-state-store.js';\nimport { StatefulStateStore } from './store/stateful-state-store.js';\nimport { createRouteUrl, toSafeRedirect } from './utils.js';\n\nexport * from './types.js';\nexport { CookieTransactionStore } from './store/cookie-transaction-store.js';\n\ndeclare module 'fastify' {\n interface FastifyInstance {\n auth0Client: ServerClient<StoreOptions> | undefined;\n }\n}\n\nexport interface Auth0FastifyOptions {\n domain: string;\n clientId: string;\n clientSecret?: string;\n clientAssertionSigningKey?: string | CryptoKey;\n clientAssertionSigningAlg?: string;\n audience?: string;\n appBaseUrl: string;\n\n pushedAuthorizationRequests?: boolean;\n\n sessionSecret: string;\n sessionStore?: SessionStore;\n sessionConfiguration?: SessionConfiguration;\n /**\n * Whether to mount the default routes for login, logout, callback and profile.\n * Defaults to true.\n */\n mountRoutes?: boolean;\n /**\n * Whether to mount the routes for account linking and unlinking.\n * Defaults to false.\n */\n mountConnectRoutes?: boolean;\n /**\n * Optional, custom Fetch implementation to use.\n */\n customFetch?: typeof fetch;\n}\n\nexport default fp(async function auth0Fastify(fastify: FastifyInstance, options: Auth0FastifyOptions) {\n const callbackPath = '/auth/callback';\n const redirectUri = createRouteUrl(callbackPath, options.appBaseUrl);\n\n const auth0Client = new ServerClient<StoreOptions>({\n domain: options.domain,\n clientId: options.clientId,\n clientSecret: options.clientSecret,\n clientAssertionSigningKey: options.clientAssertionSigningKey,\n clientAssertionSigningAlg: options.clientAssertionSigningAlg,\n authorizationParams: {\n audience: options.audience,\n redirect_uri: redirectUri.toString(),\n },\n transactionStore: new CookieTransactionStore({ secret: options.sessionSecret }),\n stateStore: options.sessionStore\n ? new StatefulStateStore({\n ...options.sessionConfiguration,\n secret: options.sessionSecret,\n store: options.sessionStore,\n })\n : new StatelessStateStore({\n ...options.sessionConfiguration,\n secret: options.sessionSecret,\n }),\n stateIdentifier: options.sessionConfiguration?.cookie?.name,\n customFetch: options.customFetch,\n });\n\n if (!fastify.hasReplyDecorator('cookie')) {\n fastify.register(import('@fastify/cookie'));\n }\n\n const shouldMountRoutes = options.mountRoutes ?? true;\n\n if (shouldMountRoutes) {\n fastify.get(\n '/auth/login',\n async (\n request: FastifyRequest<{\n Querystring: { returnTo?: string };\n }>,\n reply\n ) => {\n const dangerousReturnTo = request.query.returnTo;\n const sanitizedReturnTo = toSafeRedirect(dangerousReturnTo || '/', options.appBaseUrl);\n\n const authorizationUrl = await auth0Client.startInteractiveLogin(\n {\n pushedAuthorizationRequests: options.pushedAuthorizationRequests,\n appState: { returnTo: sanitizedReturnTo },\n },\n { request, reply }\n );\n\n reply.redirect(authorizationUrl.href);\n }\n );\n\n fastify.get('/auth/callback', async (request, reply) => {\n const { appState } = await auth0Client.completeInteractiveLogin<{ returnTo: string } | undefined>(\n createRouteUrl(request.url, options.appBaseUrl),\n { request, reply }\n );\n\n reply.redirect(appState?.returnTo ?? options.appBaseUrl);\n });\n\n fastify.get('/auth/logout', async (request, reply) => {\n const returnTo = options.appBaseUrl;\n const logoutUrl = await auth0Client.logout({ returnTo: returnTo.toString() }, { request, reply });\n\n reply.redirect(logoutUrl.href);\n });\n\n fastify.post(\n '/auth/backchannel-logout',\n async (\n request: FastifyRequest<{\n Body: { logout_token?: string };\n }>,\n reply\n ) => {\n const logoutToken = request.body.logout_token;\n\n if (!logoutToken) {\n reply.code(400).send('Missing `logout_token` in the request body.');\n\n return;\n }\n\n try {\n await auth0Client.handleBackchannelLogout(logoutToken, { request, reply });\n reply.code(204).send(null);\n } catch (e) {\n reply.code(400).send((e as Error).message);\n }\n }\n );\n\n const shouldMountConnectRoutes = options.mountConnectRoutes ?? false;\n\n if (shouldMountConnectRoutes) {\n fastify.get(\n '/auth/connect',\n async (\n request: FastifyRequest<{\n Querystring: { connection: string; connectionScope: string; returnTo?: string };\n }>,\n reply\n ) => {\n const { connection, connectionScope, returnTo } = request.query;\n const dangerousReturnTo = returnTo;\n\n if (!connection) {\n return reply.code(400).send({\n error: 'invalid_request',\n error_description: 'connection is required',\n });\n }\n\n const sanitizedReturnTo = toSafeRedirect(dangerousReturnTo || '/', options.appBaseUrl);\n const callbackPath = '/auth/connect/callback';\n const redirectUri = createRouteUrl(callbackPath, options.appBaseUrl);\n const linkUserUrl = await fastify.auth0Client!.startLinkUser(\n {\n connection: connection,\n connectionScope: connectionScope,\n authorizationParams: {\n redirect_uri: redirectUri.toString(),\n },\n appState: {\n returnTo: sanitizedReturnTo,\n },\n },\n { request, reply }\n );\n\n reply.redirect(linkUserUrl.href);\n }\n );\n\n fastify.get('/auth/connect/callback', async (request, reply) => {\n const { appState } = await fastify.auth0Client!.completeLinkUser<{ returnTo: string }>(\n createRouteUrl(request.url, options.appBaseUrl),\n {\n request,\n reply,\n }\n );\n\n reply.redirect(appState?.returnTo ?? options.appBaseUrl);\n });\n\n fastify.get(\n '/auth/unconnect',\n async (\n request: FastifyRequest<{\n Querystring: { connection: string; returnTo?: string };\n }>,\n reply\n ) => {\n const { connection, returnTo } = request.query;\n const dangerousReturnTo = returnTo;\n\n if (!connection) {\n return reply.code(400).send({\n error: 'invalid_request',\n error_description: 'connection is required',\n });\n }\n\n const sanitizedReturnTo = toSafeRedirect(dangerousReturnTo || '/', options.appBaseUrl);\n const callbackPath = '/auth/unconnect/callback';\n const redirectUri = createRouteUrl(callbackPath, options.appBaseUrl);\n const linkUserUrl = await fastify.auth0Client!.startUnlinkUser(\n {\n connection: connection,\n authorizationParams: {\n redirect_uri: redirectUri.toString(),\n },\n appState: {\n returnTo: sanitizedReturnTo,\n },\n },\n { request, reply }\n );\n\n reply.redirect(linkUserUrl.href);\n }\n );\n\n fastify.get('/auth/unconnect/callback', async (request, reply) => {\n const { appState } = await fastify.auth0Client!.completeUnlinkUser<{ returnTo: string }>(\n createRouteUrl(request.url, options.appBaseUrl),\n {\n request,\n reply,\n }\n );\n\n reply.redirect(appState?.returnTo ?? options.appBaseUrl);\n });\n }\n }\n\n fastify.decorate('auth0Client', auth0Client);\n});\n","import { CookieSerializeOptions } from '@fastify/cookie';\nimport { TransactionData, AbstractTransactionStore } from '@auth0/auth0-server-js';\nimport { MissingStoreOptionsError } from '../errors/index.js';\nimport { StoreOptions } from '../types.js';\n\nexport class CookieTransactionStore extends AbstractTransactionStore<StoreOptions> {\n async set(\n identifier: string,\n transactionData: TransactionData,\n removeIfExists?: boolean,\n options?: StoreOptions\n ): Promise<void> {\n // We can not handle cookies in Fastify when the `StoreOptions` are not provided.\n if (!options) {\n throw new MissingStoreOptionsError();\n }\n\n const maxAge = 60 * 60;\n const cookieOpts: CookieSerializeOptions = { httpOnly: true, sameSite: 'lax', path: '/', maxAge };\n const expiration = Math.floor(Date.now() / 1000 + maxAge);\n const encryptedStateData = await this.encrypt(identifier, transactionData, expiration);\n \n options.reply.setCookie(identifier, encryptedStateData, cookieOpts);\n }\n\n async get(identifier: string, options?: StoreOptions): Promise<TransactionData | undefined> {\n // We can not handle cookies in Fastify when the `StoreOptions` are not provided.\n if (!options) {\n throw new MissingStoreOptionsError();\n }\n\n const cookieValue = options.request.cookies[identifier];\n\n if (cookieValue) {\n return await this.decrypt(identifier, cookieValue);\n }\n }\n\n async delete(identifier: string, options?: StoreOptions | undefined): Promise<void> {\n // We can not handle cookies in Fastify when the `StoreOptions` are not provided.\n if (!options) {\n throw new MissingStoreOptionsError();\n }\n\n options?.reply.clearCookie(identifier);\n }\n}\n","export class MissingStoreOptionsError extends Error {\n public code: string = 'missing_store_options_error';\n\n constructor(message?: string) {\n super(message ?? 'The store options are missing, making it impossible to interact with the store.');\n this.name = 'MissingStoreOptionsError';\n }\n}\n","import type { CookieSerializeOptions } from '@fastify/cookie';\nimport { BackchannelLogoutError, EncryptedStoreOptions, StateData } from '@auth0/auth0-server-js';\nimport { MissingStoreOptionsError } from '../errors/index.js';\nimport type { SessionConfiguration, SessionCookieOptions, StoreOptions } from '../types.js';\nimport { AbstractSessionStore } from './abstract-session-store.js';\n\nexport class StatelessStateStore extends AbstractSessionStore {\n readonly #cookieOptions: SessionCookieOptions | undefined;\n\n constructor(options: SessionConfiguration & EncryptedStoreOptions) {\n super(options);\n\n this.#cookieOptions = options.cookie;\n }\n\n async set(\n identifier: string,\n stateData: StateData,\n removeIfExists?: boolean,\n options?: StoreOptions | undefined\n ): Promise<void> {\n // We can not handle cookies in Fastify when the `StoreOptions` are not provided.\n if (!options) {\n throw new MissingStoreOptionsError();\n }\n\n const maxAge = this.calculateMaxAge(stateData.internal.createdAt);\n const cookieOpts: CookieSerializeOptions = {\n httpOnly: true,\n sameSite: this.#cookieOptions?.sameSite ?? 'lax',\n path: '/',\n secure: this.#cookieOptions?.secure ?? 'auto',\n maxAge,\n };\n const expiration = Math.floor(Date.now() / 1000 + maxAge);\n const encryptedStateData = await this.encrypt(identifier, stateData, expiration);\n\n const chunkSize = 3072;\n const chunkCount = Math.ceil(encryptedStateData.length / chunkSize);\n const chunks = [...Array(chunkCount).keys()].map((i) => ({\n value: encryptedStateData.substring(i * chunkSize, (i + 1) * chunkSize),\n name: `${identifier}.${i}`,\n }));\n\n chunks.forEach((chunk) => {\n options.reply.setCookie(chunk.name, chunk.value, cookieOpts);\n });\n\n const existingCookieKeys = this.getCookieKeys(identifier, options);\n const cookieKeysToRemove = existingCookieKeys.filter((key) => !chunks.some((chunk) => chunk.name === key));\n cookieKeysToRemove.forEach((key) => {\n options.reply.clearCookie(key);\n });\n }\n\n async get(identifier: string, options?: StoreOptions | undefined): Promise<StateData | undefined> {\n // We can not handle cookies in Fastify when the `StoreOptions` are not provided.\n if (!options) {\n throw new MissingStoreOptionsError();\n }\n\n const cookieKeys = this.getCookieKeys(identifier, options);\n const encryptedStateData = cookieKeys\n .map((key) => ({ index: parseInt(key.split('.')[1] as string, 10), value: options.request.cookies[key] }))\n .sort((a, b) => a.index - b.index)\n .map((item) => item.value)\n .join('');\n\n if (encryptedStateData) {\n return (await this.decrypt(identifier, encryptedStateData)) as StateData;\n }\n }\n\n async delete(identifier: string, options?: StoreOptions | undefined): Promise<void> {\n // We can not handle cookies in Fastify when the `StoreOptions` are not provided.\n if (!options) {\n throw new MissingStoreOptionsError();\n }\n\n const cookieKeys = this.getCookieKeys(identifier, options);\n for (const key of cookieKeys) {\n options?.reply.clearCookie(key);\n }\n }\n\n deleteByLogoutToken(): Promise<void> {\n throw new BackchannelLogoutError(\n 'Backchannel logout is not available when using Stateless Storage. Use Stateful Storage by providing a `sessionStore`'\n );\n }\n\n private getCookieKeys(identifier: string, options: StoreOptions): string[] {\n return Object.keys(options.request.cookies).filter((key) => key.startsWith(identifier));\n }\n}\n","import { AbstractStateStore, EncryptedStoreOptions, LogoutTokenClaims, StateData } from '@auth0/auth0-server-js';\nimport type { SessionConfiguration, StoreOptions } from '../types.js';\n\nexport abstract class AbstractSessionStore extends AbstractStateStore<StoreOptions> {\n readonly #rolling: boolean;\n readonly #absoluteDuration: number;\n readonly #inactivityDuration: number;\n\n constructor(options: SessionConfiguration & EncryptedStoreOptions) {\n super(options);\n\n this.#rolling = options.rolling ?? true;\n this.#absoluteDuration = options.absoluteDuration ?? 60 * 60 * 24 * 3;\n this.#inactivityDuration = options.inactivityDuration ?? 60 * 60 * 24 * 1;\n }\n\n abstract set(\n identifier: string,\n stateData: StateData,\n removeIfExists?: boolean,\n options?: StoreOptions | undefined\n ): Promise<void>;\n\n abstract get(identifier: string, options?: StoreOptions | undefined): Promise<StateData | undefined>;\n\n abstract delete(identifier: string, options?: StoreOptions | undefined): Promise<void>;\n\n abstract deleteByLogoutToken(claims: LogoutTokenClaims, options?: StoreOptions | undefined): Promise<void>;\n\n /**\n * calculateMaxAge calculates the max age of the session based on createdAt and the rolling and absolute durations.\n */\n protected calculateMaxAge(createdAt: number) {\n if (!this.#rolling) {\n return this.#absoluteDuration;\n }\n\n const now = (Date.now() / 1000) | 0;\n const expiresAt = Math.min(now + this.#inactivityDuration, createdAt + this.#absoluteDuration);\n const maxAge = expiresAt - now;\n\n return maxAge > 0 ? maxAge : 0;\n }\n}\n","import type { CookieSerializeOptions } from '@fastify/cookie';\nimport { EncryptedStoreOptions, LogoutTokenClaims, StateData } from '@auth0/auth0-server-js';\nimport { MissingStoreOptionsError } from '../errors/index.js';\nimport type { SessionConfiguration, SessionCookieOptions, SessionStore, StoreOptions } from '../types.js';\nimport { AbstractSessionStore } from './abstract-session-store.js';\n\nexport interface StatefulStateStoreOptions extends EncryptedStoreOptions {\n store: SessionStore;\n}\n\nconst generateId = () => {\n const bytes = new Uint8Array(16);\n crypto.getRandomValues(bytes);\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n};\n\nexport class StatefulStateStore extends AbstractSessionStore {\n readonly #store: SessionStore;\n readonly #cookieOptions: SessionCookieOptions | undefined;\n\n constructor(options: StatefulStateStoreOptions & SessionConfiguration) {\n super(options);\n\n this.#store = options.store;\n this.#cookieOptions = options.cookie;\n }\n\n async set(\n identifier: string,\n stateData: StateData,\n removeIfExists?: boolean,\n options?: StoreOptions | undefined\n ): Promise<void> {\n // We can not handle cookies in Fastify when the `StoreOptions` are not provided.\n if (!options) {\n throw new MissingStoreOptionsError();\n }\n\n let sessionId = await this.getSessionId(identifier, options);\n\n // if this is a new session created by a new login we need to remove the old session\n // from the store and regenerate the session ID to prevent session fixation.\n if (sessionId && removeIfExists) {\n await this.#store.delete(sessionId);\n sessionId = generateId();\n }\n\n if (!sessionId) {\n sessionId = generateId();\n }\n\n const maxAge = this.calculateMaxAge(stateData.internal.createdAt);\n const cookieOpts: CookieSerializeOptions = {\n httpOnly: true,\n sameSite: this.#cookieOptions?.sameSite ?? 'lax',\n path: '/',\n secure: this.#cookieOptions?.secure ?? 'auto',\n maxAge,\n };\n const expiration = Date.now() / 1000 + maxAge;\n const encryptedStateData = await this.encrypt<{ id: string }>(\n identifier,\n {\n id: sessionId,\n },\n expiration\n );\n\n await this.#store.set(sessionId, stateData);\n\n options.reply.setCookie(identifier, encryptedStateData, cookieOpts);\n }\n\n async get(identifier: string, options?: StoreOptions | undefined): Promise<StateData | undefined> {\n // We can not handle cookies in Fastify when the `StoreOptions` are not provided.\n if (!options) {\n throw new MissingStoreOptionsError();\n }\n\n const sessionId = await this.getSessionId(identifier, options);\n\n if (sessionId) {\n const stateData = await this.#store.get(sessionId);\n\n // If we have a session cookie, but no `stateData`, we should remove the cookie.\n if (!stateData) {\n options?.reply.clearCookie(identifier);\n }\n\n return stateData;\n }\n }\n\n async delete(identifier: string, options?: StoreOptions | undefined): Promise<void> {\n // We can not handle cookies in Fastify when the `StoreOptions` are not provided.\n if (!options) {\n throw new MissingStoreOptionsError();\n }\n\n const sessionId = await this.getSessionId(identifier, options);\n\n if (sessionId) {\n await this.#store.delete(sessionId);\n }\n\n options?.reply.clearCookie(identifier);\n }\n\n private async getSessionId(identifier: string, options: StoreOptions) {\n const cookieValue = options.request.cookies[identifier];\n if (cookieValue) {\n const sessionCookie = await this.decrypt<{ id: string }>(identifier, cookieValue);\n return sessionCookie.id;\n }\n }\n\n deleteByLogoutToken(claims: LogoutTokenClaims, options?: StoreOptions | undefined): Promise<void> {\n return this.#store.deleteByLogoutToken(claims, options);\n }\n}\n","/**\n * Ensures the value has a trailing slash.\n * If it does not, it will append one.\n * @param value The value to ensure has a trailing slash.\n * @returns The value with a trailing slash.\n */\nfunction ensureTrailingSlash(value: string) {\n return value && !value.endsWith('/') ? `${value}/` : value;\n}\n\n/**\n * Ensures the value does not have a leading slash.\n * If it does, it will trim it.\n * @param value The value to ensure has no leading slash.\n * @returns The value without a leading slash.\n */\nfunction ensureNoLeadingSlash(value: string) {\n return value && value.startsWith('/') ? value.substring(1, value.length) : value;\n}\n\n/**\n * Utility function to ensure Route URLs are created correctly when using both the root and subpath as base URL.\n * @param url The URL to use.\n * @param base The base URL to use.\n * @returns A URL object, combining the base and url.\n */\nexport function createRouteUrl(url: string, base: string) {\n return new URL(ensureNoLeadingSlash(url), ensureTrailingSlash(base));\n}\n\n/**\n * Function to ensure a redirect URL is safe to use, as in, it has the same origin as the safeBaseUrl.\n * @param dangerousRedirect The redirect URL to check.\n * @param safeBaseUrl The base URL to check against.\n * @returns A safe redirect URL or undefined if the redirect URL is not safe.\n */\nexport function toSafeRedirect(dangerousRedirect: string, safeBaseUrl: string): string | undefined {\n let url: URL;\n\n try {\n url = createRouteUrl(dangerousRedirect, safeBaseUrl);\n } catch {\n return undefined;\n }\n\n if (url.origin === new URL(safeBaseUrl).origin) {\n return url.toString();\n }\n\n return undefined;\n}"],"mappings":"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","names":["import_auth0_server_js","import_auth0_server_js","import_auth0_server_js","fp","callbackPath","redirectUri"]}
{"version":3,"sources":["../src/index.ts","../src/utils.ts","../src/errors/index.ts","../src/store/fastify-cookie-handler.ts"],"sourcesContent":["import type { FastifyInstance, FastifyRequest } from 'fastify';\nimport fp from 'fastify-plugin';\nimport { CookieTransactionStore, ServerClient, StatelessStateStore, StatefulStateStore } from '@auth0/auth0-server-js';\nimport type { SessionConfiguration, SessionStore, StoreOptions } from './types.js';\nimport { createRouteUrl, toSafeRedirect } from './utils.js';\nimport { FastifyCookieHandler } from './store/fastify-cookie-handler.js';\n\nexport * from './types.js';\nexport { CookieTransactionStore } from '@auth0/auth0-server-js';\n\ndeclare module 'fastify' {\n interface FastifyInstance {\n auth0Client: ServerClient<StoreOptions> | undefined;\n }\n}\n\nexport interface Auth0FastifyOptions {\n domain: string;\n clientId: string;\n clientSecret?: string;\n clientAssertionSigningKey?: string | CryptoKey;\n clientAssertionSigningAlg?: string;\n audience?: string;\n appBaseUrl: string;\n\n pushedAuthorizationRequests?: boolean;\n\n sessionSecret: string;\n sessionStore?: SessionStore;\n sessionConfiguration?: SessionConfiguration;\n /**\n * Whether to mount the default routes for login, logout, callback and profile.\n * Defaults to true.\n */\n mountRoutes?: boolean;\n /**\n * Whether to mount the routes for account linking and unlinking.\n * Defaults to false.\n */\n mountConnectRoutes?: boolean;\n /**\n * Optional, custom Fetch implementation to use.\n */\n customFetch?: typeof fetch;\n\n routes?: {\n login?: string;\n callback?: string;\n logout?: string;\n backchannelLogout?: string;\n connect?: string;\n connectCallback?: string;\n unconnect?: string;\n unconnectCallback?: string;\n }\n}\n\nexport default fp(async function auth0Fastify(fastify: FastifyInstance, options: Auth0FastifyOptions) {\n const callbackPath = options.routes?.callback ?? '/auth/callback';\n const redirectUri = createRouteUrl(callbackPath, options.appBaseUrl);\n\n const auth0Client = new ServerClient<StoreOptions>({\n domain: options.domain,\n clientId: options.clientId,\n clientSecret: options.clientSecret,\n clientAssertionSigningKey: options.clientAssertionSigningKey,\n clientAssertionSigningAlg: options.clientAssertionSigningAlg,\n authorizationParams: {\n audience: options.audience,\n redirect_uri: redirectUri.toString(),\n },\n transactionStore: new CookieTransactionStore({ secret: options.sessionSecret }, new FastifyCookieHandler()),\n stateStore: options.sessionStore\n ? new StatefulStateStore({\n ...options.sessionConfiguration,\n secret: options.sessionSecret,\n store: options.sessionStore,\n }, new FastifyCookieHandler())\n : new StatelessStateStore({\n ...options.sessionConfiguration,\n secret: options.sessionSecret,\n }, new FastifyCookieHandler()),\n stateIdentifier: options.sessionConfiguration?.cookie?.name,\n customFetch: options.customFetch,\n });\n\n if (!fastify.hasReplyDecorator('cookie')) {\n fastify.register(import('@fastify/cookie'));\n }\n\n const shouldMountRoutes = options.mountRoutes ?? true;\n\n if (shouldMountRoutes) {\n fastify.get(\n options.routes?.login ?? '/auth/login',\n async (\n request: FastifyRequest<{\n Querystring: { returnTo?: string };\n }>,\n reply\n ) => {\n const dangerousReturnTo = request.query.returnTo;\n const sanitizedReturnTo = toSafeRedirect(dangerousReturnTo || '/', options.appBaseUrl);\n\n const authorizationUrl = await auth0Client.startInteractiveLogin(\n {\n pushedAuthorizationRequests: options.pushedAuthorizationRequests,\n appState: { returnTo: sanitizedReturnTo },\n },\n { request, reply }\n );\n\n reply.redirect(authorizationUrl.href);\n }\n );\n\n fastify.get(options.routes?.callback ?? '/auth/callback', async (request, reply) => {\n const { appState } = await auth0Client.completeInteractiveLogin<{ returnTo: string } | undefined>(\n createRouteUrl(request.url, options.appBaseUrl),\n { request, reply }\n );\n\n reply.redirect(appState?.returnTo ?? options.appBaseUrl);\n });\n\n fastify.get(options.routes?.logout ?? '/auth/logout', async (request, reply) => {\n const returnTo = options.appBaseUrl;\n const logoutUrl = await auth0Client.logout({ returnTo: returnTo.toString() }, { request, reply });\n\n reply.redirect(logoutUrl.href);\n });\n\n fastify.post(\n options.routes?.backchannelLogout ?? '/auth/backchannel-logout',\n async (\n request: FastifyRequest<{\n Body: { logout_token?: string };\n }>,\n reply\n ) => {\n const logoutToken = request.body.logout_token;\n\n if (!logoutToken) {\n reply.code(400).send('Missing `logout_token` in the request body.');\n\n return;\n }\n\n try {\n await auth0Client.handleBackchannelLogout(logoutToken, { request, reply });\n reply.code(204).send(null);\n } catch (e) {\n reply.code(400).send((e as Error).message);\n }\n }\n );\n\n const shouldMountConnectRoutes = options.mountConnectRoutes ?? false;\n\n if (shouldMountConnectRoutes) {\n fastify.get(\n options.routes?.connect ?? '/auth/connect',\n async (\n request: FastifyRequest<{\n Querystring: { connection: string; connectionScope: string; returnTo?: string };\n }>,\n reply\n ) => {\n const { connection, connectionScope, returnTo } = request.query;\n const dangerousReturnTo = returnTo;\n\n if (!connection) {\n return reply.code(400).send({\n error: 'invalid_request',\n error_description: 'connection is required',\n });\n }\n\n const sanitizedReturnTo = toSafeRedirect(dangerousReturnTo || '/', options.appBaseUrl);\n const callbackPath = options.routes?.connectCallback ?? '/auth/connect/callback';\n const redirectUri = createRouteUrl(callbackPath, options.appBaseUrl);\n const linkUserUrl = await fastify.auth0Client!.startLinkUser(\n {\n connection: connection,\n connectionScope: connectionScope,\n authorizationParams: {\n redirect_uri: redirectUri.toString(),\n },\n appState: {\n returnTo: sanitizedReturnTo,\n },\n },\n { request, reply }\n );\n\n reply.redirect(linkUserUrl.href);\n }\n );\n\n fastify.get(options.routes?.connectCallback ?? '/auth/connect/callback', async (request, reply) => {\n const { appState } = await fastify.auth0Client!.completeLinkUser<{ returnTo: string }>(\n createRouteUrl(request.url, options.appBaseUrl),\n {\n request,\n reply,\n }\n );\n\n reply.redirect(appState?.returnTo ?? options.appBaseUrl);\n });\n\n fastify.get(\n options.routes?.unconnect ?? '/auth/unconnect',\n async (\n request: FastifyRequest<{\n Querystring: { connection: string; returnTo?: string };\n }>,\n reply\n ) => {\n const { connection, returnTo } = request.query;\n const dangerousReturnTo = returnTo;\n\n if (!connection) {\n return reply.code(400).send({\n error: 'invalid_request',\n error_description: 'connection is required',\n });\n }\n\n const sanitizedReturnTo = toSafeRedirect(dangerousReturnTo || '/', options.appBaseUrl);\n const callbackPath = options.routes?.unconnectCallback ?? '/auth/unconnect/callback';\n const redirectUri = createRouteUrl(callbackPath, options.appBaseUrl);\n const linkUserUrl = await fastify.auth0Client!.startUnlinkUser(\n {\n connection: connection,\n authorizationParams: {\n redirect_uri: redirectUri.toString(),\n },\n appState: {\n returnTo: sanitizedReturnTo,\n },\n },\n { request, reply }\n );\n\n reply.redirect(linkUserUrl.href);\n }\n );\n\n fastify.get(options.routes?.unconnectCallback ?? '/auth/unconnect/callback', async (request, reply) => {\n const { appState } = await fastify.auth0Client!.completeUnlinkUser<{ returnTo: string }>(\n createRouteUrl(request.url, options.appBaseUrl),\n {\n request,\n reply,\n }\n );\n\n reply.redirect(appState?.returnTo ?? options.appBaseUrl);\n });\n }\n }\n\n fastify.decorate('auth0Client', auth0Client);\n});\n","/**\n * Ensures the value has a trailing slash.\n * If it does not, it will append one.\n * @param value The value to ensure has a trailing slash.\n * @returns The value with a trailing slash.\n */\nfunction ensureTrailingSlash(value: string) {\n return value && !value.endsWith('/') ? `${value}/` : value;\n}\n\n/**\n * Ensures the value does not have a leading slash.\n * If it does, it will trim it.\n * @param value The value to ensure has no leading slash.\n * @returns The value without a leading slash.\n */\nfunction ensureNoLeadingSlash(value: string) {\n return value && value.startsWith('/') ? value.substring(1, value.length) : value;\n}\n\n/**\n * Utility function to ensure Route URLs are created correctly when using both the root and subpath as base URL.\n * @param url The URL to use.\n * @param base The base URL to use.\n * @returns A URL object, combining the base and url.\n */\nexport function createRouteUrl(url: string, base: string) {\n return new URL(ensureNoLeadingSlash(url), ensureTrailingSlash(base));\n}\n\n/**\n * Function to ensure a redirect URL is safe to use, as in, it has the same origin as the safeBaseUrl.\n * @param dangerousRedirect The redirect URL to check.\n * @param safeBaseUrl The base URL to check against.\n * @returns A safe redirect URL or undefined if the redirect URL is not safe.\n */\nexport function toSafeRedirect(dangerousRedirect: string, safeBaseUrl: string): string | undefined {\n let url: URL;\n\n try {\n url = createRouteUrl(dangerousRedirect, safeBaseUrl);\n } catch {\n return undefined;\n }\n\n if (url.origin === new URL(safeBaseUrl).origin) {\n return url.toString();\n }\n\n return undefined;\n}","export class MissingStoreOptionsError extends Error {\n public code: string = 'missing_store_options_error';\n\n constructor(message?: string) {\n super(message ?? 'The store options are missing, making it impossible to interact with the store.');\n this.name = 'MissingStoreOptionsError';\n }\n}\n","import { CookieHandler, CookieSerializeOptions } from '@auth0/auth0-server-js';\nimport { StoreOptions } from '../types.js';\nimport { MissingStoreOptionsError } from '../errors/index.js';\n\nexport class FastifyCookieHandler implements CookieHandler<StoreOptions> {\n setCookie(\n name: string,\n value: string,\n options?: CookieSerializeOptions,\n storeOptions?: StoreOptions,\n ): void {\n if (!storeOptions) {\n throw new MissingStoreOptionsError();\n }\n\n storeOptions.reply.setCookie(name, value, options || {});\n }\n\n getCookie(name: string, storeOptions?: StoreOptions): string | undefined {\n if (!storeOptions) {\n throw new MissingStoreOptionsError();\n }\n\n return storeOptions.request.cookies?.[name];\n }\n\n getCookies(storeOptions?: StoreOptions): Record<string, string> {\n if (!storeOptions) {\n throw new MissingStoreOptionsError();\n }\n\n return storeOptions.request.cookies as Record<string, string>;\n }\n\n deleteCookie(name: string, storeOptions?: StoreOptions): void {\n if (!storeOptions) {\n throw new MissingStoreOptionsError();\n }\n\n storeOptions.reply.clearCookie(name);\n }\n}\n"],"mappings":"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","names":["import_auth0_server_js","fp","callbackPath","redirectUri"]}
import { FastifyRequest, FastifyReply, FastifyInstance } from 'fastify';
import { StateData, LogoutTokenClaims, AbstractTransactionStore, TransactionData, ServerClient } from '@auth0/auth0-server-js';
import { StateData, LogoutTokenClaims, ServerClient } from '@auth0/auth0-server-js';
export { CookieTransactionStore } from '@auth0/auth0-server-js';

@@ -66,8 +67,2 @@ interface StoreOptions {

declare class CookieTransactionStore extends AbstractTransactionStore<StoreOptions> {
set(identifier: string, transactionData: TransactionData, removeIfExists?: boolean, options?: StoreOptions): Promise<void>;
get(identifier: string, options?: StoreOptions): Promise<TransactionData | undefined>;
delete(identifier: string, options?: StoreOptions | undefined): Promise<void>;
}
declare module 'fastify' {

@@ -104,5 +99,15 @@ interface FastifyInstance {

customFetch?: typeof fetch;
routes?: {
login?: string;
callback?: string;
logout?: string;
backchannelLogout?: string;
connect?: string;
connectCallback?: string;
unconnect?: string;
unconnectCallback?: string;
};
}
declare const _default: (fastify: FastifyInstance, options: Auth0FastifyOptions) => Promise<void>;
export { type Auth0FastifyOptions, CookieTransactionStore, type SessionConfiguration, type SessionCookieOptions, type SessionStore, type StoreOptions, _default as default };
export { type Auth0FastifyOptions, type SessionConfiguration, type SessionCookieOptions, type SessionStore, type StoreOptions, _default as default };
import { FastifyRequest, FastifyReply, FastifyInstance } from 'fastify';
import { StateData, LogoutTokenClaims, AbstractTransactionStore, TransactionData, ServerClient } from '@auth0/auth0-server-js';
import { StateData, LogoutTokenClaims, ServerClient } from '@auth0/auth0-server-js';
export { CookieTransactionStore } from '@auth0/auth0-server-js';

@@ -66,8 +67,2 @@ interface StoreOptions {

declare class CookieTransactionStore extends AbstractTransactionStore<StoreOptions> {
set(identifier: string, transactionData: TransactionData, removeIfExists?: boolean, options?: StoreOptions): Promise<void>;
get(identifier: string, options?: StoreOptions): Promise<TransactionData | undefined>;
delete(identifier: string, options?: StoreOptions | undefined): Promise<void>;
}
declare module 'fastify' {

@@ -104,5 +99,15 @@ interface FastifyInstance {

customFetch?: typeof fetch;
routes?: {
login?: string;
callback?: string;
logout?: string;
backchannelLogout?: string;
connect?: string;
connectCallback?: string;
unconnect?: string;
unconnectCallback?: string;
};
}
declare const _default: (fastify: FastifyInstance, options: Auth0FastifyOptions) => Promise<void>;
export { type Auth0FastifyOptions, CookieTransactionStore, type SessionConfiguration, type SessionCookieOptions, type SessionStore, type StoreOptions, _default as default };
export { type Auth0FastifyOptions, type SessionConfiguration, type SessionCookieOptions, type SessionStore, type StoreOptions, _default as default };
// src/index.ts
import fp from "fastify-plugin";
import { ServerClient } from "@auth0/auth0-server-js";
import { CookieTransactionStore, ServerClient, StatelessStateStore, StatefulStateStore } from "@auth0/auth0-server-js";
// src/store/cookie-transaction-store.ts
import { AbstractTransactionStore } from "@auth0/auth0-server-js";
// src/utils.ts
function ensureTrailingSlash(value) {
return value && !value.endsWith("/") ? `${value}/` : value;
}
function ensureNoLeadingSlash(value) {
return value && value.startsWith("/") ? value.substring(1, value.length) : value;
}
function createRouteUrl(url, base) {
return new URL(ensureNoLeadingSlash(url), ensureTrailingSlash(base));
}
function toSafeRedirect(dangerousRedirect, safeBaseUrl) {
let url;
try {
url = createRouteUrl(dangerousRedirect, safeBaseUrl);
} catch {
return void 0;
}
if (url.origin === new URL(safeBaseUrl).origin) {
return url.toString();
}
return void 0;
}

@@ -17,231 +37,34 @@ // src/errors/index.ts

// src/store/cookie-transaction-store.ts
var CookieTransactionStore = class extends AbstractTransactionStore {
async set(identifier, transactionData, removeIfExists, options) {
if (!options) {
// src/store/fastify-cookie-handler.ts
var FastifyCookieHandler = class {
setCookie(name, value, options, storeOptions) {
if (!storeOptions) {
throw new MissingStoreOptionsError();
}
const maxAge = 60 * 60;
const cookieOpts = { httpOnly: true, sameSite: "lax", path: "/", maxAge };
const expiration = Math.floor(Date.now() / 1e3 + maxAge);
const encryptedStateData = await this.encrypt(identifier, transactionData, expiration);
options.reply.setCookie(identifier, encryptedStateData, cookieOpts);
storeOptions.reply.setCookie(name, value, options || {});
}
async get(identifier, options) {
if (!options) {
getCookie(name, storeOptions) {
if (!storeOptions) {
throw new MissingStoreOptionsError();
}
const cookieValue = options.request.cookies[identifier];
if (cookieValue) {
return await this.decrypt(identifier, cookieValue);
}
return storeOptions.request.cookies?.[name];
}
async delete(identifier, options) {
if (!options) {
getCookies(storeOptions) {
if (!storeOptions) {
throw new MissingStoreOptionsError();
}
options?.reply.clearCookie(identifier);
return storeOptions.request.cookies;
}
};
// src/store/stateless-state-store.ts
import { BackchannelLogoutError } from "@auth0/auth0-server-js";
// src/store/abstract-session-store.ts
import { AbstractStateStore } from "@auth0/auth0-server-js";
var AbstractSessionStore = class extends AbstractStateStore {
#rolling;
#absoluteDuration;
#inactivityDuration;
constructor(options) {
super(options);
this.#rolling = options.rolling ?? true;
this.#absoluteDuration = options.absoluteDuration ?? 60 * 60 * 24 * 3;
this.#inactivityDuration = options.inactivityDuration ?? 60 * 60 * 24 * 1;
}
/**
* calculateMaxAge calculates the max age of the session based on createdAt and the rolling and absolute durations.
*/
calculateMaxAge(createdAt) {
if (!this.#rolling) {
return this.#absoluteDuration;
}
const now = Date.now() / 1e3 | 0;
const expiresAt = Math.min(now + this.#inactivityDuration, createdAt + this.#absoluteDuration);
const maxAge = expiresAt - now;
return maxAge > 0 ? maxAge : 0;
}
};
// src/store/stateless-state-store.ts
var StatelessStateStore = class extends AbstractSessionStore {
#cookieOptions;
constructor(options) {
super(options);
this.#cookieOptions = options.cookie;
}
async set(identifier, stateData, removeIfExists, options) {
if (!options) {
deleteCookie(name, storeOptions) {
if (!storeOptions) {
throw new MissingStoreOptionsError();
}
const maxAge = this.calculateMaxAge(stateData.internal.createdAt);
const cookieOpts = {
httpOnly: true,
sameSite: this.#cookieOptions?.sameSite ?? "lax",
path: "/",
secure: this.#cookieOptions?.secure ?? "auto",
maxAge
};
const expiration = Math.floor(Date.now() / 1e3 + maxAge);
const encryptedStateData = await this.encrypt(identifier, stateData, expiration);
const chunkSize = 3072;
const chunkCount = Math.ceil(encryptedStateData.length / chunkSize);
const chunks = [...Array(chunkCount).keys()].map((i) => ({
value: encryptedStateData.substring(i * chunkSize, (i + 1) * chunkSize),
name: `${identifier}.${i}`
}));
chunks.forEach((chunk) => {
options.reply.setCookie(chunk.name, chunk.value, cookieOpts);
});
const existingCookieKeys = this.getCookieKeys(identifier, options);
const cookieKeysToRemove = existingCookieKeys.filter((key) => !chunks.some((chunk) => chunk.name === key));
cookieKeysToRemove.forEach((key) => {
options.reply.clearCookie(key);
});
storeOptions.reply.clearCookie(name);
}
async get(identifier, options) {
if (!options) {
throw new MissingStoreOptionsError();
}
const cookieKeys = this.getCookieKeys(identifier, options);
const encryptedStateData = cookieKeys.map((key) => ({ index: parseInt(key.split(".")[1], 10), value: options.request.cookies[key] })).sort((a, b) => a.index - b.index).map((item) => item.value).join("");
if (encryptedStateData) {
return await this.decrypt(identifier, encryptedStateData);
}
}
async delete(identifier, options) {
if (!options) {
throw new MissingStoreOptionsError();
}
const cookieKeys = this.getCookieKeys(identifier, options);
for (const key of cookieKeys) {
options?.reply.clearCookie(key);
}
}
deleteByLogoutToken() {
throw new BackchannelLogoutError(
"Backchannel logout is not available when using Stateless Storage. Use Stateful Storage by providing a `sessionStore`"
);
}
getCookieKeys(identifier, options) {
return Object.keys(options.request.cookies).filter((key) => key.startsWith(identifier));
}
};
// src/store/stateful-state-store.ts
var generateId = () => {
const bytes = new Uint8Array(16);
crypto.getRandomValues(bytes);
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
};
var StatefulStateStore = class extends AbstractSessionStore {
#store;
#cookieOptions;
constructor(options) {
super(options);
this.#store = options.store;
this.#cookieOptions = options.cookie;
}
async set(identifier, stateData, removeIfExists, options) {
if (!options) {
throw new MissingStoreOptionsError();
}
let sessionId = await this.getSessionId(identifier, options);
if (sessionId && removeIfExists) {
await this.#store.delete(sessionId);
sessionId = generateId();
}
if (!sessionId) {
sessionId = generateId();
}
const maxAge = this.calculateMaxAge(stateData.internal.createdAt);
const cookieOpts = {
httpOnly: true,
sameSite: this.#cookieOptions?.sameSite ?? "lax",
path: "/",
secure: this.#cookieOptions?.secure ?? "auto",
maxAge
};
const expiration = Date.now() / 1e3 + maxAge;
const encryptedStateData = await this.encrypt(
identifier,
{
id: sessionId
},
expiration
);
await this.#store.set(sessionId, stateData);
options.reply.setCookie(identifier, encryptedStateData, cookieOpts);
}
async get(identifier, options) {
if (!options) {
throw new MissingStoreOptionsError();
}
const sessionId = await this.getSessionId(identifier, options);
if (sessionId) {
const stateData = await this.#store.get(sessionId);
if (!stateData) {
options?.reply.clearCookie(identifier);
}
return stateData;
}
}
async delete(identifier, options) {
if (!options) {
throw new MissingStoreOptionsError();
}
const sessionId = await this.getSessionId(identifier, options);
if (sessionId) {
await this.#store.delete(sessionId);
}
options?.reply.clearCookie(identifier);
}
async getSessionId(identifier, options) {
const cookieValue = options.request.cookies[identifier];
if (cookieValue) {
const sessionCookie = await this.decrypt(identifier, cookieValue);
return sessionCookie.id;
}
}
deleteByLogoutToken(claims, options) {
return this.#store.deleteByLogoutToken(claims, options);
}
};
// src/utils.ts
function ensureTrailingSlash(value) {
return value && !value.endsWith("/") ? `${value}/` : value;
}
function ensureNoLeadingSlash(value) {
return value && value.startsWith("/") ? value.substring(1, value.length) : value;
}
function createRouteUrl(url, base) {
return new URL(ensureNoLeadingSlash(url), ensureTrailingSlash(base));
}
function toSafeRedirect(dangerousRedirect, safeBaseUrl) {
let url;
try {
url = createRouteUrl(dangerousRedirect, safeBaseUrl);
} catch {
return void 0;
}
if (url.origin === new URL(safeBaseUrl).origin) {
return url.toString();
}
return void 0;
}
// src/index.ts
import { CookieTransactionStore as CookieTransactionStore2 } from "@auth0/auth0-server-js";
var index_default = fp(async function auth0Fastify(fastify, options) {
const callbackPath = "/auth/callback";
const callbackPath = options.routes?.callback ?? "/auth/callback";
const redirectUri = createRouteUrl(callbackPath, options.appBaseUrl);

@@ -258,3 +81,3 @@ const auth0Client = new ServerClient({

},
transactionStore: new CookieTransactionStore({ secret: options.sessionSecret }),
transactionStore: new CookieTransactionStore({ secret: options.sessionSecret }, new FastifyCookieHandler()),
stateStore: options.sessionStore ? new StatefulStateStore({

@@ -264,6 +87,6 @@ ...options.sessionConfiguration,

store: options.sessionStore
}) : new StatelessStateStore({
}, new FastifyCookieHandler()) : new StatelessStateStore({
...options.sessionConfiguration,
secret: options.sessionSecret
}),
}, new FastifyCookieHandler()),
stateIdentifier: options.sessionConfiguration?.cookie?.name,

@@ -278,3 +101,3 @@ customFetch: options.customFetch

fastify.get(
"/auth/login",
options.routes?.login ?? "/auth/login",
async (request, reply) => {

@@ -293,3 +116,3 @@ const dangerousReturnTo = request.query.returnTo;

);
fastify.get("/auth/callback", async (request, reply) => {
fastify.get(options.routes?.callback ?? "/auth/callback", async (request, reply) => {
const { appState } = await auth0Client.completeInteractiveLogin(

@@ -301,3 +124,3 @@ createRouteUrl(request.url, options.appBaseUrl),

});
fastify.get("/auth/logout", async (request, reply) => {
fastify.get(options.routes?.logout ?? "/auth/logout", async (request, reply) => {
const returnTo = options.appBaseUrl;

@@ -308,3 +131,3 @@ const logoutUrl = await auth0Client.logout({ returnTo: returnTo.toString() }, { request, reply });

fastify.post(
"/auth/backchannel-logout",
options.routes?.backchannelLogout ?? "/auth/backchannel-logout",
async (request, reply) => {

@@ -327,3 +150,3 @@ const logoutToken = request.body.logout_token;

fastify.get(
"/auth/connect",
options.routes?.connect ?? "/auth/connect",
async (request, reply) => {

@@ -339,3 +162,3 @@ const { connection, connectionScope, returnTo } = request.query;

const sanitizedReturnTo = toSafeRedirect(dangerousReturnTo || "/", options.appBaseUrl);
const callbackPath2 = "/auth/connect/callback";
const callbackPath2 = options.routes?.connectCallback ?? "/auth/connect/callback";
const redirectUri2 = createRouteUrl(callbackPath2, options.appBaseUrl);

@@ -358,3 +181,3 @@ const linkUserUrl = await fastify.auth0Client.startLinkUser(

);
fastify.get("/auth/connect/callback", async (request, reply) => {
fastify.get(options.routes?.connectCallback ?? "/auth/connect/callback", async (request, reply) => {
const { appState } = await fastify.auth0Client.completeLinkUser(

@@ -370,3 +193,3 @@ createRouteUrl(request.url, options.appBaseUrl),

fastify.get(
"/auth/unconnect",
options.routes?.unconnect ?? "/auth/unconnect",
async (request, reply) => {

@@ -382,3 +205,3 @@ const { connection, returnTo } = request.query;

const sanitizedReturnTo = toSafeRedirect(dangerousReturnTo || "/", options.appBaseUrl);
const callbackPath2 = "/auth/unconnect/callback";
const callbackPath2 = options.routes?.unconnectCallback ?? "/auth/unconnect/callback";
const redirectUri2 = createRouteUrl(callbackPath2, options.appBaseUrl);

@@ -400,3 +223,3 @@ const linkUserUrl = await fastify.auth0Client.startUnlinkUser(

);
fastify.get("/auth/unconnect/callback", async (request, reply) => {
fastify.get(options.routes?.unconnectCallback ?? "/auth/unconnect/callback", async (request, reply) => {
const { appState } = await fastify.auth0Client.completeUnlinkUser(

@@ -416,5 +239,5 @@ createRouteUrl(request.url, options.appBaseUrl),

export {
CookieTransactionStore,
CookieTransactionStore2 as CookieTransactionStore,
index_default as default
};
//# sourceMappingURL=index.js.map

@@ -1,1 +0,1 @@

{"version":3,"sources":["../src/index.ts","../src/store/cookie-transaction-store.ts","../src/errors/index.ts","../src/store/stateless-state-store.ts","../src/store/abstract-session-store.ts","../src/store/stateful-state-store.ts","../src/utils.ts"],"sourcesContent":["import type { FastifyInstance, FastifyRequest } from 'fastify';\nimport fp from 'fastify-plugin';\nimport { ServerClient } from '@auth0/auth0-server-js';\nimport type { SessionConfiguration, SessionStore, StoreOptions } from './types.js';\nimport { CookieTransactionStore } from './store/cookie-transaction-store.js';\nimport { StatelessStateStore } from './store/stateless-state-store.js';\nimport { StatefulStateStore } from './store/stateful-state-store.js';\nimport { createRouteUrl, toSafeRedirect } from './utils.js';\n\nexport * from './types.js';\nexport { CookieTransactionStore } from './store/cookie-transaction-store.js';\n\ndeclare module 'fastify' {\n interface FastifyInstance {\n auth0Client: ServerClient<StoreOptions> | undefined;\n }\n}\n\nexport interface Auth0FastifyOptions {\n domain: string;\n clientId: string;\n clientSecret?: string;\n clientAssertionSigningKey?: string | CryptoKey;\n clientAssertionSigningAlg?: string;\n audience?: string;\n appBaseUrl: string;\n\n pushedAuthorizationRequests?: boolean;\n\n sessionSecret: string;\n sessionStore?: SessionStore;\n sessionConfiguration?: SessionConfiguration;\n /**\n * Whether to mount the default routes for login, logout, callback and profile.\n * Defaults to true.\n */\n mountRoutes?: boolean;\n /**\n * Whether to mount the routes for account linking and unlinking.\n * Defaults to false.\n */\n mountConnectRoutes?: boolean;\n /**\n * Optional, custom Fetch implementation to use.\n */\n customFetch?: typeof fetch;\n}\n\nexport default fp(async function auth0Fastify(fastify: FastifyInstance, options: Auth0FastifyOptions) {\n const callbackPath = '/auth/callback';\n const redirectUri = createRouteUrl(callbackPath, options.appBaseUrl);\n\n const auth0Client = new ServerClient<StoreOptions>({\n domain: options.domain,\n clientId: options.clientId,\n clientSecret: options.clientSecret,\n clientAssertionSigningKey: options.clientAssertionSigningKey,\n clientAssertionSigningAlg: options.clientAssertionSigningAlg,\n authorizationParams: {\n audience: options.audience,\n redirect_uri: redirectUri.toString(),\n },\n transactionStore: new CookieTransactionStore({ secret: options.sessionSecret }),\n stateStore: options.sessionStore\n ? new StatefulStateStore({\n ...options.sessionConfiguration,\n secret: options.sessionSecret,\n store: options.sessionStore,\n })\n : new StatelessStateStore({\n ...options.sessionConfiguration,\n secret: options.sessionSecret,\n }),\n stateIdentifier: options.sessionConfiguration?.cookie?.name,\n customFetch: options.customFetch,\n });\n\n if (!fastify.hasReplyDecorator('cookie')) {\n fastify.register(import('@fastify/cookie'));\n }\n\n const shouldMountRoutes = options.mountRoutes ?? true;\n\n if (shouldMountRoutes) {\n fastify.get(\n '/auth/login',\n async (\n request: FastifyRequest<{\n Querystring: { returnTo?: string };\n }>,\n reply\n ) => {\n const dangerousReturnTo = request.query.returnTo;\n const sanitizedReturnTo = toSafeRedirect(dangerousReturnTo || '/', options.appBaseUrl);\n\n const authorizationUrl = await auth0Client.startInteractiveLogin(\n {\n pushedAuthorizationRequests: options.pushedAuthorizationRequests,\n appState: { returnTo: sanitizedReturnTo },\n },\n { request, reply }\n );\n\n reply.redirect(authorizationUrl.href);\n }\n );\n\n fastify.get('/auth/callback', async (request, reply) => {\n const { appState } = await auth0Client.completeInteractiveLogin<{ returnTo: string } | undefined>(\n createRouteUrl(request.url, options.appBaseUrl),\n { request, reply }\n );\n\n reply.redirect(appState?.returnTo ?? options.appBaseUrl);\n });\n\n fastify.get('/auth/logout', async (request, reply) => {\n const returnTo = options.appBaseUrl;\n const logoutUrl = await auth0Client.logout({ returnTo: returnTo.toString() }, { request, reply });\n\n reply.redirect(logoutUrl.href);\n });\n\n fastify.post(\n '/auth/backchannel-logout',\n async (\n request: FastifyRequest<{\n Body: { logout_token?: string };\n }>,\n reply\n ) => {\n const logoutToken = request.body.logout_token;\n\n if (!logoutToken) {\n reply.code(400).send('Missing `logout_token` in the request body.');\n\n return;\n }\n\n try {\n await auth0Client.handleBackchannelLogout(logoutToken, { request, reply });\n reply.code(204).send(null);\n } catch (e) {\n reply.code(400).send((e as Error).message);\n }\n }\n );\n\n const shouldMountConnectRoutes = options.mountConnectRoutes ?? false;\n\n if (shouldMountConnectRoutes) {\n fastify.get(\n '/auth/connect',\n async (\n request: FastifyRequest<{\n Querystring: { connection: string; connectionScope: string; returnTo?: string };\n }>,\n reply\n ) => {\n const { connection, connectionScope, returnTo } = request.query;\n const dangerousReturnTo = returnTo;\n\n if (!connection) {\n return reply.code(400).send({\n error: 'invalid_request',\n error_description: 'connection is required',\n });\n }\n\n const sanitizedReturnTo = toSafeRedirect(dangerousReturnTo || '/', options.appBaseUrl);\n const callbackPath = '/auth/connect/callback';\n const redirectUri = createRouteUrl(callbackPath, options.appBaseUrl);\n const linkUserUrl = await fastify.auth0Client!.startLinkUser(\n {\n connection: connection,\n connectionScope: connectionScope,\n authorizationParams: {\n redirect_uri: redirectUri.toString(),\n },\n appState: {\n returnTo: sanitizedReturnTo,\n },\n },\n { request, reply }\n );\n\n reply.redirect(linkUserUrl.href);\n }\n );\n\n fastify.get('/auth/connect/callback', async (request, reply) => {\n const { appState } = await fastify.auth0Client!.completeLinkUser<{ returnTo: string }>(\n createRouteUrl(request.url, options.appBaseUrl),\n {\n request,\n reply,\n }\n );\n\n reply.redirect(appState?.returnTo ?? options.appBaseUrl);\n });\n\n fastify.get(\n '/auth/unconnect',\n async (\n request: FastifyRequest<{\n Querystring: { connection: string; returnTo?: string };\n }>,\n reply\n ) => {\n const { connection, returnTo } = request.query;\n const dangerousReturnTo = returnTo;\n\n if (!connection) {\n return reply.code(400).send({\n error: 'invalid_request',\n error_description: 'connection is required',\n });\n }\n\n const sanitizedReturnTo = toSafeRedirect(dangerousReturnTo || '/', options.appBaseUrl);\n const callbackPath = '/auth/unconnect/callback';\n const redirectUri = createRouteUrl(callbackPath, options.appBaseUrl);\n const linkUserUrl = await fastify.auth0Client!.startUnlinkUser(\n {\n connection: connection,\n authorizationParams: {\n redirect_uri: redirectUri.toString(),\n },\n appState: {\n returnTo: sanitizedReturnTo,\n },\n },\n { request, reply }\n );\n\n reply.redirect(linkUserUrl.href);\n }\n );\n\n fastify.get('/auth/unconnect/callback', async (request, reply) => {\n const { appState } = await fastify.auth0Client!.completeUnlinkUser<{ returnTo: string }>(\n createRouteUrl(request.url, options.appBaseUrl),\n {\n request,\n reply,\n }\n );\n\n reply.redirect(appState?.returnTo ?? options.appBaseUrl);\n });\n }\n }\n\n fastify.decorate('auth0Client', auth0Client);\n});\n","import { CookieSerializeOptions } from '@fastify/cookie';\nimport { TransactionData, AbstractTransactionStore } from '@auth0/auth0-server-js';\nimport { MissingStoreOptionsError } from '../errors/index.js';\nimport { StoreOptions } from '../types.js';\n\nexport class CookieTransactionStore extends AbstractTransactionStore<StoreOptions> {\n async set(\n identifier: string,\n transactionData: TransactionData,\n removeIfExists?: boolean,\n options?: StoreOptions\n ): Promise<void> {\n // We can not handle cookies in Fastify when the `StoreOptions` are not provided.\n if (!options) {\n throw new MissingStoreOptionsError();\n }\n\n const maxAge = 60 * 60;\n const cookieOpts: CookieSerializeOptions = { httpOnly: true, sameSite: 'lax', path: '/', maxAge };\n const expiration = Math.floor(Date.now() / 1000 + maxAge);\n const encryptedStateData = await this.encrypt(identifier, transactionData, expiration);\n \n options.reply.setCookie(identifier, encryptedStateData, cookieOpts);\n }\n\n async get(identifier: string, options?: StoreOptions): Promise<TransactionData | undefined> {\n // We can not handle cookies in Fastify when the `StoreOptions` are not provided.\n if (!options) {\n throw new MissingStoreOptionsError();\n }\n\n const cookieValue = options.request.cookies[identifier];\n\n if (cookieValue) {\n return await this.decrypt(identifier, cookieValue);\n }\n }\n\n async delete(identifier: string, options?: StoreOptions | undefined): Promise<void> {\n // We can not handle cookies in Fastify when the `StoreOptions` are not provided.\n if (!options) {\n throw new MissingStoreOptionsError();\n }\n\n options?.reply.clearCookie(identifier);\n }\n}\n","export class MissingStoreOptionsError extends Error {\n public code: string = 'missing_store_options_error';\n\n constructor(message?: string) {\n super(message ?? 'The store options are missing, making it impossible to interact with the store.');\n this.name = 'MissingStoreOptionsError';\n }\n}\n","import type { CookieSerializeOptions } from '@fastify/cookie';\nimport { BackchannelLogoutError, EncryptedStoreOptions, StateData } from '@auth0/auth0-server-js';\nimport { MissingStoreOptionsError } from '../errors/index.js';\nimport type { SessionConfiguration, SessionCookieOptions, StoreOptions } from '../types.js';\nimport { AbstractSessionStore } from './abstract-session-store.js';\n\nexport class StatelessStateStore extends AbstractSessionStore {\n readonly #cookieOptions: SessionCookieOptions | undefined;\n\n constructor(options: SessionConfiguration & EncryptedStoreOptions) {\n super(options);\n\n this.#cookieOptions = options.cookie;\n }\n\n async set(\n identifier: string,\n stateData: StateData,\n removeIfExists?: boolean,\n options?: StoreOptions | undefined\n ): Promise<void> {\n // We can not handle cookies in Fastify when the `StoreOptions` are not provided.\n if (!options) {\n throw new MissingStoreOptionsError();\n }\n\n const maxAge = this.calculateMaxAge(stateData.internal.createdAt);\n const cookieOpts: CookieSerializeOptions = {\n httpOnly: true,\n sameSite: this.#cookieOptions?.sameSite ?? 'lax',\n path: '/',\n secure: this.#cookieOptions?.secure ?? 'auto',\n maxAge,\n };\n const expiration = Math.floor(Date.now() / 1000 + maxAge);\n const encryptedStateData = await this.encrypt(identifier, stateData, expiration);\n\n const chunkSize = 3072;\n const chunkCount = Math.ceil(encryptedStateData.length / chunkSize);\n const chunks = [...Array(chunkCount).keys()].map((i) => ({\n value: encryptedStateData.substring(i * chunkSize, (i + 1) * chunkSize),\n name: `${identifier}.${i}`,\n }));\n\n chunks.forEach((chunk) => {\n options.reply.setCookie(chunk.name, chunk.value, cookieOpts);\n });\n\n const existingCookieKeys = this.getCookieKeys(identifier, options);\n const cookieKeysToRemove = existingCookieKeys.filter((key) => !chunks.some((chunk) => chunk.name === key));\n cookieKeysToRemove.forEach((key) => {\n options.reply.clearCookie(key);\n });\n }\n\n async get(identifier: string, options?: StoreOptions | undefined): Promise<StateData | undefined> {\n // We can not handle cookies in Fastify when the `StoreOptions` are not provided.\n if (!options) {\n throw new MissingStoreOptionsError();\n }\n\n const cookieKeys = this.getCookieKeys(identifier, options);\n const encryptedStateData = cookieKeys\n .map((key) => ({ index: parseInt(key.split('.')[1] as string, 10), value: options.request.cookies[key] }))\n .sort((a, b) => a.index - b.index)\n .map((item) => item.value)\n .join('');\n\n if (encryptedStateData) {\n return (await this.decrypt(identifier, encryptedStateData)) as StateData;\n }\n }\n\n async delete(identifier: string, options?: StoreOptions | undefined): Promise<void> {\n // We can not handle cookies in Fastify when the `StoreOptions` are not provided.\n if (!options) {\n throw new MissingStoreOptionsError();\n }\n\n const cookieKeys = this.getCookieKeys(identifier, options);\n for (const key of cookieKeys) {\n options?.reply.clearCookie(key);\n }\n }\n\n deleteByLogoutToken(): Promise<void> {\n throw new BackchannelLogoutError(\n 'Backchannel logout is not available when using Stateless Storage. Use Stateful Storage by providing a `sessionStore`'\n );\n }\n\n private getCookieKeys(identifier: string, options: StoreOptions): string[] {\n return Object.keys(options.request.cookies).filter((key) => key.startsWith(identifier));\n }\n}\n","import { AbstractStateStore, EncryptedStoreOptions, LogoutTokenClaims, StateData } from '@auth0/auth0-server-js';\nimport type { SessionConfiguration, StoreOptions } from '../types.js';\n\nexport abstract class AbstractSessionStore extends AbstractStateStore<StoreOptions> {\n readonly #rolling: boolean;\n readonly #absoluteDuration: number;\n readonly #inactivityDuration: number;\n\n constructor(options: SessionConfiguration & EncryptedStoreOptions) {\n super(options);\n\n this.#rolling = options.rolling ?? true;\n this.#absoluteDuration = options.absoluteDuration ?? 60 * 60 * 24 * 3;\n this.#inactivityDuration = options.inactivityDuration ?? 60 * 60 * 24 * 1;\n }\n\n abstract set(\n identifier: string,\n stateData: StateData,\n removeIfExists?: boolean,\n options?: StoreOptions | undefined\n ): Promise<void>;\n\n abstract get(identifier: string, options?: StoreOptions | undefined): Promise<StateData | undefined>;\n\n abstract delete(identifier: string, options?: StoreOptions | undefined): Promise<void>;\n\n abstract deleteByLogoutToken(claims: LogoutTokenClaims, options?: StoreOptions | undefined): Promise<void>;\n\n /**\n * calculateMaxAge calculates the max age of the session based on createdAt and the rolling and absolute durations.\n */\n protected calculateMaxAge(createdAt: number) {\n if (!this.#rolling) {\n return this.#absoluteDuration;\n }\n\n const now = (Date.now() / 1000) | 0;\n const expiresAt = Math.min(now + this.#inactivityDuration, createdAt + this.#absoluteDuration);\n const maxAge = expiresAt - now;\n\n return maxAge > 0 ? maxAge : 0;\n }\n}\n","import type { CookieSerializeOptions } from '@fastify/cookie';\nimport { EncryptedStoreOptions, LogoutTokenClaims, StateData } from '@auth0/auth0-server-js';\nimport { MissingStoreOptionsError } from '../errors/index.js';\nimport type { SessionConfiguration, SessionCookieOptions, SessionStore, StoreOptions } from '../types.js';\nimport { AbstractSessionStore } from './abstract-session-store.js';\n\nexport interface StatefulStateStoreOptions extends EncryptedStoreOptions {\n store: SessionStore;\n}\n\nconst generateId = () => {\n const bytes = new Uint8Array(16);\n crypto.getRandomValues(bytes);\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n};\n\nexport class StatefulStateStore extends AbstractSessionStore {\n readonly #store: SessionStore;\n readonly #cookieOptions: SessionCookieOptions | undefined;\n\n constructor(options: StatefulStateStoreOptions & SessionConfiguration) {\n super(options);\n\n this.#store = options.store;\n this.#cookieOptions = options.cookie;\n }\n\n async set(\n identifier: string,\n stateData: StateData,\n removeIfExists?: boolean,\n options?: StoreOptions | undefined\n ): Promise<void> {\n // We can not handle cookies in Fastify when the `StoreOptions` are not provided.\n if (!options) {\n throw new MissingStoreOptionsError();\n }\n\n let sessionId = await this.getSessionId(identifier, options);\n\n // if this is a new session created by a new login we need to remove the old session\n // from the store and regenerate the session ID to prevent session fixation.\n if (sessionId && removeIfExists) {\n await this.#store.delete(sessionId);\n sessionId = generateId();\n }\n\n if (!sessionId) {\n sessionId = generateId();\n }\n\n const maxAge = this.calculateMaxAge(stateData.internal.createdAt);\n const cookieOpts: CookieSerializeOptions = {\n httpOnly: true,\n sameSite: this.#cookieOptions?.sameSite ?? 'lax',\n path: '/',\n secure: this.#cookieOptions?.secure ?? 'auto',\n maxAge,\n };\n const expiration = Date.now() / 1000 + maxAge;\n const encryptedStateData = await this.encrypt<{ id: string }>(\n identifier,\n {\n id: sessionId,\n },\n expiration\n );\n\n await this.#store.set(sessionId, stateData);\n\n options.reply.setCookie(identifier, encryptedStateData, cookieOpts);\n }\n\n async get(identifier: string, options?: StoreOptions | undefined): Promise<StateData | undefined> {\n // We can not handle cookies in Fastify when the `StoreOptions` are not provided.\n if (!options) {\n throw new MissingStoreOptionsError();\n }\n\n const sessionId = await this.getSessionId(identifier, options);\n\n if (sessionId) {\n const stateData = await this.#store.get(sessionId);\n\n // If we have a session cookie, but no `stateData`, we should remove the cookie.\n if (!stateData) {\n options?.reply.clearCookie(identifier);\n }\n\n return stateData;\n }\n }\n\n async delete(identifier: string, options?: StoreOptions | undefined): Promise<void> {\n // We can not handle cookies in Fastify when the `StoreOptions` are not provided.\n if (!options) {\n throw new MissingStoreOptionsError();\n }\n\n const sessionId = await this.getSessionId(identifier, options);\n\n if (sessionId) {\n await this.#store.delete(sessionId);\n }\n\n options?.reply.clearCookie(identifier);\n }\n\n private async getSessionId(identifier: string, options: StoreOptions) {\n const cookieValue = options.request.cookies[identifier];\n if (cookieValue) {\n const sessionCookie = await this.decrypt<{ id: string }>(identifier, cookieValue);\n return sessionCookie.id;\n }\n }\n\n deleteByLogoutToken(claims: LogoutTokenClaims, options?: StoreOptions | undefined): Promise<void> {\n return this.#store.deleteByLogoutToken(claims, options);\n }\n}\n","/**\n * Ensures the value has a trailing slash.\n * If it does not, it will append one.\n * @param value The value to ensure has a trailing slash.\n * @returns The value with a trailing slash.\n */\nfunction ensureTrailingSlash(value: string) {\n return value && !value.endsWith('/') ? `${value}/` : value;\n}\n\n/**\n * Ensures the value does not have a leading slash.\n * If it does, it will trim it.\n * @param value The value to ensure has no leading slash.\n * @returns The value without a leading slash.\n */\nfunction ensureNoLeadingSlash(value: string) {\n return value && value.startsWith('/') ? value.substring(1, value.length) : value;\n}\n\n/**\n * Utility function to ensure Route URLs are created correctly when using both the root and subpath as base URL.\n * @param url The URL to use.\n * @param base The base URL to use.\n * @returns A URL object, combining the base and url.\n */\nexport function createRouteUrl(url: string, base: string) {\n return new URL(ensureNoLeadingSlash(url), ensureTrailingSlash(base));\n}\n\n/**\n * Function to ensure a redirect URL is safe to use, as in, it has the same origin as the safeBaseUrl.\n * @param dangerousRedirect The redirect URL to check.\n * @param safeBaseUrl The base URL to check against.\n * @returns A safe redirect URL or undefined if the redirect URL is not safe.\n */\nexport function toSafeRedirect(dangerousRedirect: string, safeBaseUrl: string): string | undefined {\n let url: URL;\n\n try {\n url = createRouteUrl(dangerousRedirect, safeBaseUrl);\n } catch {\n return undefined;\n }\n\n if (url.origin === new URL(safeBaseUrl).origin) {\n return url.toString();\n }\n\n return undefined;\n}"],"mappings":"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","names":["callbackPath","redirectUri"]}
{"version":3,"sources":["../src/index.ts","../src/utils.ts","../src/errors/index.ts","../src/store/fastify-cookie-handler.ts"],"sourcesContent":["import type { FastifyInstance, FastifyRequest } from 'fastify';\nimport fp from 'fastify-plugin';\nimport { CookieTransactionStore, ServerClient, StatelessStateStore, StatefulStateStore } from '@auth0/auth0-server-js';\nimport type { SessionConfiguration, SessionStore, StoreOptions } from './types.js';\nimport { createRouteUrl, toSafeRedirect } from './utils.js';\nimport { FastifyCookieHandler } from './store/fastify-cookie-handler.js';\n\nexport * from './types.js';\nexport { CookieTransactionStore } from '@auth0/auth0-server-js';\n\ndeclare module 'fastify' {\n interface FastifyInstance {\n auth0Client: ServerClient<StoreOptions> | undefined;\n }\n}\n\nexport interface Auth0FastifyOptions {\n domain: string;\n clientId: string;\n clientSecret?: string;\n clientAssertionSigningKey?: string | CryptoKey;\n clientAssertionSigningAlg?: string;\n audience?: string;\n appBaseUrl: string;\n\n pushedAuthorizationRequests?: boolean;\n\n sessionSecret: string;\n sessionStore?: SessionStore;\n sessionConfiguration?: SessionConfiguration;\n /**\n * Whether to mount the default routes for login, logout, callback and profile.\n * Defaults to true.\n */\n mountRoutes?: boolean;\n /**\n * Whether to mount the routes for account linking and unlinking.\n * Defaults to false.\n */\n mountConnectRoutes?: boolean;\n /**\n * Optional, custom Fetch implementation to use.\n */\n customFetch?: typeof fetch;\n\n routes?: {\n login?: string;\n callback?: string;\n logout?: string;\n backchannelLogout?: string;\n connect?: string;\n connectCallback?: string;\n unconnect?: string;\n unconnectCallback?: string;\n }\n}\n\nexport default fp(async function auth0Fastify(fastify: FastifyInstance, options: Auth0FastifyOptions) {\n const callbackPath = options.routes?.callback ?? '/auth/callback';\n const redirectUri = createRouteUrl(callbackPath, options.appBaseUrl);\n\n const auth0Client = new ServerClient<StoreOptions>({\n domain: options.domain,\n clientId: options.clientId,\n clientSecret: options.clientSecret,\n clientAssertionSigningKey: options.clientAssertionSigningKey,\n clientAssertionSigningAlg: options.clientAssertionSigningAlg,\n authorizationParams: {\n audience: options.audience,\n redirect_uri: redirectUri.toString(),\n },\n transactionStore: new CookieTransactionStore({ secret: options.sessionSecret }, new FastifyCookieHandler()),\n stateStore: options.sessionStore\n ? new StatefulStateStore({\n ...options.sessionConfiguration,\n secret: options.sessionSecret,\n store: options.sessionStore,\n }, new FastifyCookieHandler())\n : new StatelessStateStore({\n ...options.sessionConfiguration,\n secret: options.sessionSecret,\n }, new FastifyCookieHandler()),\n stateIdentifier: options.sessionConfiguration?.cookie?.name,\n customFetch: options.customFetch,\n });\n\n if (!fastify.hasReplyDecorator('cookie')) {\n fastify.register(import('@fastify/cookie'));\n }\n\n const shouldMountRoutes = options.mountRoutes ?? true;\n\n if (shouldMountRoutes) {\n fastify.get(\n options.routes?.login ?? '/auth/login',\n async (\n request: FastifyRequest<{\n Querystring: { returnTo?: string };\n }>,\n reply\n ) => {\n const dangerousReturnTo = request.query.returnTo;\n const sanitizedReturnTo = toSafeRedirect(dangerousReturnTo || '/', options.appBaseUrl);\n\n const authorizationUrl = await auth0Client.startInteractiveLogin(\n {\n pushedAuthorizationRequests: options.pushedAuthorizationRequests,\n appState: { returnTo: sanitizedReturnTo },\n },\n { request, reply }\n );\n\n reply.redirect(authorizationUrl.href);\n }\n );\n\n fastify.get(options.routes?.callback ?? '/auth/callback', async (request, reply) => {\n const { appState } = await auth0Client.completeInteractiveLogin<{ returnTo: string } | undefined>(\n createRouteUrl(request.url, options.appBaseUrl),\n { request, reply }\n );\n\n reply.redirect(appState?.returnTo ?? options.appBaseUrl);\n });\n\n fastify.get(options.routes?.logout ?? '/auth/logout', async (request, reply) => {\n const returnTo = options.appBaseUrl;\n const logoutUrl = await auth0Client.logout({ returnTo: returnTo.toString() }, { request, reply });\n\n reply.redirect(logoutUrl.href);\n });\n\n fastify.post(\n options.routes?.backchannelLogout ?? '/auth/backchannel-logout',\n async (\n request: FastifyRequest<{\n Body: { logout_token?: string };\n }>,\n reply\n ) => {\n const logoutToken = request.body.logout_token;\n\n if (!logoutToken) {\n reply.code(400).send('Missing `logout_token` in the request body.');\n\n return;\n }\n\n try {\n await auth0Client.handleBackchannelLogout(logoutToken, { request, reply });\n reply.code(204).send(null);\n } catch (e) {\n reply.code(400).send((e as Error).message);\n }\n }\n );\n\n const shouldMountConnectRoutes = options.mountConnectRoutes ?? false;\n\n if (shouldMountConnectRoutes) {\n fastify.get(\n options.routes?.connect ?? '/auth/connect',\n async (\n request: FastifyRequest<{\n Querystring: { connection: string; connectionScope: string; returnTo?: string };\n }>,\n reply\n ) => {\n const { connection, connectionScope, returnTo } = request.query;\n const dangerousReturnTo = returnTo;\n\n if (!connection) {\n return reply.code(400).send({\n error: 'invalid_request',\n error_description: 'connection is required',\n });\n }\n\n const sanitizedReturnTo = toSafeRedirect(dangerousReturnTo || '/', options.appBaseUrl);\n const callbackPath = options.routes?.connectCallback ?? '/auth/connect/callback';\n const redirectUri = createRouteUrl(callbackPath, options.appBaseUrl);\n const linkUserUrl = await fastify.auth0Client!.startLinkUser(\n {\n connection: connection,\n connectionScope: connectionScope,\n authorizationParams: {\n redirect_uri: redirectUri.toString(),\n },\n appState: {\n returnTo: sanitizedReturnTo,\n },\n },\n { request, reply }\n );\n\n reply.redirect(linkUserUrl.href);\n }\n );\n\n fastify.get(options.routes?.connectCallback ?? '/auth/connect/callback', async (request, reply) => {\n const { appState } = await fastify.auth0Client!.completeLinkUser<{ returnTo: string }>(\n createRouteUrl(request.url, options.appBaseUrl),\n {\n request,\n reply,\n }\n );\n\n reply.redirect(appState?.returnTo ?? options.appBaseUrl);\n });\n\n fastify.get(\n options.routes?.unconnect ?? '/auth/unconnect',\n async (\n request: FastifyRequest<{\n Querystring: { connection: string; returnTo?: string };\n }>,\n reply\n ) => {\n const { connection, returnTo } = request.query;\n const dangerousReturnTo = returnTo;\n\n if (!connection) {\n return reply.code(400).send({\n error: 'invalid_request',\n error_description: 'connection is required',\n });\n }\n\n const sanitizedReturnTo = toSafeRedirect(dangerousReturnTo || '/', options.appBaseUrl);\n const callbackPath = options.routes?.unconnectCallback ?? '/auth/unconnect/callback';\n const redirectUri = createRouteUrl(callbackPath, options.appBaseUrl);\n const linkUserUrl = await fastify.auth0Client!.startUnlinkUser(\n {\n connection: connection,\n authorizationParams: {\n redirect_uri: redirectUri.toString(),\n },\n appState: {\n returnTo: sanitizedReturnTo,\n },\n },\n { request, reply }\n );\n\n reply.redirect(linkUserUrl.href);\n }\n );\n\n fastify.get(options.routes?.unconnectCallback ?? '/auth/unconnect/callback', async (request, reply) => {\n const { appState } = await fastify.auth0Client!.completeUnlinkUser<{ returnTo: string }>(\n createRouteUrl(request.url, options.appBaseUrl),\n {\n request,\n reply,\n }\n );\n\n reply.redirect(appState?.returnTo ?? options.appBaseUrl);\n });\n }\n }\n\n fastify.decorate('auth0Client', auth0Client);\n});\n","/**\n * Ensures the value has a trailing slash.\n * If it does not, it will append one.\n * @param value The value to ensure has a trailing slash.\n * @returns The value with a trailing slash.\n */\nfunction ensureTrailingSlash(value: string) {\n return value && !value.endsWith('/') ? `${value}/` : value;\n}\n\n/**\n * Ensures the value does not have a leading slash.\n * If it does, it will trim it.\n * @param value The value to ensure has no leading slash.\n * @returns The value without a leading slash.\n */\nfunction ensureNoLeadingSlash(value: string) {\n return value && value.startsWith('/') ? value.substring(1, value.length) : value;\n}\n\n/**\n * Utility function to ensure Route URLs are created correctly when using both the root and subpath as base URL.\n * @param url The URL to use.\n * @param base The base URL to use.\n * @returns A URL object, combining the base and url.\n */\nexport function createRouteUrl(url: string, base: string) {\n return new URL(ensureNoLeadingSlash(url), ensureTrailingSlash(base));\n}\n\n/**\n * Function to ensure a redirect URL is safe to use, as in, it has the same origin as the safeBaseUrl.\n * @param dangerousRedirect The redirect URL to check.\n * @param safeBaseUrl The base URL to check against.\n * @returns A safe redirect URL or undefined if the redirect URL is not safe.\n */\nexport function toSafeRedirect(dangerousRedirect: string, safeBaseUrl: string): string | undefined {\n let url: URL;\n\n try {\n url = createRouteUrl(dangerousRedirect, safeBaseUrl);\n } catch {\n return undefined;\n }\n\n if (url.origin === new URL(safeBaseUrl).origin) {\n return url.toString();\n }\n\n return undefined;\n}","export class MissingStoreOptionsError extends Error {\n public code: string = 'missing_store_options_error';\n\n constructor(message?: string) {\n super(message ?? 'The store options are missing, making it impossible to interact with the store.');\n this.name = 'MissingStoreOptionsError';\n }\n}\n","import { CookieHandler, CookieSerializeOptions } from '@auth0/auth0-server-js';\nimport { StoreOptions } from '../types.js';\nimport { MissingStoreOptionsError } from '../errors/index.js';\n\nexport class FastifyCookieHandler implements CookieHandler<StoreOptions> {\n setCookie(\n name: string,\n value: string,\n options?: CookieSerializeOptions,\n storeOptions?: StoreOptions,\n ): void {\n if (!storeOptions) {\n throw new MissingStoreOptionsError();\n }\n\n storeOptions.reply.setCookie(name, value, options || {});\n }\n\n getCookie(name: string, storeOptions?: StoreOptions): string | undefined {\n if (!storeOptions) {\n throw new MissingStoreOptionsError();\n }\n\n return storeOptions.request.cookies?.[name];\n }\n\n getCookies(storeOptions?: StoreOptions): Record<string, string> {\n if (!storeOptions) {\n throw new MissingStoreOptionsError();\n }\n\n return storeOptions.request.cookies as Record<string, string>;\n }\n\n deleteCookie(name: string, storeOptions?: StoreOptions): void {\n if (!storeOptions) {\n throw new MissingStoreOptionsError();\n }\n\n storeOptions.reply.clearCookie(name);\n }\n}\n"],"mappings":"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","names":["CookieTransactionStore","callbackPath","redirectUri"]}
{
"name": "@auth0/auth0-fastify",
"version": "1.0.2",
"version": "1.1.0",
"description": "Auth0 Authentication SDK for Fastify Applications on JavaScript runtimes",

@@ -30,2 +30,3 @@ "author": "Auth0",

"eslint": "^9.20.1",
"msw": "^2.11.3",
"tsup": "^8.4.0",

@@ -37,5 +38,5 @@ "typescript": "^5.7.3",

"dependencies": {
"@auth0/auth0-server-js": "^1.0.0",
"@auth0/auth0-server-js": "^1.1.0",
"@fastify/cookie": "^11.0.2",
"fastify": "^5.2.1",
"fastify": "^5.3.2",
"fastify-plugin": "^5.0.1"

@@ -47,15 +48,15 @@ },

"publishConfig": {
"access": "public"
"access": "public"
},
"repository": {
"type": "git",
"url": "git://github.com/auth0/auth0-fastify.git"
"type": "git",
"url": "git://github.com/auth0/auth0-fastify.git"
},
"bugs": {
"url": "https://github.com/auth0/auth0-fastify/issues"
"url": "https://github.com/auth0/auth0-fastify/issues"
},
"homepage": "https://github.com/auth0/auth0-fastify#readme",
"keywords": [
"auth0"
"auth0"
]
}