@auth0/auth0-fastify
Advanced tools
+78
-27
@@ -102,5 +102,36 @@ "use strict"; | ||
| var import_auth0_server_js2 = require("@auth0/auth0-server-js"); | ||
| var assertAppBaseUrl = (value) => { | ||
| try { | ||
| new URL(value); | ||
| } catch { | ||
| throw new Error("appBaseUrl must be an absolute URL."); | ||
| } | ||
| return value; | ||
| }; | ||
| var getHeaderValue = (value) => Array.isArray(value) ? value[0] : value; | ||
| var inferAppBaseUrlFromRequest = (request) => { | ||
| const hostHeader = getHeaderValue(request.headers["x-forwarded-host"]) ?? getHeaderValue(request.headers.host); | ||
| if (!hostHeader) { | ||
| throw new Error("Unable to infer appBaseUrl: missing host header."); | ||
| } | ||
| const forwardedProto = getHeaderValue(request.headers["x-forwarded-proto"]); | ||
| const protocol = (forwardedProto ?? request.protocol).toString().split(",")[0]?.trim(); | ||
| if (!protocol) { | ||
| throw new Error("Unable to infer appBaseUrl: missing protocol."); | ||
| } | ||
| return assertAppBaseUrl(`${protocol}://${hostHeader}`); | ||
| }; | ||
| var index_default = (0, import_fastify_plugin.default)(async function auth0Fastify(fastify, options) { | ||
| const callbackPath = options.routes?.callback ?? "/auth/callback"; | ||
| const redirectUri = createRouteUrl(callbackPath, options.appBaseUrl); | ||
| const staticAppBaseUrl = options.appBaseUrl ? assertAppBaseUrl(options.appBaseUrl) : void 0; | ||
| if (typeof options.domain === "string" && !staticAppBaseUrl) { | ||
| throw new Error("appBaseUrl is required when domain is a string."); | ||
| } | ||
| const staticRedirectUri = staticAppBaseUrl ? createRouteUrl(callbackPath, staticAppBaseUrl) : void 0; | ||
| const resolveAppBaseUrl = (request) => { | ||
| if (staticAppBaseUrl) { | ||
| return staticAppBaseUrl; | ||
| } | ||
| return inferAppBaseUrlFromRequest(request); | ||
| }; | ||
| const auth0Client = new import_auth0_server_js.ServerClient({ | ||
@@ -114,13 +145,23 @@ domain: options.domain, | ||
| audience: options.audience, | ||
| redirect_uri: redirectUri.toString() | ||
| ...staticRedirectUri ? { redirect_uri: staticRedirectUri.toString() } : {} | ||
| }, | ||
| 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 FastifyCookieHandler()) : new import_auth0_server_js.StatelessStateStore({ | ||
| ...options.sessionConfiguration, | ||
| secret: options.sessionSecret | ||
| }, new FastifyCookieHandler()), | ||
| discoveryCache: options.discoveryCache, | ||
| 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 FastifyCookieHandler() | ||
| ) : new import_auth0_server_js.StatelessStateStore( | ||
| { | ||
| ...options.sessionConfiguration, | ||
| secret: options.sessionSecret | ||
| }, | ||
| new FastifyCookieHandler() | ||
| ), | ||
| stateIdentifier: options.sessionConfiguration?.cookie?.name, | ||
@@ -137,8 +178,13 @@ customFetch: options.customFetch | ||
| async (request, reply) => { | ||
| const appBaseUrl = resolveAppBaseUrl(request); | ||
| const dangerousReturnTo = request.query.returnTo; | ||
| const sanitizedReturnTo = toSafeRedirect(dangerousReturnTo || "/", options.appBaseUrl); | ||
| const sanitizedReturnTo = toSafeRedirect(dangerousReturnTo || "/", appBaseUrl); | ||
| const redirectUri = createRouteUrl(callbackPath, appBaseUrl); | ||
| const authorizationUrl = await auth0Client.startInteractiveLogin( | ||
| { | ||
| pushedAuthorizationRequests: options.pushedAuthorizationRequests, | ||
| appState: { returnTo: sanitizedReturnTo } | ||
| appState: { returnTo: sanitizedReturnTo }, | ||
| authorizationParams: { | ||
| redirect_uri: redirectUri.toString() | ||
| } | ||
| }, | ||
@@ -151,11 +197,12 @@ { request, reply } | ||
| fastify.get(options.routes?.callback ?? "/auth/callback", async (request, reply) => { | ||
| const appBaseUrl = resolveAppBaseUrl(request); | ||
| const { appState } = await auth0Client.completeInteractiveLogin( | ||
| createRouteUrl(request.url, options.appBaseUrl), | ||
| createRouteUrl(request.url, appBaseUrl), | ||
| { request, reply } | ||
| ); | ||
| reply.redirect(appState?.returnTo ?? options.appBaseUrl); | ||
| reply.redirect(appState?.returnTo ?? appBaseUrl); | ||
| }); | ||
| fastify.get(options.routes?.logout ?? "/auth/logout", async (request, reply) => { | ||
| const returnTo = options.appBaseUrl; | ||
| const logoutUrl = await auth0Client.logout({ returnTo: returnTo.toString() }, { request, reply }); | ||
| const appBaseUrl = resolveAppBaseUrl(request); | ||
| const logoutUrl = await auth0Client.logout({ returnTo: appBaseUrl.toString() }, { request, reply }); | ||
| reply.redirect(logoutUrl.href); | ||
@@ -192,5 +239,6 @@ }); | ||
| } | ||
| const sanitizedReturnTo = toSafeRedirect(dangerousReturnTo || "/", options.appBaseUrl); | ||
| const appBaseUrl = resolveAppBaseUrl(request); | ||
| const sanitizedReturnTo = toSafeRedirect(dangerousReturnTo || "/", appBaseUrl); | ||
| const callbackPath2 = options.routes?.connectCallback ?? "/auth/connect/callback"; | ||
| const redirectUri2 = createRouteUrl(callbackPath2, options.appBaseUrl); | ||
| const redirectUri = createRouteUrl(callbackPath2, appBaseUrl); | ||
| const linkUserUrl = await fastify.auth0Client.startLinkUser( | ||
@@ -201,3 +249,3 @@ { | ||
| authorizationParams: { | ||
| redirect_uri: redirectUri2.toString() | ||
| redirect_uri: redirectUri.toString() | ||
| }, | ||
@@ -214,4 +262,5 @@ appState: { | ||
| fastify.get(options.routes?.connectCallback ?? "/auth/connect/callback", async (request, reply) => { | ||
| const appBaseUrl = resolveAppBaseUrl(request); | ||
| const { appState } = await fastify.auth0Client.completeLinkUser( | ||
| createRouteUrl(request.url, options.appBaseUrl), | ||
| createRouteUrl(request.url, appBaseUrl), | ||
| { | ||
@@ -222,3 +271,3 @@ request, | ||
| ); | ||
| reply.redirect(appState?.returnTo ?? options.appBaseUrl); | ||
| reply.redirect(appState?.returnTo ?? appBaseUrl); | ||
| }); | ||
@@ -236,5 +285,6 @@ fastify.get( | ||
| } | ||
| const sanitizedReturnTo = toSafeRedirect(dangerousReturnTo || "/", options.appBaseUrl); | ||
| const appBaseUrl = resolveAppBaseUrl(request); | ||
| const sanitizedReturnTo = toSafeRedirect(dangerousReturnTo || "/", appBaseUrl); | ||
| const callbackPath2 = options.routes?.unconnectCallback ?? "/auth/unconnect/callback"; | ||
| const redirectUri2 = createRouteUrl(callbackPath2, options.appBaseUrl); | ||
| const redirectUri = createRouteUrl(callbackPath2, appBaseUrl); | ||
| const linkUserUrl = await fastify.auth0Client.startUnlinkUser( | ||
@@ -244,3 +294,3 @@ { | ||
| authorizationParams: { | ||
| redirect_uri: redirectUri2.toString() | ||
| redirect_uri: redirectUri.toString() | ||
| }, | ||
@@ -257,4 +307,5 @@ appState: { | ||
| fastify.get(options.routes?.unconnectCallback ?? "/auth/unconnect/callback", async (request, reply) => { | ||
| const appBaseUrl = resolveAppBaseUrl(request); | ||
| const { appState } = await fastify.auth0Client.completeUnlinkUser( | ||
| createRouteUrl(request.url, options.appBaseUrl), | ||
| createRouteUrl(request.url, appBaseUrl), | ||
| { | ||
@@ -265,3 +316,3 @@ request, | ||
| ); | ||
| reply.redirect(appState?.returnTo ?? options.appBaseUrl); | ||
| reply.redirect(appState?.returnTo ?? appBaseUrl); | ||
| }); | ||
@@ -268,0 +319,0 @@ } |
@@ -1,1 +0,1 @@ | ||
| {"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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,4BAAe;AACf,6BAA8F;;;ACI9F,SAAS,oBAAoB,OAAe;AAC1C,SAAO,SAAS,CAAC,MAAM,SAAS,GAAG,IAAI,GAAG,KAAK,MAAM;AACvD;AAQA,SAAS,qBAAqB,OAAe;AAC3C,SAAO,SAAS,MAAM,WAAW,GAAG,IAAI,MAAM,UAAU,GAAG,MAAM,MAAM,IAAI;AAC7E;AAQO,SAAS,eAAe,KAAa,MAAc;AACxD,SAAO,IAAI,IAAI,qBAAqB,GAAG,GAAG,oBAAoB,IAAI,CAAC;AACrE;AAQO,SAAS,eAAe,mBAA2B,aAAyC;AACjG,MAAI;AAEJ,MAAI;AACF,UAAM,eAAe,mBAAmB,WAAW;AAAA,EACrD,QAAQ;AACN,WAAO;AAAA,EACT;AAEA,MAAI,IAAI,WAAW,IAAI,IAAI,WAAW,EAAE,QAAQ;AAC9C,WAAO,IAAI,SAAS;AAAA,EACtB;AAEA,SAAO;AACT;;;AClDO,IAAM,2BAAN,cAAuC,MAAM;AAAA,EAC3C,OAAe;AAAA,EAEtB,YAAY,SAAkB;AAC5B,UAAM,WAAW,iFAAiF;AAClG,SAAK,OAAO;AAAA,EACd;AACF;;;ACHO,IAAM,uBAAN,MAAkE;AAAA,EACvE,UACE,MACA,OACA,SACA,cACM;AACN,QAAI,CAAC,cAAc;AACjB,YAAM,IAAI,yBAAyB;AAAA,IACrC;AAEA,iBAAa,MAAM,UAAU,MAAM,OAAO,WAAW,CAAC,CAAC;AAAA,EACzD;AAAA,EAEA,UAAU,MAAc,cAAiD;AACvE,QAAI,CAAC,cAAc;AACjB,YAAM,IAAI,yBAAyB;AAAA,IACrC;AAEA,WAAO,aAAa,QAAQ,UAAU,IAAI;AAAA,EAC5C;AAAA,EAEA,WAAW,cAAqD;AAC9D,QAAI,CAAC,cAAc;AACjB,YAAM,IAAI,yBAAyB;AAAA,IACrC;AAEA,WAAO,aAAa,QAAQ;AAAA,EAC9B;AAAA,EAEA,aAAa,MAAc,cAAmC;AAC5D,QAAI,CAAC,cAAc;AACjB,YAAM,IAAI,yBAAyB;AAAA,IACrC;AAEA,iBAAa,MAAM,YAAY,IAAI;AAAA,EACrC;AACF;;;AHjCA,IAAAA,0BAAuC;AAiDvC,IAAO,oBAAQ,sBAAAC,SAAG,eAAe,aAAa,SAA0B,SAA8B;AACpG,QAAM,eAAe,QAAQ,QAAQ,YAAY;AACjD,QAAM,cAAc,eAAe,cAAc,QAAQ,UAAU;AAEnE,QAAM,cAAc,IAAI,oCAA2B;AAAA,IACjD,QAAQ,QAAQ;AAAA,IAChB,UAAU,QAAQ;AAAA,IAClB,cAAc,QAAQ;AAAA,IACtB,2BAA2B,QAAQ;AAAA,IACnC,2BAA2B,QAAQ;AAAA,IACnC,qBAAqB;AAAA,MACnB,UAAU,QAAQ;AAAA,MAClB,cAAc,YAAY,SAAS;AAAA,IACrC;AAAA,IACA,kBAAkB,IAAI,8CAAuB,EAAE,QAAQ,QAAQ,cAAc,GAAG,IAAI,qBAAqB,CAAC;AAAA,IAC1G,YAAY,QAAQ,eAChB,IAAI,0CAAmB;AAAA,MACrB,GAAG,QAAQ;AAAA,MACX,QAAQ,QAAQ;AAAA,MAChB,OAAO,QAAQ;AAAA,IACjB,GAAG,IAAI,qBAAqB,CAAC,IAC7B,IAAI,2CAAoB;AAAA,MACtB,GAAG,QAAQ;AAAA,MACX,QAAQ,QAAQ;AAAA,IAClB,GAAG,IAAI,qBAAqB,CAAC;AAAA,IACjC,iBAAiB,QAAQ,sBAAsB,QAAQ;AAAA,IACvD,aAAa,QAAQ;AAAA,EACvB,CAAC;AAED,MAAI,CAAC,QAAQ,kBAAkB,QAAQ,GAAG;AACxC,YAAQ,SAAS,OAAO,iBAAiB,CAAC;AAAA,EAC5C;AAEA,QAAM,oBAAoB,QAAQ,eAAe;AAEjD,MAAI,mBAAmB;AACrB,YAAQ;AAAA,MACN,QAAQ,QAAQ,SAAS;AAAA,MACzB,OACE,SAGA,UACG;AACH,cAAM,oBAAoB,QAAQ,MAAM;AACxC,cAAM,oBAAoB,eAAe,qBAAqB,KAAK,QAAQ,UAAU;AAErF,cAAM,mBAAmB,MAAM,YAAY;AAAA,UACzC;AAAA,YACE,6BAA6B,QAAQ;AAAA,YACrC,UAAU,EAAE,UAAU,kBAAkB;AAAA,UAC1C;AAAA,UACA,EAAE,SAAS,MAAM;AAAA,QACnB;AAEA,cAAM,SAAS,iBAAiB,IAAI;AAAA,MACtC;AAAA,IACF;AAEA,YAAQ,IAAI,QAAQ,QAAQ,YAAY,kBAAkB,OAAO,SAAS,UAAU;AAClF,YAAM,EAAE,SAAS,IAAI,MAAM,YAAY;AAAA,QACrC,eAAe,QAAQ,KAAK,QAAQ,UAAU;AAAA,QAC9C,EAAE,SAAS,MAAM;AAAA,MACnB;AAEA,YAAM,SAAS,UAAU,YAAY,QAAQ,UAAU;AAAA,IACzD,CAAC;AAED,YAAQ,IAAI,QAAQ,QAAQ,UAAU,gBAAgB,OAAO,SAAS,UAAU;AAC9E,YAAM,WAAW,QAAQ;AACzB,YAAM,YAAY,MAAM,YAAY,OAAO,EAAE,UAAU,SAAS,SAAS,EAAE,GAAG,EAAE,SAAS,MAAM,CAAC;AAEhG,YAAM,SAAS,UAAU,IAAI;AAAA,IAC/B,CAAC;AAED,YAAQ;AAAA,MACN,QAAQ,QAAQ,qBAAqB;AAAA,MACrC,OACE,SAGA,UACG;AACH,cAAM,cAAc,QAAQ,KAAK;AAEjC,YAAI,CAAC,aAAa;AAChB,gBAAM,KAAK,GAAG,EAAE,KAAK,6CAA6C;AAElE;AAAA,QACF;AAEA,YAAI;AACF,gBAAM,YAAY,wBAAwB,aAAa,EAAE,SAAS,MAAM,CAAC;AACzE,gBAAM,KAAK,GAAG,EAAE,KAAK,IAAI;AAAA,QAC3B,SAAS,GAAG;AACV,gBAAM,KAAK,GAAG,EAAE,KAAM,EAAY,OAAO;AAAA,QAC3C;AAAA,MACF;AAAA,IACF;AAEA,UAAM,2BAA2B,QAAQ,sBAAsB;AAE/D,QAAI,0BAA0B;AAC5B,cAAQ;AAAA,QACN,QAAQ,QAAQ,WAAW;AAAA,QAC3B,OACE,SAGA,UACG;AACH,gBAAM,EAAE,YAAY,iBAAiB,SAAS,IAAI,QAAQ;AAC1D,gBAAM,oBAAoB;AAE1B,cAAI,CAAC,YAAY;AACf,mBAAO,MAAM,KAAK,GAAG,EAAE,KAAK;AAAA,cAC1B,OAAO;AAAA,cACP,mBAAmB;AAAA,YACrB,CAAC;AAAA,UACH;AAEA,gBAAM,oBAAoB,eAAe,qBAAqB,KAAK,QAAQ,UAAU;AACrF,gBAAMC,gBAAe,QAAQ,QAAQ,mBAAmB;AACxD,gBAAMC,eAAc,eAAeD,eAAc,QAAQ,UAAU;AACnE,gBAAM,cAAc,MAAM,QAAQ,YAAa;AAAA,YAC7C;AAAA,cACE;AAAA,cACA;AAAA,cACA,qBAAqB;AAAA,gBACnB,cAAcC,aAAY,SAAS;AAAA,cACrC;AAAA,cACA,UAAU;AAAA,gBACR,UAAU;AAAA,cACZ;AAAA,YACF;AAAA,YACA,EAAE,SAAS,MAAM;AAAA,UACnB;AAEA,gBAAM,SAAS,YAAY,IAAI;AAAA,QACjC;AAAA,MACF;AAEA,cAAQ,IAAI,QAAQ,QAAQ,mBAAmB,0BAA0B,OAAO,SAAS,UAAU;AACjG,cAAM,EAAE,SAAS,IAAI,MAAM,QAAQ,YAAa;AAAA,UAC9C,eAAe,QAAQ,KAAK,QAAQ,UAAU;AAAA,UAC9C;AAAA,YACE;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAEA,cAAM,SAAS,UAAU,YAAY,QAAQ,UAAU;AAAA,MACzD,CAAC;AAED,cAAQ;AAAA,QACN,QAAQ,QAAQ,aAAa;AAAA,QAC7B,OACE,SAGA,UACG;AACH,gBAAM,EAAE,YAAY,SAAS,IAAI,QAAQ;AACzC,gBAAM,oBAAoB;AAE1B,cAAI,CAAC,YAAY;AACf,mBAAO,MAAM,KAAK,GAAG,EAAE,KAAK;AAAA,cAC1B,OAAO;AAAA,cACP,mBAAmB;AAAA,YACrB,CAAC;AAAA,UACH;AAEA,gBAAM,oBAAoB,eAAe,qBAAqB,KAAK,QAAQ,UAAU;AACrF,gBAAMD,gBAAe,QAAQ,QAAQ,qBAAqB;AAC1D,gBAAMC,eAAc,eAAeD,eAAc,QAAQ,UAAU;AACnE,gBAAM,cAAc,MAAM,QAAQ,YAAa;AAAA,YAC7C;AAAA,cACE;AAAA,cACA,qBAAqB;AAAA,gBACnB,cAAcC,aAAY,SAAS;AAAA,cACrC;AAAA,cACA,UAAU;AAAA,gBACR,UAAU;AAAA,cACZ;AAAA,YACF;AAAA,YACA,EAAE,SAAS,MAAM;AAAA,UACnB;AAEA,gBAAM,SAAS,YAAY,IAAI;AAAA,QACjC;AAAA,MACF;AAEA,cAAQ,IAAI,QAAQ,QAAQ,qBAAqB,4BAA4B,OAAO,SAAS,UAAU;AACrG,cAAM,EAAE,SAAS,IAAI,MAAM,QAAQ,YAAa;AAAA,UAC9C,eAAe,QAAQ,KAAK,QAAQ,UAAU;AAAA,UAC9C;AAAA,YACE;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAEA,cAAM,SAAS,UAAU,YAAY,QAAQ,UAAU;AAAA,MACzD,CAAC;AAAA,IACH;AAAA,EACF;AAEA,UAAQ,SAAS,eAAe,WAAW;AAC7C,CAAC;","names":["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 {\n FastifyInstance,\n FastifyRequest,\n RouteGenericInterface,\n RawServerBase,\n RawRequestDefaultExpression,\n RawReplyDefaultExpression,\n RawServerDefault,\n} from 'fastify';\nimport fp from 'fastify-plugin';\nimport { CookieTransactionStore, ServerClient, StatelessStateStore, StatefulStateStore } from '@auth0/auth0-server-js';\nimport type { DomainResolver } from '@auth0/auth0-server-js';\nimport type { DiscoveryCacheOptions, 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 type { DomainResolver } from '@auth0/auth0-server-js';\nexport { CookieTransactionStore } from '@auth0/auth0-server-js';\n\ndeclare module 'fastify' {\n /**\n * FastifyInstance is a generic interface, whose generics represent the underlying server, request and reply types.\n * By extending the interface with the same generics, we ensure that the `auth0Client` property is aware\n * of the underlying server type (e.g., HTTP/1.1, HTTP/2, etc.).\n *\n * @remark The generics default to the values used by a standard Fastify instance.\n */\n interface FastifyInstance<\n RawServer extends RawServerBase = RawServerDefault,\n RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>,\n RawReply extends RawReplyDefaultExpression<RawServer> = RawReplyDefaultExpression<RawServer>\n > {\n /**\n * The Auth0 Server Client instance attached to the Fastify instance.\n * This client is used to interact with Auth0 for authentication and session management.\n *\n * We pass-through the FastifyInstance generics to ensure compatibility with different server types.\n */\n auth0Client: ServerClient<StoreOptions<RawServer, RawRequest, RawReply>> | undefined;\n }\n}\n\nconst assertAppBaseUrl = (value: string): string => {\n try {\n new URL(value);\n } catch {\n throw new Error('appBaseUrl must be an absolute URL.');\n }\n return value;\n};\n\nconst getHeaderValue = (value: string | string[] | undefined): string | undefined =>\n Array.isArray(value) ? value[0] : value;\n\nconst inferAppBaseUrlFromRequest = <\n RawServer extends RawServerBase = RawServerDefault,\n RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>\n>(\n request: FastifyRequest<RouteGenericInterface, RawServer, RawRequest>\n): string => {\n const hostHeader = getHeaderValue(request.headers['x-forwarded-host']) ?? getHeaderValue(request.headers.host);\n if (!hostHeader) {\n throw new Error('Unable to infer appBaseUrl: missing host header.');\n }\n\n const forwardedProto = getHeaderValue(request.headers['x-forwarded-proto']);\n const protocol = (forwardedProto ?? request.protocol).toString().split(',')[0]?.trim();\n if (!protocol) {\n throw new Error('Unable to infer appBaseUrl: missing protocol.');\n }\n\n return assertAppBaseUrl(`${protocol}://${hostHeader}`);\n};\n\ntype Auth0FastifyCommonOptions<\n RawServer extends RawServerBase = RawServerDefault,\n RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>,\n RawReply extends RawReplyDefaultExpression<RawServer> = RawReplyDefaultExpression<RawServer>\n> = {\n clientId: string;\n clientSecret?: string;\n clientAssertionSigningKey?: string | CryptoKey;\n clientAssertionSigningAlg?: string;\n audience?: string;\n\n pushedAuthorizationRequests?: boolean;\n\n sessionSecret: string;\n sessionStore?: SessionStore<RawServer, RawRequest, RawReply>;\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 * Optional discovery cache configuration for OIDC metadata and JWKS fetchers.\n * TTL is in seconds. Defaults to the ServerClient defaults when omitted.\n */\n discoveryCache?: DiscoveryCacheOptions;\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 type Auth0FastifyOptions<\n RawServer extends RawServerBase = RawServerDefault,\n RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>,\n RawReply extends RawReplyDefaultExpression<RawServer> = RawReplyDefaultExpression<RawServer>\n> =\n | (Auth0FastifyCommonOptions<RawServer, RawRequest, RawReply> & {\n domain: string;\n /**\n * The base URL of the application used for redirects and callbacks.\n * Required when using a static domain.\n */\n appBaseUrl: string;\n })\n | (Auth0FastifyCommonOptions<RawServer, RawRequest, RawReply> & {\n domain: DomainResolver<StoreOptions<RawServer, RawRequest, RawReply>>;\n /**\n * Optional base URL used for redirects and callbacks.\n * When omitted, the base URL is inferred from the request host/proto.\n */\n appBaseUrl?: string;\n });\n\nexport default fp(async function auth0Fastify<\n RawServer extends RawServerBase = RawServerDefault,\n RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>,\n RawReply extends RawReplyDefaultExpression<RawServer> = RawReplyDefaultExpression<RawServer>\n>(\n fastify: FastifyInstance<RawServer, RawRequest, RawReply>,\n options: Auth0FastifyOptions<RawServer, RawRequest, RawReply>\n) {\n const callbackPath = options.routes?.callback ?? '/auth/callback';\n const staticAppBaseUrl = options.appBaseUrl ? assertAppBaseUrl(options.appBaseUrl) : undefined;\n if (typeof options.domain === 'string' && !staticAppBaseUrl) {\n throw new Error('appBaseUrl is required when domain is a string.');\n }\n const staticRedirectUri = staticAppBaseUrl ? createRouteUrl(callbackPath, staticAppBaseUrl) : undefined;\n\n const resolveAppBaseUrl = (request: FastifyRequest<RouteGenericInterface, RawServer, RawRequest>): string => {\n if (staticAppBaseUrl) {\n return staticAppBaseUrl;\n }\n return inferAppBaseUrlFromRequest(request);\n };\n\n const auth0Client = new ServerClient<StoreOptions<RawServer, RawRequest, RawReply>>({\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 ...(staticRedirectUri ? { redirect_uri: staticRedirectUri.toString() } : {}),\n },\n discoveryCache: options.discoveryCache,\n transactionStore: new CookieTransactionStore(\n { secret: options.sessionSecret },\n new FastifyCookieHandler<RawServer, RawRequest, RawReply>()\n ),\n stateStore: options.sessionStore\n ? new StatefulStateStore(\n {\n ...options.sessionConfiguration,\n secret: options.sessionSecret,\n store: options.sessionStore,\n },\n new FastifyCookieHandler<RawServer, RawRequest, RawReply>()\n )\n : new StatelessStateStore(\n {\n ...options.sessionConfiguration,\n secret: options.sessionSecret,\n },\n new FastifyCookieHandler<RawServer, RawRequest, RawReply>()\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 options.routes?.login ?? '/auth/login',\n async (\n request: FastifyRequest<\n {\n Querystring: { returnTo?: string };\n },\n RawServer,\n RawRequest\n >,\n reply\n ) => {\n const appBaseUrl = resolveAppBaseUrl(request);\n const dangerousReturnTo = request.query.returnTo;\n const sanitizedReturnTo = toSafeRedirect(dangerousReturnTo || '/', appBaseUrl);\n const redirectUri = createRouteUrl(callbackPath, appBaseUrl);\n\n const authorizationUrl = await auth0Client.startInteractiveLogin(\n {\n pushedAuthorizationRequests: options.pushedAuthorizationRequests,\n appState: { returnTo: sanitizedReturnTo },\n authorizationParams: {\n redirect_uri: redirectUri.toString(),\n },\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 appBaseUrl = resolveAppBaseUrl(request);\n const { appState } = await auth0Client.completeInteractiveLogin<{ returnTo: string } | undefined>(\n createRouteUrl(request.url, appBaseUrl),\n { request, reply }\n );\n\n reply.redirect(appState?.returnTo ?? appBaseUrl);\n });\n\n fastify.get(options.routes?.logout ?? '/auth/logout', async (request, reply) => {\n const appBaseUrl = resolveAppBaseUrl(request);\n const logoutUrl = await auth0Client.logout({ returnTo: appBaseUrl.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 {\n Body: { logout_token?: string };\n },\n RawServer,\n RawRequest\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 {\n Querystring: { connection: string; connectionScope: string; returnTo?: string };\n },\n RawServer,\n RawRequest\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 appBaseUrl = resolveAppBaseUrl(request);\n const sanitizedReturnTo = toSafeRedirect(dangerousReturnTo || '/', appBaseUrl);\n const callbackPath = options.routes?.connectCallback ?? '/auth/connect/callback';\n const redirectUri = createRouteUrl(callbackPath, 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 appBaseUrl = resolveAppBaseUrl(request);\n const { appState } = await fastify.auth0Client!.completeLinkUser<{ returnTo: string }>(\n createRouteUrl(request.url, appBaseUrl),\n {\n request,\n reply,\n }\n );\n\n reply.redirect(appState?.returnTo ?? appBaseUrl);\n });\n\n fastify.get(\n options.routes?.unconnect ?? '/auth/unconnect',\n async (\n request: FastifyRequest<\n {\n Querystring: { connection: string; returnTo?: string };\n },\n RawServer,\n RawRequest\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 appBaseUrl = resolveAppBaseUrl(request);\n const sanitizedReturnTo = toSafeRedirect(dangerousReturnTo || '/', appBaseUrl);\n const callbackPath = options.routes?.unconnectCallback ?? '/auth/unconnect/callback';\n const redirectUri = createRouteUrl(callbackPath, 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 appBaseUrl = resolveAppBaseUrl(request);\n const { appState } = await fastify.auth0Client!.completeUnlinkUser<{ returnTo: string }>(\n createRouteUrl(request.url, appBaseUrl),\n {\n request,\n reply,\n }\n );\n\n reply.redirect(appState?.returnTo ?? 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}\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 type { RawServerBase, RawRequestDefaultExpression, RawReplyDefaultExpression, RawServerDefault } from 'fastify';\nimport { StoreOptions } from '../types.js';\nimport { MissingStoreOptionsError } from '../errors/index.js';\n\nexport class FastifyCookieHandler<\n RawServer extends RawServerBase = RawServerDefault,\n RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>,\n RawReply extends RawReplyDefaultExpression<RawServer> = RawReplyDefaultExpression<RawServer>\n> implements CookieHandler<StoreOptions<RawServer, RawRequest, RawReply>>\n{\n setCookie(\n name: string,\n value: string,\n options?: CookieSerializeOptions,\n storeOptions?: StoreOptions<RawServer, RawRequest, RawReply>\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<RawServer, RawRequest, RawReply>): string | undefined {\n if (!storeOptions) {\n throw new MissingStoreOptionsError();\n }\n\n return storeOptions.request.cookies?.[name];\n }\n\n getCookies(storeOptions?: StoreOptions<RawServer, RawRequest, RawReply>): 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<RawServer, RawRequest, RawReply>): 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"]} |
+57
-17
@@ -1,14 +0,23 @@ | ||
| import { FastifyRequest, FastifyReply, FastifyInstance } from 'fastify'; | ||
| import { StateData, LogoutTokenClaims, ServerClient } from '@auth0/auth0-server-js'; | ||
| export { CookieTransactionStore } from '@auth0/auth0-server-js'; | ||
| import { RawServerBase, RawServerDefault, RawRequestDefaultExpression, RawReplyDefaultExpression, FastifyRequest, RouteGenericInterface, FastifyReply, FastifyInstance } from 'fastify'; | ||
| import { StateData, LogoutTokenClaims, ServerClient, DiscoveryCacheOptions, DomainResolver } from '@auth0/auth0-server-js'; | ||
| export { CookieTransactionStore, DiscoveryCacheOptions, DomainResolver } from '@auth0/auth0-server-js'; | ||
| interface StoreOptions { | ||
| request: FastifyRequest; | ||
| reply: FastifyReply; | ||
| /** | ||
| * Options for accessing the Fastify request and reply objects. | ||
| * These are used in store implementations to interact with cookies and sessions. | ||
| * | ||
| * FastifyInstance is a generic interface itself, whose generics represent the underlying server, request and reply types. | ||
| * By including these in the StoreOptions generics, we ensure that `StoreOptions` is aware of the underlying server type (e.g., HTTP/1.1, HTTP/2, etc.). | ||
| * | ||
| * @remark The generics default to the values used by a standard Fastify instance. | ||
| */ | ||
| interface StoreOptions<RawServer extends RawServerBase = RawServerDefault, RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>, RawReply extends RawReplyDefaultExpression<RawServer> = RawReplyDefaultExpression<RawServer>> { | ||
| request: FastifyRequest<RouteGenericInterface, RawServer, RawRequest>; | ||
| reply: FastifyReply<RouteGenericInterface, RawServer, RawRequest, RawReply>; | ||
| } | ||
| interface SessionStore { | ||
| interface SessionStore<RawServer extends RawServerBase = RawServerDefault, RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>, RawReply extends RawReplyDefaultExpression<RawServer> = RawReplyDefaultExpression<RawServer>> { | ||
| delete(identifier: string): Promise<void>; | ||
| set(identifier: string, stateData: StateData): Promise<void>; | ||
| get(identifier: string): Promise<StateData | undefined>; | ||
| deleteByLogoutToken(claims: LogoutTokenClaims, options?: StoreOptions | undefined): Promise<void>; | ||
| deleteByLogoutToken(claims: LogoutTokenClaims, options?: StoreOptions<RawServer, RawRequest, RawReply> | undefined): Promise<void>; | ||
| } | ||
@@ -27,3 +36,3 @@ interface SessionCookieOptions { | ||
| */ | ||
| sameSite?: "strict" | "lax" | "none"; | ||
| sameSite?: 'strict' | 'lax' | 'none'; | ||
| /** | ||
@@ -69,8 +78,20 @@ * The secure attribute of the session cookie. | ||
| declare module 'fastify' { | ||
| interface FastifyInstance { | ||
| auth0Client: ServerClient<StoreOptions> | undefined; | ||
| /** | ||
| * FastifyInstance is a generic interface, whose generics represent the underlying server, request and reply types. | ||
| * By extending the interface with the same generics, we ensure that the `auth0Client` property is aware | ||
| * of the underlying server type (e.g., HTTP/1.1, HTTP/2, etc.). | ||
| * | ||
| * @remark The generics default to the values used by a standard Fastify instance. | ||
| */ | ||
| interface FastifyInstance<RawServer extends RawServerBase = RawServerDefault, RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>, RawReply extends RawReplyDefaultExpression<RawServer> = RawReplyDefaultExpression<RawServer>> { | ||
| /** | ||
| * The Auth0 Server Client instance attached to the Fastify instance. | ||
| * This client is used to interact with Auth0 for authentication and session management. | ||
| * | ||
| * We pass-through the FastifyInstance generics to ensure compatibility with different server types. | ||
| */ | ||
| auth0Client: ServerClient<StoreOptions<RawServer, RawRequest, RawReply>> | undefined; | ||
| } | ||
| } | ||
| interface Auth0FastifyOptions { | ||
| domain: string; | ||
| type Auth0FastifyCommonOptions<RawServer extends RawServerBase = RawServerDefault, RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>, RawReply extends RawReplyDefaultExpression<RawServer> = RawReplyDefaultExpression<RawServer>> = { | ||
| clientId: string; | ||
@@ -81,6 +102,5 @@ clientSecret?: string; | ||
| audience?: string; | ||
| appBaseUrl: string; | ||
| pushedAuthorizationRequests?: boolean; | ||
| sessionSecret: string; | ||
| sessionStore?: SessionStore; | ||
| sessionStore?: SessionStore<RawServer, RawRequest, RawReply>; | ||
| sessionConfiguration?: SessionConfiguration; | ||
@@ -101,2 +121,7 @@ /** | ||
| customFetch?: typeof fetch; | ||
| /** | ||
| * Optional discovery cache configuration for OIDC metadata and JWKS fetchers. | ||
| * TTL is in seconds. Defaults to the ServerClient defaults when omitted. | ||
| */ | ||
| discoveryCache?: DiscoveryCacheOptions; | ||
| routes?: { | ||
@@ -112,5 +137,20 @@ login?: string; | ||
| }; | ||
| } | ||
| declare const _default: (fastify: FastifyInstance, options: Auth0FastifyOptions) => Promise<void>; | ||
| }; | ||
| type Auth0FastifyOptions<RawServer extends RawServerBase = RawServerDefault, RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>, RawReply extends RawReplyDefaultExpression<RawServer> = RawReplyDefaultExpression<RawServer>> = (Auth0FastifyCommonOptions<RawServer, RawRequest, RawReply> & { | ||
| domain: string; | ||
| /** | ||
| * The base URL of the application used for redirects and callbacks. | ||
| * Required when using a static domain. | ||
| */ | ||
| appBaseUrl: string; | ||
| }) | (Auth0FastifyCommonOptions<RawServer, RawRequest, RawReply> & { | ||
| domain: DomainResolver<StoreOptions<RawServer, RawRequest, RawReply>>; | ||
| /** | ||
| * Optional base URL used for redirects and callbacks. | ||
| * When omitted, the base URL is inferred from the request host/proto. | ||
| */ | ||
| appBaseUrl?: string; | ||
| }); | ||
| declare const _default: <RawServer extends RawServerBase = RawServerDefault, RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>, RawReply extends RawReplyDefaultExpression<RawServer> = RawReplyDefaultExpression<RawServer>>(fastify: FastifyInstance<RawServer, RawRequest, RawReply>, options: Auth0FastifyOptions<RawServer, RawRequest, RawReply>) => Promise<void>; | ||
| export { type Auth0FastifyOptions, type SessionConfiguration, type SessionCookieOptions, type SessionStore, type StoreOptions, _default as default }; |
+57
-17
@@ -1,14 +0,23 @@ | ||
| import { FastifyRequest, FastifyReply, FastifyInstance } from 'fastify'; | ||
| import { StateData, LogoutTokenClaims, ServerClient } from '@auth0/auth0-server-js'; | ||
| export { CookieTransactionStore } from '@auth0/auth0-server-js'; | ||
| import { RawServerBase, RawServerDefault, RawRequestDefaultExpression, RawReplyDefaultExpression, FastifyRequest, RouteGenericInterface, FastifyReply, FastifyInstance } from 'fastify'; | ||
| import { StateData, LogoutTokenClaims, ServerClient, DiscoveryCacheOptions, DomainResolver } from '@auth0/auth0-server-js'; | ||
| export { CookieTransactionStore, DiscoveryCacheOptions, DomainResolver } from '@auth0/auth0-server-js'; | ||
| interface StoreOptions { | ||
| request: FastifyRequest; | ||
| reply: FastifyReply; | ||
| /** | ||
| * Options for accessing the Fastify request and reply objects. | ||
| * These are used in store implementations to interact with cookies and sessions. | ||
| * | ||
| * FastifyInstance is a generic interface itself, whose generics represent the underlying server, request and reply types. | ||
| * By including these in the StoreOptions generics, we ensure that `StoreOptions` is aware of the underlying server type (e.g., HTTP/1.1, HTTP/2, etc.). | ||
| * | ||
| * @remark The generics default to the values used by a standard Fastify instance. | ||
| */ | ||
| interface StoreOptions<RawServer extends RawServerBase = RawServerDefault, RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>, RawReply extends RawReplyDefaultExpression<RawServer> = RawReplyDefaultExpression<RawServer>> { | ||
| request: FastifyRequest<RouteGenericInterface, RawServer, RawRequest>; | ||
| reply: FastifyReply<RouteGenericInterface, RawServer, RawRequest, RawReply>; | ||
| } | ||
| interface SessionStore { | ||
| interface SessionStore<RawServer extends RawServerBase = RawServerDefault, RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>, RawReply extends RawReplyDefaultExpression<RawServer> = RawReplyDefaultExpression<RawServer>> { | ||
| delete(identifier: string): Promise<void>; | ||
| set(identifier: string, stateData: StateData): Promise<void>; | ||
| get(identifier: string): Promise<StateData | undefined>; | ||
| deleteByLogoutToken(claims: LogoutTokenClaims, options?: StoreOptions | undefined): Promise<void>; | ||
| deleteByLogoutToken(claims: LogoutTokenClaims, options?: StoreOptions<RawServer, RawRequest, RawReply> | undefined): Promise<void>; | ||
| } | ||
@@ -27,3 +36,3 @@ interface SessionCookieOptions { | ||
| */ | ||
| sameSite?: "strict" | "lax" | "none"; | ||
| sameSite?: 'strict' | 'lax' | 'none'; | ||
| /** | ||
@@ -69,8 +78,20 @@ * The secure attribute of the session cookie. | ||
| declare module 'fastify' { | ||
| interface FastifyInstance { | ||
| auth0Client: ServerClient<StoreOptions> | undefined; | ||
| /** | ||
| * FastifyInstance is a generic interface, whose generics represent the underlying server, request and reply types. | ||
| * By extending the interface with the same generics, we ensure that the `auth0Client` property is aware | ||
| * of the underlying server type (e.g., HTTP/1.1, HTTP/2, etc.). | ||
| * | ||
| * @remark The generics default to the values used by a standard Fastify instance. | ||
| */ | ||
| interface FastifyInstance<RawServer extends RawServerBase = RawServerDefault, RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>, RawReply extends RawReplyDefaultExpression<RawServer> = RawReplyDefaultExpression<RawServer>> { | ||
| /** | ||
| * The Auth0 Server Client instance attached to the Fastify instance. | ||
| * This client is used to interact with Auth0 for authentication and session management. | ||
| * | ||
| * We pass-through the FastifyInstance generics to ensure compatibility with different server types. | ||
| */ | ||
| auth0Client: ServerClient<StoreOptions<RawServer, RawRequest, RawReply>> | undefined; | ||
| } | ||
| } | ||
| interface Auth0FastifyOptions { | ||
| domain: string; | ||
| type Auth0FastifyCommonOptions<RawServer extends RawServerBase = RawServerDefault, RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>, RawReply extends RawReplyDefaultExpression<RawServer> = RawReplyDefaultExpression<RawServer>> = { | ||
| clientId: string; | ||
@@ -81,6 +102,5 @@ clientSecret?: string; | ||
| audience?: string; | ||
| appBaseUrl: string; | ||
| pushedAuthorizationRequests?: boolean; | ||
| sessionSecret: string; | ||
| sessionStore?: SessionStore; | ||
| sessionStore?: SessionStore<RawServer, RawRequest, RawReply>; | ||
| sessionConfiguration?: SessionConfiguration; | ||
@@ -101,2 +121,7 @@ /** | ||
| customFetch?: typeof fetch; | ||
| /** | ||
| * Optional discovery cache configuration for OIDC metadata and JWKS fetchers. | ||
| * TTL is in seconds. Defaults to the ServerClient defaults when omitted. | ||
| */ | ||
| discoveryCache?: DiscoveryCacheOptions; | ||
| routes?: { | ||
@@ -112,5 +137,20 @@ login?: string; | ||
| }; | ||
| } | ||
| declare const _default: (fastify: FastifyInstance, options: Auth0FastifyOptions) => Promise<void>; | ||
| }; | ||
| type Auth0FastifyOptions<RawServer extends RawServerBase = RawServerDefault, RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>, RawReply extends RawReplyDefaultExpression<RawServer> = RawReplyDefaultExpression<RawServer>> = (Auth0FastifyCommonOptions<RawServer, RawRequest, RawReply> & { | ||
| domain: string; | ||
| /** | ||
| * The base URL of the application used for redirects and callbacks. | ||
| * Required when using a static domain. | ||
| */ | ||
| appBaseUrl: string; | ||
| }) | (Auth0FastifyCommonOptions<RawServer, RawRequest, RawReply> & { | ||
| domain: DomainResolver<StoreOptions<RawServer, RawRequest, RawReply>>; | ||
| /** | ||
| * Optional base URL used for redirects and callbacks. | ||
| * When omitted, the base URL is inferred from the request host/proto. | ||
| */ | ||
| appBaseUrl?: string; | ||
| }); | ||
| declare const _default: <RawServer extends RawServerBase = RawServerDefault, RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>, RawReply extends RawReplyDefaultExpression<RawServer> = RawReplyDefaultExpression<RawServer>>(fastify: FastifyInstance<RawServer, RawRequest, RawReply>, options: Auth0FastifyOptions<RawServer, RawRequest, RawReply>) => Promise<void>; | ||
| export { type Auth0FastifyOptions, type SessionConfiguration, type SessionCookieOptions, type SessionStore, type StoreOptions, _default as default }; |
+78
-27
@@ -67,5 +67,36 @@ // src/index.ts | ||
| import { CookieTransactionStore as CookieTransactionStore2 } from "@auth0/auth0-server-js"; | ||
| var assertAppBaseUrl = (value) => { | ||
| try { | ||
| new URL(value); | ||
| } catch { | ||
| throw new Error("appBaseUrl must be an absolute URL."); | ||
| } | ||
| return value; | ||
| }; | ||
| var getHeaderValue = (value) => Array.isArray(value) ? value[0] : value; | ||
| var inferAppBaseUrlFromRequest = (request) => { | ||
| const hostHeader = getHeaderValue(request.headers["x-forwarded-host"]) ?? getHeaderValue(request.headers.host); | ||
| if (!hostHeader) { | ||
| throw new Error("Unable to infer appBaseUrl: missing host header."); | ||
| } | ||
| const forwardedProto = getHeaderValue(request.headers["x-forwarded-proto"]); | ||
| const protocol = (forwardedProto ?? request.protocol).toString().split(",")[0]?.trim(); | ||
| if (!protocol) { | ||
| throw new Error("Unable to infer appBaseUrl: missing protocol."); | ||
| } | ||
| return assertAppBaseUrl(`${protocol}://${hostHeader}`); | ||
| }; | ||
| var index_default = fp(async function auth0Fastify(fastify, options) { | ||
| const callbackPath = options.routes?.callback ?? "/auth/callback"; | ||
| const redirectUri = createRouteUrl(callbackPath, options.appBaseUrl); | ||
| const staticAppBaseUrl = options.appBaseUrl ? assertAppBaseUrl(options.appBaseUrl) : void 0; | ||
| if (typeof options.domain === "string" && !staticAppBaseUrl) { | ||
| throw new Error("appBaseUrl is required when domain is a string."); | ||
| } | ||
| const staticRedirectUri = staticAppBaseUrl ? createRouteUrl(callbackPath, staticAppBaseUrl) : void 0; | ||
| const resolveAppBaseUrl = (request) => { | ||
| if (staticAppBaseUrl) { | ||
| return staticAppBaseUrl; | ||
| } | ||
| return inferAppBaseUrlFromRequest(request); | ||
| }; | ||
| const auth0Client = new ServerClient({ | ||
@@ -79,13 +110,23 @@ domain: options.domain, | ||
| audience: options.audience, | ||
| redirect_uri: redirectUri.toString() | ||
| ...staticRedirectUri ? { redirect_uri: staticRedirectUri.toString() } : {} | ||
| }, | ||
| transactionStore: new CookieTransactionStore({ secret: options.sessionSecret }, new FastifyCookieHandler()), | ||
| stateStore: options.sessionStore ? new StatefulStateStore({ | ||
| ...options.sessionConfiguration, | ||
| secret: options.sessionSecret, | ||
| store: options.sessionStore | ||
| }, new FastifyCookieHandler()) : new StatelessStateStore({ | ||
| ...options.sessionConfiguration, | ||
| secret: options.sessionSecret | ||
| }, new FastifyCookieHandler()), | ||
| discoveryCache: options.discoveryCache, | ||
| transactionStore: new CookieTransactionStore( | ||
| { secret: options.sessionSecret }, | ||
| new FastifyCookieHandler() | ||
| ), | ||
| stateStore: options.sessionStore ? new StatefulStateStore( | ||
| { | ||
| ...options.sessionConfiguration, | ||
| secret: options.sessionSecret, | ||
| store: options.sessionStore | ||
| }, | ||
| new FastifyCookieHandler() | ||
| ) : new StatelessStateStore( | ||
| { | ||
| ...options.sessionConfiguration, | ||
| secret: options.sessionSecret | ||
| }, | ||
| new FastifyCookieHandler() | ||
| ), | ||
| stateIdentifier: options.sessionConfiguration?.cookie?.name, | ||
@@ -102,8 +143,13 @@ customFetch: options.customFetch | ||
| async (request, reply) => { | ||
| const appBaseUrl = resolveAppBaseUrl(request); | ||
| const dangerousReturnTo = request.query.returnTo; | ||
| const sanitizedReturnTo = toSafeRedirect(dangerousReturnTo || "/", options.appBaseUrl); | ||
| const sanitizedReturnTo = toSafeRedirect(dangerousReturnTo || "/", appBaseUrl); | ||
| const redirectUri = createRouteUrl(callbackPath, appBaseUrl); | ||
| const authorizationUrl = await auth0Client.startInteractiveLogin( | ||
| { | ||
| pushedAuthorizationRequests: options.pushedAuthorizationRequests, | ||
| appState: { returnTo: sanitizedReturnTo } | ||
| appState: { returnTo: sanitizedReturnTo }, | ||
| authorizationParams: { | ||
| redirect_uri: redirectUri.toString() | ||
| } | ||
| }, | ||
@@ -116,11 +162,12 @@ { request, reply } | ||
| fastify.get(options.routes?.callback ?? "/auth/callback", async (request, reply) => { | ||
| const appBaseUrl = resolveAppBaseUrl(request); | ||
| const { appState } = await auth0Client.completeInteractiveLogin( | ||
| createRouteUrl(request.url, options.appBaseUrl), | ||
| createRouteUrl(request.url, appBaseUrl), | ||
| { request, reply } | ||
| ); | ||
| reply.redirect(appState?.returnTo ?? options.appBaseUrl); | ||
| reply.redirect(appState?.returnTo ?? appBaseUrl); | ||
| }); | ||
| fastify.get(options.routes?.logout ?? "/auth/logout", async (request, reply) => { | ||
| const returnTo = options.appBaseUrl; | ||
| const logoutUrl = await auth0Client.logout({ returnTo: returnTo.toString() }, { request, reply }); | ||
| const appBaseUrl = resolveAppBaseUrl(request); | ||
| const logoutUrl = await auth0Client.logout({ returnTo: appBaseUrl.toString() }, { request, reply }); | ||
| reply.redirect(logoutUrl.href); | ||
@@ -157,5 +204,6 @@ }); | ||
| } | ||
| const sanitizedReturnTo = toSafeRedirect(dangerousReturnTo || "/", options.appBaseUrl); | ||
| const appBaseUrl = resolveAppBaseUrl(request); | ||
| const sanitizedReturnTo = toSafeRedirect(dangerousReturnTo || "/", appBaseUrl); | ||
| const callbackPath2 = options.routes?.connectCallback ?? "/auth/connect/callback"; | ||
| const redirectUri2 = createRouteUrl(callbackPath2, options.appBaseUrl); | ||
| const redirectUri = createRouteUrl(callbackPath2, appBaseUrl); | ||
| const linkUserUrl = await fastify.auth0Client.startLinkUser( | ||
@@ -166,3 +214,3 @@ { | ||
| authorizationParams: { | ||
| redirect_uri: redirectUri2.toString() | ||
| redirect_uri: redirectUri.toString() | ||
| }, | ||
@@ -179,4 +227,5 @@ appState: { | ||
| fastify.get(options.routes?.connectCallback ?? "/auth/connect/callback", async (request, reply) => { | ||
| const appBaseUrl = resolveAppBaseUrl(request); | ||
| const { appState } = await fastify.auth0Client.completeLinkUser( | ||
| createRouteUrl(request.url, options.appBaseUrl), | ||
| createRouteUrl(request.url, appBaseUrl), | ||
| { | ||
@@ -187,3 +236,3 @@ request, | ||
| ); | ||
| reply.redirect(appState?.returnTo ?? options.appBaseUrl); | ||
| reply.redirect(appState?.returnTo ?? appBaseUrl); | ||
| }); | ||
@@ -201,5 +250,6 @@ fastify.get( | ||
| } | ||
| const sanitizedReturnTo = toSafeRedirect(dangerousReturnTo || "/", options.appBaseUrl); | ||
| const appBaseUrl = resolveAppBaseUrl(request); | ||
| const sanitizedReturnTo = toSafeRedirect(dangerousReturnTo || "/", appBaseUrl); | ||
| const callbackPath2 = options.routes?.unconnectCallback ?? "/auth/unconnect/callback"; | ||
| const redirectUri2 = createRouteUrl(callbackPath2, options.appBaseUrl); | ||
| const redirectUri = createRouteUrl(callbackPath2, appBaseUrl); | ||
| const linkUserUrl = await fastify.auth0Client.startUnlinkUser( | ||
@@ -209,3 +259,3 @@ { | ||
| authorizationParams: { | ||
| redirect_uri: redirectUri2.toString() | ||
| redirect_uri: redirectUri.toString() | ||
| }, | ||
@@ -222,4 +272,5 @@ appState: { | ||
| fastify.get(options.routes?.unconnectCallback ?? "/auth/unconnect/callback", async (request, reply) => { | ||
| const appBaseUrl = resolveAppBaseUrl(request); | ||
| const { appState } = await fastify.auth0Client.completeUnlinkUser( | ||
| createRouteUrl(request.url, options.appBaseUrl), | ||
| createRouteUrl(request.url, appBaseUrl), | ||
| { | ||
@@ -230,3 +281,3 @@ request, | ||
| ); | ||
| reply.redirect(appState?.returnTo ?? options.appBaseUrl); | ||
| reply.redirect(appState?.returnTo ?? appBaseUrl); | ||
| }); | ||
@@ -233,0 +284,0 @@ } |
@@ -1,1 +0,1 @@ | ||
| {"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"]} | ||
| {"version":3,"sources":["../src/index.ts","../src/utils.ts","../src/errors/index.ts","../src/store/fastify-cookie-handler.ts"],"sourcesContent":["import type {\n FastifyInstance,\n FastifyRequest,\n RouteGenericInterface,\n RawServerBase,\n RawRequestDefaultExpression,\n RawReplyDefaultExpression,\n RawServerDefault,\n} from 'fastify';\nimport fp from 'fastify-plugin';\nimport { CookieTransactionStore, ServerClient, StatelessStateStore, StatefulStateStore } from '@auth0/auth0-server-js';\nimport type { DomainResolver } from '@auth0/auth0-server-js';\nimport type { DiscoveryCacheOptions, 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 type { DomainResolver } from '@auth0/auth0-server-js';\nexport { CookieTransactionStore } from '@auth0/auth0-server-js';\n\ndeclare module 'fastify' {\n /**\n * FastifyInstance is a generic interface, whose generics represent the underlying server, request and reply types.\n * By extending the interface with the same generics, we ensure that the `auth0Client` property is aware\n * of the underlying server type (e.g., HTTP/1.1, HTTP/2, etc.).\n *\n * @remark The generics default to the values used by a standard Fastify instance.\n */\n interface FastifyInstance<\n RawServer extends RawServerBase = RawServerDefault,\n RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>,\n RawReply extends RawReplyDefaultExpression<RawServer> = RawReplyDefaultExpression<RawServer>\n > {\n /**\n * The Auth0 Server Client instance attached to the Fastify instance.\n * This client is used to interact with Auth0 for authentication and session management.\n *\n * We pass-through the FastifyInstance generics to ensure compatibility with different server types.\n */\n auth0Client: ServerClient<StoreOptions<RawServer, RawRequest, RawReply>> | undefined;\n }\n}\n\nconst assertAppBaseUrl = (value: string): string => {\n try {\n new URL(value);\n } catch {\n throw new Error('appBaseUrl must be an absolute URL.');\n }\n return value;\n};\n\nconst getHeaderValue = (value: string | string[] | undefined): string | undefined =>\n Array.isArray(value) ? value[0] : value;\n\nconst inferAppBaseUrlFromRequest = <\n RawServer extends RawServerBase = RawServerDefault,\n RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>\n>(\n request: FastifyRequest<RouteGenericInterface, RawServer, RawRequest>\n): string => {\n const hostHeader = getHeaderValue(request.headers['x-forwarded-host']) ?? getHeaderValue(request.headers.host);\n if (!hostHeader) {\n throw new Error('Unable to infer appBaseUrl: missing host header.');\n }\n\n const forwardedProto = getHeaderValue(request.headers['x-forwarded-proto']);\n const protocol = (forwardedProto ?? request.protocol).toString().split(',')[0]?.trim();\n if (!protocol) {\n throw new Error('Unable to infer appBaseUrl: missing protocol.');\n }\n\n return assertAppBaseUrl(`${protocol}://${hostHeader}`);\n};\n\ntype Auth0FastifyCommonOptions<\n RawServer extends RawServerBase = RawServerDefault,\n RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>,\n RawReply extends RawReplyDefaultExpression<RawServer> = RawReplyDefaultExpression<RawServer>\n> = {\n clientId: string;\n clientSecret?: string;\n clientAssertionSigningKey?: string | CryptoKey;\n clientAssertionSigningAlg?: string;\n audience?: string;\n\n pushedAuthorizationRequests?: boolean;\n\n sessionSecret: string;\n sessionStore?: SessionStore<RawServer, RawRequest, RawReply>;\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 * Optional discovery cache configuration for OIDC metadata and JWKS fetchers.\n * TTL is in seconds. Defaults to the ServerClient defaults when omitted.\n */\n discoveryCache?: DiscoveryCacheOptions;\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 type Auth0FastifyOptions<\n RawServer extends RawServerBase = RawServerDefault,\n RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>,\n RawReply extends RawReplyDefaultExpression<RawServer> = RawReplyDefaultExpression<RawServer>\n> =\n | (Auth0FastifyCommonOptions<RawServer, RawRequest, RawReply> & {\n domain: string;\n /**\n * The base URL of the application used for redirects and callbacks.\n * Required when using a static domain.\n */\n appBaseUrl: string;\n })\n | (Auth0FastifyCommonOptions<RawServer, RawRequest, RawReply> & {\n domain: DomainResolver<StoreOptions<RawServer, RawRequest, RawReply>>;\n /**\n * Optional base URL used for redirects and callbacks.\n * When omitted, the base URL is inferred from the request host/proto.\n */\n appBaseUrl?: string;\n });\n\nexport default fp(async function auth0Fastify<\n RawServer extends RawServerBase = RawServerDefault,\n RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>,\n RawReply extends RawReplyDefaultExpression<RawServer> = RawReplyDefaultExpression<RawServer>\n>(\n fastify: FastifyInstance<RawServer, RawRequest, RawReply>,\n options: Auth0FastifyOptions<RawServer, RawRequest, RawReply>\n) {\n const callbackPath = options.routes?.callback ?? '/auth/callback';\n const staticAppBaseUrl = options.appBaseUrl ? assertAppBaseUrl(options.appBaseUrl) : undefined;\n if (typeof options.domain === 'string' && !staticAppBaseUrl) {\n throw new Error('appBaseUrl is required when domain is a string.');\n }\n const staticRedirectUri = staticAppBaseUrl ? createRouteUrl(callbackPath, staticAppBaseUrl) : undefined;\n\n const resolveAppBaseUrl = (request: FastifyRequest<RouteGenericInterface, RawServer, RawRequest>): string => {\n if (staticAppBaseUrl) {\n return staticAppBaseUrl;\n }\n return inferAppBaseUrlFromRequest(request);\n };\n\n const auth0Client = new ServerClient<StoreOptions<RawServer, RawRequest, RawReply>>({\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 ...(staticRedirectUri ? { redirect_uri: staticRedirectUri.toString() } : {}),\n },\n discoveryCache: options.discoveryCache,\n transactionStore: new CookieTransactionStore(\n { secret: options.sessionSecret },\n new FastifyCookieHandler<RawServer, RawRequest, RawReply>()\n ),\n stateStore: options.sessionStore\n ? new StatefulStateStore(\n {\n ...options.sessionConfiguration,\n secret: options.sessionSecret,\n store: options.sessionStore,\n },\n new FastifyCookieHandler<RawServer, RawRequest, RawReply>()\n )\n : new StatelessStateStore(\n {\n ...options.sessionConfiguration,\n secret: options.sessionSecret,\n },\n new FastifyCookieHandler<RawServer, RawRequest, RawReply>()\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 options.routes?.login ?? '/auth/login',\n async (\n request: FastifyRequest<\n {\n Querystring: { returnTo?: string };\n },\n RawServer,\n RawRequest\n >,\n reply\n ) => {\n const appBaseUrl = resolveAppBaseUrl(request);\n const dangerousReturnTo = request.query.returnTo;\n const sanitizedReturnTo = toSafeRedirect(dangerousReturnTo || '/', appBaseUrl);\n const redirectUri = createRouteUrl(callbackPath, appBaseUrl);\n\n const authorizationUrl = await auth0Client.startInteractiveLogin(\n {\n pushedAuthorizationRequests: options.pushedAuthorizationRequests,\n appState: { returnTo: sanitizedReturnTo },\n authorizationParams: {\n redirect_uri: redirectUri.toString(),\n },\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 appBaseUrl = resolveAppBaseUrl(request);\n const { appState } = await auth0Client.completeInteractiveLogin<{ returnTo: string } | undefined>(\n createRouteUrl(request.url, appBaseUrl),\n { request, reply }\n );\n\n reply.redirect(appState?.returnTo ?? appBaseUrl);\n });\n\n fastify.get(options.routes?.logout ?? '/auth/logout', async (request, reply) => {\n const appBaseUrl = resolveAppBaseUrl(request);\n const logoutUrl = await auth0Client.logout({ returnTo: appBaseUrl.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 {\n Body: { logout_token?: string };\n },\n RawServer,\n RawRequest\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 {\n Querystring: { connection: string; connectionScope: string; returnTo?: string };\n },\n RawServer,\n RawRequest\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 appBaseUrl = resolveAppBaseUrl(request);\n const sanitizedReturnTo = toSafeRedirect(dangerousReturnTo || '/', appBaseUrl);\n const callbackPath = options.routes?.connectCallback ?? '/auth/connect/callback';\n const redirectUri = createRouteUrl(callbackPath, 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 appBaseUrl = resolveAppBaseUrl(request);\n const { appState } = await fastify.auth0Client!.completeLinkUser<{ returnTo: string }>(\n createRouteUrl(request.url, appBaseUrl),\n {\n request,\n reply,\n }\n );\n\n reply.redirect(appState?.returnTo ?? appBaseUrl);\n });\n\n fastify.get(\n options.routes?.unconnect ?? '/auth/unconnect',\n async (\n request: FastifyRequest<\n {\n Querystring: { connection: string; returnTo?: string };\n },\n RawServer,\n RawRequest\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 appBaseUrl = resolveAppBaseUrl(request);\n const sanitizedReturnTo = toSafeRedirect(dangerousReturnTo || '/', appBaseUrl);\n const callbackPath = options.routes?.unconnectCallback ?? '/auth/unconnect/callback';\n const redirectUri = createRouteUrl(callbackPath, 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 appBaseUrl = resolveAppBaseUrl(request);\n const { appState } = await fastify.auth0Client!.completeUnlinkUser<{ returnTo: string }>(\n createRouteUrl(request.url, appBaseUrl),\n {\n request,\n reply,\n }\n );\n\n reply.redirect(appState?.returnTo ?? 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}\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 type { RawServerBase, RawRequestDefaultExpression, RawReplyDefaultExpression, RawServerDefault } from 'fastify';\nimport { StoreOptions } from '../types.js';\nimport { MissingStoreOptionsError } from '../errors/index.js';\n\nexport class FastifyCookieHandler<\n RawServer extends RawServerBase = RawServerDefault,\n RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>,\n RawReply extends RawReplyDefaultExpression<RawServer> = RawReplyDefaultExpression<RawServer>\n> implements CookieHandler<StoreOptions<RawServer, RawRequest, RawReply>>\n{\n setCookie(\n name: string,\n value: string,\n options?: CookieSerializeOptions,\n storeOptions?: StoreOptions<RawServer, RawRequest, RawReply>\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<RawServer, RawRequest, RawReply>): string | undefined {\n if (!storeOptions) {\n throw new MissingStoreOptionsError();\n }\n\n return storeOptions.request.cookies?.[name];\n }\n\n getCookies(storeOptions?: StoreOptions<RawServer, RawRequest, RawReply>): 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<RawServer, RawRequest, RawReply>): 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"]} |
+3
-3
| { | ||
| "name": "@auth0/auth0-fastify", | ||
| "version": "1.2.0", | ||
| "version": "1.3.0", | ||
| "description": "Auth0 Authentication SDK for Fastify Applications on JavaScript runtimes", | ||
@@ -32,3 +32,3 @@ "author": "Auth0", | ||
| "tsup": "^8.4.0", | ||
| "typescript": "^5.7.3", | ||
| "typescript": "~5.8.2", | ||
| "typescript-eslint": "^8.24.0", | ||
@@ -38,3 +38,3 @@ "vitest": "^3.0.5" | ||
| "dependencies": { | ||
| "@auth0/auth0-server-js": "^1.1.0", | ||
| "@auth0/auth0-server-js": "^1.4.0", | ||
| "@fastify/cookie": "^11.0.2", | ||
@@ -41,0 +41,0 @@ "fastify": "^5.3.2", |
+3
-1
@@ -51,2 +51,4 @@ The Auth0 Fastify SDK is a library for implementing user authentication in Fastify applications. | ||
| > [!IMPORTANT] | ||
@@ -219,2 +221,2 @@ > You will need to register the following URLs in your Auth0 Application via the [Auth0 Dashboard](https://manage.auth0.com): | ||
| This project is licensed under the MIT license. See the <a href="https://github.com/auth0/auth0-fastify/blob/main/packages/auth0-fastify/LICENSE"> LICENSE</a> file for more info. | ||
| </p> | ||
| </p> |
97368
36.95%736
24.75%221
1.38%