@absolutejs/auth 0.59.2 → 0.60.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -29,8 +29,8 @@ Absolute Auth is a TypeScript-based authentication system that provides a compre
29
29
  1. Clone the repository:
30
30
 
31
31
  ```bash
32
- git clone https://github.com/alexkahndev/absolute-auth.git
33
- cd absolute-auth
32
+ git clone https://github.com/absolutejs/auth.git
33
+ cd auth
34
34
  ```
35
35
 
36
36
  2. Install the dependencies:
@@ -1,3 +1,4 @@
1
1
  export * from './createAuthClient';
2
2
  export * from './sessionExpiry';
3
+ export * from '../redirect';
3
4
  export { runConditionalAuthentication, runPasskeyRegistration } from './passkeyHelpers';
@@ -326,6 +326,9 @@ var isProtectedSessionRequest = ({
326
326
  const url = requestUrl(input, origin);
327
327
  return url?.origin === origin && protectedPaths.some((path) => url.pathname.startsWith(path));
328
328
  };
329
+ // src/redirect.ts
330
+ var isSafeLocalPath = (value) => /^\/(?![/\\])/.test(value);
331
+ var toSafeLocalPath = (value, fallback = "/") => value !== undefined && isSafeLocalPath(value) ? value : fallback;
329
332
  // src/client/passkeyHelpers.ts
330
333
  var loadBrowser = () => import("@simplewebauthn/browser");
331
334
  var errorFor2 = (caught) => ({
@@ -375,13 +378,15 @@ var runPasskeyRegistration = async (client) => {
375
378
  }
376
379
  };
377
380
  export {
381
+ toSafeLocalPath,
378
382
  runPasskeyRegistration,
379
383
  runConditionalAuthentication,
384
+ isSafeLocalPath,
380
385
  isProtectedSessionRequest,
381
386
  installSessionExpiryGuard,
382
387
  createAuthClient,
383
388
  buildSessionExpiredSignInUrl
384
389
  };
385
390
 
386
- //# debugId=B4E53841C044AF5F64756E2164756E21
391
+ //# debugId=E8018F05FE86589464756E2164756E21
387
392
  //# sourceMappingURL=index.js.map
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/client/createAuthClient.ts", "../src/client/sessionExpiry.ts", "../src/client/passkeyHelpers.ts"],
3
+ "sources": ["../src/client/createAuthClient.ts", "../src/client/sessionExpiry.ts", "../src/redirect.ts", "../src/client/passkeyHelpers.ts"],
4
4
  "sourcesContent": [
5
5
  "// Framework-agnostic client SDK over the auth endpoints. Thin fetch wrappers with\n// configurable routes, a uniform `{ data, error }` return, and same-origin cookies on by\n// default — the primitive the React hooks (`./react`) and future Vue/Solid composables wrap.\n// HTMX is the special case (declarative server fragments via `./htmx`); for every other UI\n// framework the natural primitive is this client + your framework's reactivity.\n\nimport type {\n\tPublicKeyCredentialCreationOptionsJSON,\n\tPublicKeyCredentialRequestOptionsJSON\n} from '@simplewebauthn/browser';\n\nexport type AuthClientError = {\n\tbody: unknown;\n\tmessage: string;\n\tstatus: number;\n};\n\nexport type AuthClientResult<T> =\n\t| { data: null; error: AuthClientError }\n\t| { data: T; error: null };\n\n// Each entry is the URL the consumer's auth() mounted that flow at. Defaults match the\n// package defaults; override to match your own custom routes.\nexport type AuthClientRoutes = {\n\temailVerify?: string;\n\temailVerifyRequest?: string;\n\tlogin?: string;\n\tmagicLinkRequest?: string;\n\tmagicLinkVerify?: string;\n\tmfaChallenge?: string;\n\tmfaManagement?: string;\n\tmfaSetup?: string;\n\tmfaVerifySetup?: string;\n\tpasskeyAuthenticateOptions?: string;\n\tpasskeyAuthenticateVerify?: string;\n\tpasskeyList?: string;\n\tpasskeyRegisterOptions?: string;\n\tpasskeyRegisterVerify?: string;\n\tpasskeyRemove?: string;\n\tpasswordReset?: string;\n\tpasswordResetRequest?: string;\n\tregister?: string;\n\tsessions?: string;\n\tsignout?: string;\n\tstatus?: string;\n};\n\nconst DEFAULT_ROUTES: Required<AuthClientRoutes> = {\n\temailVerify: '/auth/verify-email',\n\temailVerifyRequest: '/auth/verify-email/request',\n\tlogin: '/auth/login',\n\tmagicLinkRequest: '/auth/passwordless/magic-link',\n\tmagicLinkVerify: '/auth/passwordless/magic-link/verify',\n\tmfaChallenge: '/auth/mfa/totp/challenge',\n\tmfaManagement: '/auth/mfa',\n\tmfaSetup: '/auth/mfa/totp/setup',\n\tmfaVerifySetup: '/auth/mfa/totp/verify',\n\tpasskeyAuthenticateOptions: '/auth/webauthn/authenticate/options',\n\tpasskeyAuthenticateVerify: '/auth/webauthn/authenticate/verify',\n\tpasskeyList: '/auth/webauthn/credentials',\n\tpasskeyRegisterOptions: '/auth/webauthn/register/options',\n\tpasskeyRegisterVerify: '/auth/webauthn/register/verify',\n\tpasskeyRemove: '/auth/webauthn/credentials',\n\tpasswordReset: '/auth/reset-password',\n\tpasswordResetRequest: '/auth/reset-password/request',\n\tregister: '/auth/register',\n\tsessions: '/auth/sessions',\n\tsignout: '/oauth2/signout',\n\tstatus: '/oauth2/status'\n};\n\nexport type AuthClientConfig = {\n\tbaseUrl?: string;\n\tcredentials?: RequestCredentials;\n\tfetch?: typeof fetch;\n\troutes?: AuthClientRoutes;\n};\n\nconst succeed = <T>(data: T): AuthClientResult<T> => ({\n\tdata,\n\terror: null\n});\n\nconst fail = (error: AuthClientError): AuthClientResult<never> => ({\n\tdata: null,\n\terror\n});\n\nconst errorFor = (response: Response, body: unknown): AuthClientError => ({\n\tbody,\n\tmessage:\n\t\ttypeof body === 'string'\n\t\t\t? body\n\t\t\t: (readMessage(body) ?? response.statusText),\n\tstatus: response.status\n});\n\nexport const createAuthClient = ({\n\tbaseUrl = '',\n\tcredentials = 'same-origin',\n\tfetch: fetchImpl = fetch,\n\troutes\n}: AuthClientConfig = {}) => {\n\tconst resolvedRoutes: Required<AuthClientRoutes> = {\n\t\t...DEFAULT_ROUTES,\n\t\t...routes\n\t};\n\n\tconst request = async <T>(path: string, init: RequestInit) => {\n\t\ttry {\n\t\t\tconst response = await fetchImpl(`${baseUrl}${path}`, {\n\t\t\t\tcredentials,\n\t\t\t\t...init\n\t\t\t});\n\t\t\tconst text = await response.text();\n\t\t\tif (!response.ok) return fail(errorFor(response, safeJson(text)));\n\n\t\t\tconst data: T = JSON.parse(text === '' ? 'null' : text);\n\n\t\t\treturn succeed(data);\n\t\t} catch (caught) {\n\t\t\tconst message =\n\t\t\t\tcaught instanceof Error ? caught.message : 'network';\n\n\t\t\treturn fail({ body: null, message, status: 0 });\n\t\t}\n\t};\n\n\tconst post = <T>(path: string, body?: unknown, method = 'POST') =>\n\t\trequest<T>(path, {\n\t\t\tbody: body === undefined ? undefined : JSON.stringify(body),\n\t\t\theaders:\n\t\t\t\tbody === undefined\n\t\t\t\t\t? undefined\n\t\t\t\t\t: { 'content-type': 'application/json' },\n\t\t\tmethod\n\t\t});\n\n\tconst get = <T>(path: string) => request<T>(path, { method: 'GET' });\n\n\tconst del = <T>(path: string) => request<T>(path, { method: 'DELETE' });\n\n\treturn {\n\t\temailVerification: {\n\t\t\trequest: (body: { email: string }) =>\n\t\t\t\tpost<{ ok: true }>(resolvedRoutes.emailVerifyRequest, body),\n\t\t\tverify: (body: { token: string }) =>\n\t\t\t\tpost<{ ok: true }>(resolvedRoutes.emailVerify, body)\n\t\t},\n\t\tmfa: {\n\t\t\tchallenge: (body: { code: string }) =>\n\t\t\t\tpost<{ status: 'authenticated' }>(\n\t\t\t\t\tresolvedRoutes.mfaChallenge,\n\t\t\t\t\tbody\n\t\t\t\t),\n\t\t\tdisable: () =>\n\t\t\t\tdel<{ status: 'disabled' }>(resolvedRoutes.mfaManagement),\n\t\t\tsetup: () =>\n\t\t\t\tpost<{ secret: string; uri: string }>(resolvedRoutes.mfaSetup),\n\t\t\tstatus: () =>\n\t\t\t\tget<import('../mfa/management').MfaStatus>(\n\t\t\t\t\tresolvedRoutes.mfaManagement\n\t\t\t\t),\n\t\t\tverifySetup: (body: { code: string }) =>\n\t\t\t\tpost<{ backupCodes: string[] }>(\n\t\t\t\t\tresolvedRoutes.mfaVerifySetup,\n\t\t\t\t\tbody\n\t\t\t\t)\n\t\t},\n\t\tpasskeys: {\n\t\t\tauthenticateOptions: () =>\n\t\t\t\tpost<PublicKeyCredentialRequestOptionsJSON>(\n\t\t\t\t\tresolvedRoutes.passkeyAuthenticateOptions\n\t\t\t\t),\n\t\t\tauthenticateVerify: (response: unknown) =>\n\t\t\t\tpost<{ status: 'authenticated' }>(\n\t\t\t\t\tresolvedRoutes.passkeyAuthenticateVerify,\n\t\t\t\t\tresponse\n\t\t\t\t),\n\t\t\tlist: () => get<unknown[]>(resolvedRoutes.passkeyList),\n\t\t\tregisterOptions: () =>\n\t\t\t\tpost<PublicKeyCredentialCreationOptionsJSON>(\n\t\t\t\t\tresolvedRoutes.passkeyRegisterOptions\n\t\t\t\t),\n\t\t\tregisterVerify: (response: unknown) =>\n\t\t\t\tpost<{ ok: true }>(\n\t\t\t\t\tresolvedRoutes.passkeyRegisterVerify,\n\t\t\t\t\tresponse\n\t\t\t\t),\n\t\t\tremove: (credentialId: string) =>\n\t\t\t\tdel<{ ok: true }>(\n\t\t\t\t\t`${resolvedRoutes.passkeyRemove}/${encodeURIComponent(credentialId)}`\n\t\t\t\t)\n\t\t},\n\t\tpasswordless: {\n\t\t\trequestMagicLink: (body: { email: string }) =>\n\t\t\t\tpost<{ ok: true }>(resolvedRoutes.magicLinkRequest, body),\n\t\t\tverifyMagicLink: (body: { token: string }) =>\n\t\t\t\tpost<{ status: 'authenticated' }>(\n\t\t\t\t\tresolvedRoutes.magicLinkVerify,\n\t\t\t\t\tbody\n\t\t\t\t)\n\t\t},\n\t\tpasswordReset: {\n\t\t\tconfirm: (body: { password: string; token: string }) =>\n\t\t\t\tpost<{ ok: true }>(resolvedRoutes.passwordReset, body),\n\t\t\trequest: (body: { email: string }) =>\n\t\t\t\tpost<{ ok: true }>(resolvedRoutes.passwordResetRequest, body)\n\t\t},\n\t\tsessions: {\n\t\t\tlist: () => get<unknown[]>(resolvedRoutes.sessions),\n\t\t\trevoke: (sessionId: string) =>\n\t\t\t\tdel<{ ok: true }>(\n\t\t\t\t\t`${resolvedRoutes.sessions}/${encodeURIComponent(sessionId)}`\n\t\t\t\t)\n\t\t},\n\t\tsignIn: {\n\t\t\temail: (body: { email: string; password: string }) =>\n\t\t\t\tpost<{\n\t\t\t\t\tpasswordCompromised?: boolean;\n\t\t\t\t\tstatus: 'authenticated' | 'mfa_required';\n\t\t\t\t}>(resolvedRoutes.login, body)\n\t\t},\n\t\tsignUp: {\n\t\t\temail: (body: {\n\t\t\t\temail: string;\n\t\t\t\tpassword: string;\n\t\t\t\t[extra: string]: unknown;\n\t\t\t}) =>\n\t\t\t\tpost<\n\t\t\t\t\t| { status: 'authenticated' }\n\t\t\t\t\t| { status: 'verification_required' }\n\t\t\t\t>(resolvedRoutes.register, body)\n\t\t},\n\t\tsignOut: () => del<null>(resolvedRoutes.signout),\n\t\tstatus: () =>\n\t\t\tget<{ impersonator?: unknown; user: unknown | null }>(\n\t\t\t\tresolvedRoutes.status\n\t\t\t)\n\t};\n};\n\nconst safeJson = (text: string) => {\n\ttry {\n\t\treturn JSON.parse(text);\n\t} catch {\n\t\treturn text;\n\t}\n};\n\nconst readMessage = (body: unknown) => {\n\tif (typeof body !== 'object' || body === null) return undefined;\n\tconst message: unknown = Reflect.get(body, 'message');\n\n\treturn typeof message === 'string' ? message : undefined;\n};\n\nexport type AuthClient = ReturnType<typeof createAuthClient>;\n",
6
6
  "const DEFAULT_CHECK_INTERVAL_MS = 30_000;\nconst DEFAULT_REASON = 'session_expired';\nconst DEFAULT_REASON_PARAM = 'reason';\nconst DEFAULT_RETURN_URL_PARAM = 'returnUrl';\nconst DEFAULT_SIGN_IN_PATH = '/signin';\nconst DEFAULT_STATUS_PATH = '/oauth2/status';\nconst HTTP_UNAUTHORIZED = 401;\n\nexport type SessionExpiredContext = {\n\treturnTo: string;\n\tsignInUrl: string;\n};\n\nexport type SessionExpiryGuard = {\n\tcheck: () => Promise<boolean>;\n\tdispose: () => void;\n};\n\nexport type SessionExpiryGuardConfig = {\n\tcheckIntervalMs?: number;\n\tisProtectedRequest?: (url: URL) => boolean;\n\tonExpired?: (context: SessionExpiredContext) => void;\n\tprotectedPaths?: readonly string[];\n\treason?: string;\n\treasonParam?: string;\n\treturnUrlParam?: string;\n\tsignInPath?: string;\n\tstatusPath?: string;\n};\n\nlet activeGuard: SessionExpiryGuard | null = null;\n\nconst requestUrl = (input: RequestInfo | URL, origin: string) => {\n\tconst raw = input instanceof Request ? input.url : String(input);\n\n\ttry {\n\t\treturn new URL(raw, origin);\n\t} catch {\n\t\treturn null;\n\t}\n};\n\nexport const buildSessionExpiredSignInUrl = ({\n\tcurrentHref,\n\treason = DEFAULT_REASON,\n\treasonParam = DEFAULT_REASON_PARAM,\n\treturnUrlParam = DEFAULT_RETURN_URL_PARAM,\n\tsignInPath = DEFAULT_SIGN_IN_PATH\n}: {\n\tcurrentHref: string;\n\treason?: string;\n\treasonParam?: string;\n\treturnUrlParam?: string;\n\tsignInPath?: string;\n}) => {\n\tconst current = new URL(currentHref);\n\tconst returnTo = `${current.pathname}${current.search}${current.hash}`;\n\tconst destination = new URL(signInPath, current.origin);\n\tdestination.searchParams.set(reasonParam, reason);\n\tdestination.searchParams.set(returnUrlParam, returnTo);\n\n\treturn destination.origin === current.origin\n\t\t? `${destination.pathname}${destination.search}${destination.hash}`\n\t\t: destination.toString();\n};\n\n/**\n * Installs one browser-wide session-expiry guard. It intercepts 401 responses\n * only for explicitly protected same-origin requests and rechecks the auth\n * status route when a backgrounded or bfcached page becomes active again.\n */\nexport const installSessionExpiryGuard = (\n\tconfig: SessionExpiryGuardConfig = {}\n) => {\n\tif (typeof window === 'undefined' || typeof document === 'undefined') {\n\t\treturn { check: async () => false, dispose: () => undefined };\n\t}\n\tif (activeGuard) return activeGuard;\n\n\tconst {\n\t\tcheckIntervalMs = DEFAULT_CHECK_INTERVAL_MS,\n\t\tisProtectedRequest,\n\t\tonExpired,\n\t\tprotectedPaths = [],\n\t\treason = DEFAULT_REASON,\n\t\treasonParam = DEFAULT_REASON_PARAM,\n\t\treturnUrlParam = DEFAULT_RETURN_URL_PARAM,\n\t\tsignInPath = DEFAULT_SIGN_IN_PATH,\n\t\tstatusPath = DEFAULT_STATUS_PATH\n\t} = config;\n\tconst nativeFetch = window.fetch.bind(window);\n\tconst originalFetch = window.fetch;\n\tlet checking = false;\n\tlet disposed = false;\n\tlet expired = false;\n\tlet lastCheckedAt = Date.now();\n\n\tconst expire = () => {\n\t\tif (expired || disposed) return;\n\t\texpired = true;\n\t\tconst currentHref = window.location.href;\n\t\tconst signInUrl = buildSessionExpiredSignInUrl({\n\t\t\tcurrentHref,\n\t\t\treason,\n\t\t\treasonParam,\n\t\t\treturnUrlParam,\n\t\t\tsignInPath\n\t\t});\n\t\tconst current = new URL(currentHref);\n\t\tconst returnTo = `${current.pathname}${current.search}${current.hash}`;\n\t\tif (onExpired) {\n\t\t\tonExpired({ returnTo, signInUrl });\n\n\t\t\treturn;\n\t\t}\n\t\twindow.location.assign(signInUrl);\n\t};\n\n\tconst protectedRequest = (input: RequestInfo | URL) => {\n\t\tconst url = requestUrl(input, window.location.origin);\n\t\tif (!url || url.origin !== window.location.origin) return false;\n\t\tif (\n\t\t\tnew URL(statusPath, window.location.origin).pathname ===\n\t\t\turl.pathname\n\t\t)\n\t\t\treturn false;\n\n\t\treturn (\n\t\t\tisProtectedRequest?.(url) === true ||\n\t\t\tprotectedPaths.some((path) => url.pathname.startsWith(path))\n\t\t);\n\t};\n\n\tconst guardedFetch = new Proxy(originalFetch, {\n\t\tapply: async (target, thisArg, args) => {\n\t\t\tconst [input] = args;\n\t\t\tconst response = await Reflect.apply(target, thisArg, args);\n\t\t\tif (\n\t\t\t\tresponse.status === HTTP_UNAUTHORIZED &&\n\t\t\t\tprotectedRequest(input)\n\t\t\t) {\n\t\t\t\texpire();\n\t\t\t}\n\n\t\t\treturn response;\n\t\t}\n\t});\n\twindow.fetch = guardedFetch;\n\n\tconst check = async () => {\n\t\tif (checking || expired || disposed) return false;\n\t\tchecking = true;\n\t\tlastCheckedAt = Date.now();\n\t\ttry {\n\t\t\tconst response = await nativeFetch(statusPath, {\n\t\t\t\tcache: 'no-store',\n\t\t\t\tcredentials: 'include',\n\t\t\t\theaders: { accept: 'application/json' }\n\t\t\t});\n\t\t\tif (!response.ok) return false;\n\t\t\tconst payload: unknown = await response.json();\n\t\t\tconst sessionExpired =\n\t\t\t\ttypeof payload === 'object' &&\n\t\t\t\tpayload !== null &&\n\t\t\t\tReflect.get(payload, 'user') === null;\n\t\t\tif (!sessionExpired) return false;\n\t\t\texpire();\n\n\t\t\treturn true;\n\t\t} catch {\n\t\t\t// A connectivity failure is not proof that the session expired.\n\t\t\treturn false;\n\t\t} finally {\n\t\t\tchecking = false;\n\t\t}\n\t};\n\n\tconst checkIfDue = () => {\n\t\tif (\n\t\t\tdocument.visibilityState !== 'visible' ||\n\t\t\tDate.now() - lastCheckedAt < checkIntervalMs\n\t\t)\n\t\t\treturn;\n\t\tvoid check();\n\t};\n\tconst checkPersistedSession = (event: PageTransitionEvent) => {\n\t\tif (!event.persisted) return;\n\t\tvoid check();\n\t};\n\tconst dispose = () => {\n\t\tif (disposed) return;\n\t\tdisposed = true;\n\t\tdocument.removeEventListener('visibilitychange', checkIfDue);\n\t\twindow.removeEventListener('focus', checkIfDue);\n\t\twindow.removeEventListener('pageshow', checkPersistedSession);\n\t\tif (window.fetch === guardedFetch) window.fetch = originalFetch;\n\t\tactiveGuard = null;\n\t};\n\n\tdocument.addEventListener('visibilitychange', checkIfDue);\n\twindow.addEventListener('focus', checkIfDue);\n\twindow.addEventListener('pageshow', checkPersistedSession);\n\tactiveGuard = { check, dispose };\n\n\treturn activeGuard;\n};\n\nexport const isProtectedSessionRequest = ({\n\tinput,\n\torigin,\n\tprotectedPaths\n}: {\n\tinput: RequestInfo | URL;\n\torigin: string;\n\tprotectedPaths: readonly string[];\n}) => {\n\tconst url = requestUrl(input, origin);\n\n\treturn (\n\t\turl?.origin === origin &&\n\t\tprotectedPaths.some((path) => url.pathname.startsWith(path))\n\t);\n};\n",
7
+ "// A value is a safe SAME-ORIGIN redirect target iff it begins with a single\n// '/' that is NOT followed by '/' or '\\'. Browsers normalize backslashes to\n// forward slashes, so '/\\evil.com' (and '/\\\\evil.com') resolve to the\n// protocol-relative '//evil.com' — an open redirect. Absolute URLs,\n// protocol-relative '//…', and backslash-prefixed paths are all rejected.\nexport const isSafeLocalPath = (value: string) => /^\\/(?![/\\\\])/.test(value);\n\n// Reduce an untrusted post-login redirect target to a safe same-origin path,\n// falling back to `fallback` (default '/') when it is not one.\nexport const toSafeLocalPath = (value: string | undefined, fallback = '/') =>\n\tvalue !== undefined && isSafeLocalPath(value) ? value : fallback;\n",
7
8
  "// Framework-agnostic glue between the WebAuthn ceremonies the package exposes via\n// `createAuthClient` and the browser's `navigator.credentials.{get,create}` APIs.\n// Used by the framework composables (`./react`, `./vue`, `./solid`, `./svelte`) so the\n// React + Vue + Solid + Svelte hooks all share the same imperative core; the framework\n// wrappers only add reactivity.\n//\n// `@simplewebauthn/browser` is an OPTIONAL peer dep — consumers that don't import any\n// of the passkey composables never load it. We dynamic-import lazily on first call so a\n// non-passkey consumer pays nothing at module load.\n\nimport type { AuthClient, AuthClientError } from './createAuthClient';\n\nconst loadBrowser = () => import('@simplewebauthn/browser');\n\nconst errorFor = (caught: unknown): AuthClientError => ({\n\tbody: null,\n\tmessage: caught instanceof Error ? caught.message : 'webauthn_failed',\n\tstatus: 0\n});\n\n// Runs the WebAuthn authentication ceremony in conditional-UI mode (the browser surfaces\n// saved passkeys directly via autofill on a focused `<input autocomplete=\"webauthn\">`).\n// Returns the same `{ data, error }` shape `createAuthClient` already uses, so composables\n// can pipe the result into their state setters unchanged.\nexport const runConditionalAuthentication = async (client: AuthClient) => {\n\tif (typeof window === 'undefined' || !window.PublicKeyCredential) {\n\t\treturn {\n\t\t\tdata: null,\n\t\t\terror: errorFor(new Error('webauthn_unavailable'))\n\t\t};\n\t}\n\tconst options = await client.passkeys.authenticateOptions();\n\tif (options.error) return { data: null, error: options.error };\n\ttry {\n\t\tconst { startAuthentication } = await loadBrowser();\n\t\tconst credential = await startAuthentication({\n\t\t\toptionsJSON: options.data,\n\t\t\tuseBrowserAutofill: true\n\t\t});\n\n\t\treturn client.passkeys.authenticateVerify(credential);\n\t} catch (caught) {\n\t\treturn { data: null, error: errorFor(caught) };\n\t}\n};\n\n// Runs the WebAuthn registration ceremony for the currently authenticated user. Used by\n// the \"upgrade to passkey\" prompt — after a password sign-in, surface a \"save a passkey\n// to this device for next time?\" CTA.\nexport const runPasskeyRegistration = async (client: AuthClient) => {\n\tif (typeof window === 'undefined' || !window.PublicKeyCredential) {\n\t\treturn {\n\t\t\tdata: null,\n\t\t\terror: errorFor(new Error('webauthn_unavailable'))\n\t\t};\n\t}\n\tconst options = await client.passkeys.registerOptions();\n\tif (options.error) return { data: null, error: options.error };\n\ttry {\n\t\tconst { startRegistration } = await loadBrowser();\n\t\tconst credential = await startRegistration({\n\t\t\toptionsJSON: options.data\n\t\t});\n\n\t\treturn client.passkeys.registerVerify(credential);\n\t} catch (caught) {\n\t\treturn { data: null, error: errorFor(caught) };\n\t}\n};\n"
8
9
  ],
9
- "mappings": "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",
10
- "debugId": "B4E53841C044AF5F64756E2164756E21",
10
+ "mappings": "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",
11
+ "debugId": "E8018F05FE86589464756E2164756E21",
11
12
  "names": []
12
13
  }
package/dist/index.d.ts CHANGED
@@ -3467,6 +3467,7 @@ export { createAuthHtmxRoutes } from './htmx/routes';
3467
3467
  export { resolveAuthHtmxRenderers } from './htmx/renderers';
3468
3468
  export type { AuthHtmxConfig, AuthHtmxConnectorTarget, AuthHtmxProviderData, AuthHtmxProviderInfo, AuthHtmxRenderOverrides, AuthHtmxRenderersConfig, AuthHtmxUser, AuthIdentityPayload, LinkedProviderPayload } from './htmx/types';
3469
3469
  export * from './utils';
3470
+ export * from './redirect';
3470
3471
  export { buildClientProviders, resolveClientProviderEntry, resolveProviderClientConfiguration } from './providers/clients';
3471
3472
  export type { OAuth2TokenResponse, OAuth2Client, OAuth2ClientForConfig, CustomProviderCredentials, ProviderConfig, ProviderOption, PKCEProvider, OIDCProvider, RefreshableProvider, RevocableProvider, ScopeRequiredProvider, ProvidersMap, ProviderConfiguration, CredentialsFor } from 'citra';
3472
3473
  export { providers, providerOptions, createCustomOAuth2Client, defineProvider, refreshableProviderOptions, revocableProviderOptions, oidcProviderOptions, pkceProviderOptions, scopeRequiredProviderOptions, decodeJWT, extractPropFromIdentity, isValidProviderOption, isRefreshableOAuth2Client, isRefreshableProviderOption, isOIDCProviderOption, isPKCEProviderOption, isRevocableProviderOption, isRevocableOAuth2Client } from 'citra';
package/dist/index.js CHANGED
@@ -5113,6 +5113,9 @@ var credentialsEmailVerification = ({
5113
5113
  if (!consumed) {
5114
5114
  return status("Bad Request", "Invalid or expired verification token");
5115
5115
  }
5116
+ if (consumed.expiresAt < Date.now()) {
5117
+ return status("Bad Request", "Invalid or expired verification token");
5118
+ }
5116
5119
  await credentialStore.setEmailVerified(consumed.email);
5117
5120
  await onEmailVerified?.({ email: consumed.email });
5118
5121
  return status("OK", { status: "email_verified" });
@@ -5466,6 +5469,9 @@ var credentialsPasswordReset = ({
5466
5469
  if (!consumed) {
5467
5470
  return status("Bad Request", "Invalid or expired reset token");
5468
5471
  }
5472
+ if (consumed.expiresAt < Date.now()) {
5473
+ return status("Bad Request", "Invalid or expired reset token");
5474
+ }
5469
5475
  const policy = await evaluatePassword(password, passwordPolicy);
5470
5476
  if (!policy.ok) {
5471
5477
  return status("Bad Request", {
@@ -10275,6 +10281,12 @@ var resolveProviderClientConfiguration = ({
10275
10281
  // src/routes/authorize.ts
10276
10282
  init_constants();
10277
10283
  import { Elysia as Elysia27, t as t20 } from "elysia";
10284
+
10285
+ // src/redirect.ts
10286
+ var isSafeLocalPath = (value) => /^\/(?![/\\])/.test(value);
10287
+ var toSafeLocalPath = (value, fallback = "/") => value !== undefined && isSafeLocalPath(value) ? value : fallback;
10288
+
10289
+ // src/routes/authorize.ts
10278
10290
  var parseReferer = (headerReferer) => {
10279
10291
  if (!headerReferer)
10280
10292
  return "/";
@@ -10282,10 +10294,7 @@ var parseReferer = (headerReferer) => {
10282
10294
  const url = new URL(headerReferer);
10283
10295
  return url.pathname + url.search;
10284
10296
  } catch {
10285
- if (headerReferer.startsWith("/") && !headerReferer.startsWith("//")) {
10286
- return headerReferer;
10287
- }
10288
- return "/";
10297
+ return toSafeLocalPath(headerReferer);
10289
10298
  }
10290
10299
  };
10291
10300
  var authorize = ({
@@ -10500,7 +10509,7 @@ var callback = ({
10500
10509
  if (requiresPKCE && verifier === undefined) {
10501
10510
  return status("Bad Request", "Code verifier not found and is required");
10502
10511
  }
10503
- const originUrl = origin_url?.value ?? "/";
10512
+ const originUrl = toSafeLocalPath(origin_url?.value);
10504
10513
  let tokenResponse2;
10505
10514
  try {
10506
10515
  tokenResponse2 = await providerInstance.validateAuthorizationCode(requiresPKCE ? { code, codeVerifier: verifier } : { code });
@@ -11962,7 +11971,7 @@ var parseReferer2 = (referer) => {
11962
11971
  const url = new URL(referer);
11963
11972
  return url.pathname + url.search;
11964
11973
  } catch {
11965
- return referer.startsWith("/") && !referer.startsWith("//") ? referer : "/";
11974
+ return toSafeLocalPath(referer);
11966
11975
  }
11967
11976
  };
11968
11977
  var oidcSsoRoutes = ({
@@ -12105,18 +12114,13 @@ var oidcSsoRoutes = ({
12105
12114
 
12106
12115
  // src/sso/samlRoutes.ts
12107
12116
  import { Elysia as Elysia39, t as t31 } from "elysia";
12108
- var toLocalPath = (value) => {
12109
- if (value === undefined || value.length === 0)
12110
- return "/";
12111
- return value.startsWith("/") && !value.startsWith("//") ? value : "/";
12112
- };
12113
12117
  var refererPath = (referer) => {
12114
12118
  if (referer === undefined)
12115
12119
  return "/";
12116
12120
  try {
12117
- return toLocalPath(new URL(referer).pathname);
12121
+ return toSafeLocalPath(new URL(referer).pathname);
12118
12122
  } catch {
12119
- return toLocalPath(referer);
12123
+ return toSafeLocalPath(referer);
12120
12124
  }
12121
12125
  };
12122
12126
  var settle = async (work) => {
@@ -12219,7 +12223,7 @@ var samlSsoRoutes = ({
12219
12223
  user,
12220
12224
  userSessionId
12221
12225
  });
12222
- return redirect(toLocalPath(body.RelayState));
12226
+ return redirect(toSafeLocalPath(body.RelayState));
12223
12227
  } catch (error) {
12224
12228
  await onSsoCallbackError?.({ error, organizationId });
12225
12229
  return status("Internal Server Error", "SAML sign-in failed");
@@ -12310,7 +12314,7 @@ var samlSsoRoutes = ({
12310
12314
  sloUrl
12311
12315
  }) ?? Promise.resolve());
12312
12316
  if (!("error" in responseSettled)) {
12313
- return redirect(toLocalPath(RelayState));
12317
+ return redirect(toSafeLocalPath(RelayState));
12314
12318
  }
12315
12319
  await onSsoCallbackError?.({
12316
12320
  error: responseSettled.error,
@@ -12358,7 +12362,7 @@ var samlSsoRoutes = ({
12358
12362
  });
12359
12363
  return redirect(url);
12360
12364
  }
12361
- return redirect(toLocalPath(info.relayState ?? RelayState));
12365
+ return redirect(toSafeLocalPath(info.relayState ?? RelayState));
12362
12366
  }, {
12363
12367
  cookie: t31.Cookie({
12364
12368
  user_session_id: t31.Optional(userSessionIdTypebox)
@@ -37581,6 +37585,7 @@ export {
37581
37585
  userInfoChallengeHeader,
37582
37586
  updateRegisteredClient,
37583
37587
  trustDevice,
37588
+ toSafeLocalPath,
37584
37589
  toPublicJwk,
37585
37590
  toBase64Url2 as toBase64Url,
37586
37591
  switchActiveSession,
@@ -37700,6 +37705,7 @@ export {
37700
37705
  isValidUser,
37701
37706
  isValidProviderOption,
37702
37707
  isUserSessionId,
37708
+ isSafeLocalPath,
37703
37709
  isRevocableProviderOption,
37704
37710
  isRevocableOAuth2Client,
37705
37711
  isRefreshableProviderOption,
@@ -38040,5 +38046,5 @@ export {
38040
38046
  AGENT_CLAIM_GRANT_TYPE
38041
38047
  };
38042
38048
 
38043
- //# debugId=FC3F27A521162E4064756E2164756E21
38049
+ //# debugId=6BF9ABB7B635052264756E2164756E21
38044
38050
  //# sourceMappingURL=index.js.map