@rttnd/gau 1.4.2 → 1.4.4
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/dist/chunk-6HKZAQHT.js +1 -0
- package/dist/chunk-6HKZAQHT.js.map +1 -0
- package/dist/chunk-MXZ363UZ.js +1 -0
- package/dist/chunk-MXZ363UZ.js.map +1 -0
- package/dist/chunk-NHENQLYI.js +1 -0
- package/dist/chunk-NHENQLYI.js.map +1 -0
- package/dist/chunk-V6AIGB33.js +1 -0
- package/dist/chunk-V6AIGB33.js.map +1 -0
- package/dist/chunk-VXWI4D7H.js +1 -0
- package/dist/chunk-VXWI4D7H.js.map +1 -0
- package/dist/src/adapters/drizzle/index.d.ts +1 -1
- package/dist/src/adapters/drizzle/index.js +1 -1
- package/dist/src/adapters/drizzle/pg.d.ts +3 -26
- package/dist/src/adapters/drizzle/pg.d.ts.map +1 -1
- package/dist/src/adapters/drizzle/shared.d.ts +49 -0
- package/dist/src/adapters/drizzle/shared.d.ts.map +1 -0
- package/dist/src/adapters/drizzle/sqlite.d.ts +3 -26
- package/dist/src/adapters/drizzle/sqlite.d.ts.map +1 -1
- package/dist/src/adapters/index.js +1 -1
- package/dist/src/client/shared/clientAuth.d.ts +57 -0
- package/dist/src/client/shared/clientAuth.d.ts.map +1 -0
- package/dist/src/client/solid/index.d.ts +3 -14
- package/dist/src/client/solid/index.d.ts.map +1 -1
- package/dist/src/client/solid/index.jsx +160 -216
- package/dist/src/client/solid2/Protected.d.ts +5 -0
- package/dist/src/client/solid2/Protected.d.ts.map +1 -0
- package/dist/src/client/solid2/index.d.ts +36 -0
- package/dist/src/client/solid2/index.d.ts.map +1 -0
- package/dist/src/client/solid2/index.jsx +708 -0
- package/dist/src/client/svelte/AuthProvider/index.svelte.d.ts +13 -0
- package/dist/src/client/svelte/AuthProvider/index.svelte.d.ts.map +1 -0
- package/dist/src/client/svelte/Protected/index.svelte.d.ts +10 -0
- package/dist/src/client/svelte/Protected/index.svelte.d.ts.map +1 -0
- package/dist/src/client/svelte/index.svelte.d.ts +15 -0
- package/dist/src/client/svelte/index.svelte.d.ts.map +1 -0
- package/dist/src/client/svelte/index.svelte.js +1 -1
- package/dist/src/client/svelte/index.svelte.js.map +1 -1
- package/dist/src/client/vanilla/index.js +1 -1
- package/dist/src/client/vanilla/index.js.map +1 -1
- package/dist/src/core/handlers/callback.d.ts.map +1 -1
- package/dist/src/core/handlers/index.js +1 -1
- package/dist/src/core/index.d.ts +3 -3
- package/dist/src/core/index.d.ts.map +1 -1
- package/dist/src/core/index.js +1 -1
- package/dist/src/core/serverSession.d.ts +13 -0
- package/dist/src/core/serverSession.d.ts.map +1 -0
- package/dist/src/index.js +1 -1
- package/dist/src/jwt/index.js +1 -1
- package/dist/src/oauth/index.d.ts +13 -11
- package/dist/src/oauth/index.d.ts.map +1 -1
- package/dist/src/oauth/index.js +1 -1
- package/dist/src/oauth/index.js.map +1 -1
- package/dist/src/oauth/providers/discord.d.ts.map +1 -1
- package/dist/src/oauth/providers/facebook.d.ts.map +1 -1
- package/dist/src/oauth/providers/github.d.ts.map +1 -1
- package/dist/src/oauth/providers/google.d.ts.map +1 -1
- package/dist/src/oauth/providers/microsoft.d.ts.map +1 -1
- package/dist/src/oauth/utils.d.ts +26 -0
- package/dist/src/oauth/utils.d.ts.map +1 -1
- package/dist/src/runtimes/index.js +1 -1
- package/dist/src/runtimes/tauri/index.d.ts.map +1 -1
- package/dist/src/runtimes/tauri/index.js +1 -1
- package/dist/src/solidstart/index.d.ts +4 -4
- package/dist/src/solidstart/index.d.ts.map +1 -1
- package/dist/src/solidstart/index.js +1 -1
- package/dist/src/solidstart/index.js.map +1 -1
- package/dist/src/sveltekit/index.d.ts +2 -2
- package/dist/src/sveltekit/index.d.ts.map +1 -1
- package/dist/src/sveltekit/index.js +1 -1
- package/dist/src/sveltekit/index.js.map +1 -1
- package/package.json +21 -8
- package/dist/chunk-DVVL3GFT.js +0 -1
- package/dist/chunk-DVVL3GFT.js.map +0 -1
- package/dist/chunk-PL7MV7OC.js +0 -1
- package/dist/chunk-PL7MV7OC.js.map +0 -1
- package/dist/chunk-RPFUKTQA.js +0 -1
- package/dist/chunk-RPFUKTQA.js.map +0 -1
- package/dist/client/svelte/index.svelte.d.ts +0 -26
- package/dist/client/svelte/index.svelte.d.ts.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{BROWSER as e}from"esm-env";import{BROWSER as n}from"esm-env";var t="__gau-session-token",r="X-Refreshed-Token";function o(e){if(n)try{localStorage.setItem(t,e)}catch{}}function i(){if(!n)return null;try{return localStorage.getItem(t)}catch{return null}}function a(){if(n)try{localStorage.removeItem(t)}catch{}}function c(e){if(!n)return;const t=e.headers.get(r);t&&o(t)}function s(){return e&&"__TAURI_INTERNALS__"in globalThis}function u(n){try{return new URL(n).toString().replace(/\/$/,"")}catch{if(e&&"undefined"!=typeof window)try{return new URL(n,window.location.origin).toString().replace(/\/$/,"")}catch{return n}return n}}function l(e,n){return e??`${n}://oauth/callback`}async function f(e,t,r="gau",o,i){if(!s())return;const{openUrl:a}=await import("@tauri-apps/plugin-opener"),c=l(o,r),{codeVerifier:f,codeChallenge:w}=await async function(){if(!n||!window.crypto||!window.crypto.subtle)throw new Error("PKCE relies on window.crypto, which is not available in this environment.");function e(e){return btoa(String.fromCharCode(...e)).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}const t=new Uint8Array(43);window.crypto.getRandomValues(t);const r=e(t),o=(new TextEncoder).encode(r),i=await window.crypto.subtle.digest("SHA-256",o);return{codeVerifier:r,codeChallenge:e(new Uint8Array(i))}}();localStorage.setItem("gau-pkce-verifier",f);const d=new URLSearchParams;d.set("redirectTo",c),i&&d.set("profile",String(i)),d.set("code_challenge",w);const g=`${u(t)}/${e}?${d.toString()}`;await a(g)}async function w(e){if(!s())return;const{listen:n}=await import("@tauri-apps/api/event");try{return await n("deep-link",async n=>{await e(n.payload)})}catch(e){console.error(e)}}async function d(n,t,r,o){const i=new URL(n),a=function(n){try{return new URL(n).origin}catch{if(e&&"undefined"!=typeof window)try{return new URL(n,window.location.origin).origin}catch{return null}return null}}(t);if(i.protocol!==`${r}:`&&(!a||i.origin!==a))return;const c=new URLSearchParams(i.search).get("code");if(c){const e=localStorage.getItem("gau-pkce-verifier");if(!e)return void console.error("No PKCE verifier found");localStorage.removeItem("gau-pkce-verifier");try{const n=await fetch(`${t}/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:c,codeVerifier:e})});if(n.ok){const e=await n.json();e.token&&o(e.token)}else console.error("Failed to exchange code for token")}catch(e){console.error("Error exchanging code for token:",e)}}}async function g(e,n,t="gau",r,o){if(!s())return;const{openUrl:a}=await import("@tauri-apps/plugin-opener"),c=l(r,t),f=i();if(!f)return void console.error("No session token found, cannot link account.");const w=new URLSearchParams;w.set("redirectTo",c),w.set("token",f),o&&w.set("profile",String(o));const d=`${u(n)}/link/${e}?${w.toString()}`;await a(d)}async function p(e,n,t){if(!s())return;return await w(async r=>{d(r,e,n,t)})}export{t as SESSION_TOKEN_KEY,r as REFRESHED_TOKEN_HEADER,o as storeSessionToken,i as getSessionToken,a as clearSessionToken,c as handleRefreshedToken,s as isTauri,f as signInWithTauri,w as setupTauriListener,d as handleTauriDeepLink,g as linkAccountWithTauri,p as startAuthBridge};//# sourceMappingURL=chunk-6HKZAQHT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/runtimes/tauri/index.ts","../src/client/token.ts"],"sourcesContent":["import type { ProfileName, ProviderIds } from '../../core'\nimport { BROWSER } from 'esm-env'\nimport { generatePKCE, getSessionToken } from '../../client/token'\n\nexport function isTauri(): boolean {\n return BROWSER && '__TAURI_INTERNALS__' in globalThis\n}\n\nfunction resolveOrigin(baseUrl: string): string | null {\n try {\n return new URL(baseUrl).origin\n }\n catch {\n if (BROWSER && typeof window !== 'undefined') {\n try {\n return new URL(baseUrl, window.location.origin).origin\n }\n catch {\n return null\n }\n }\n return null\n }\n}\n\nfunction resolveAbsoluteBase(baseUrl: string): string {\n try {\n return new URL(baseUrl).toString().replace(/\\/$/, '')\n }\n catch {\n if (BROWSER && typeof window !== 'undefined') {\n try {\n return new URL(baseUrl, window.location.origin).toString().replace(/\\/$/, '')\n }\n catch {\n return baseUrl\n }\n }\n return baseUrl\n }\n}\n\nfunction resolveTauriRedirect(redirectOverride: string | undefined, scheme: string) {\n return redirectOverride ?? `${scheme}://oauth/callback`\n}\n\nexport async function signInWithTauri<const TAuth = unknown, P extends ProviderIds<TAuth> = ProviderIds<TAuth>, PR extends (ProfileName<TAuth, P> | string) | undefined = undefined>(\n provider: P,\n baseUrl: string,\n scheme: string = 'gau',\n redirectOverride?: string,\n profile?: PR,\n) {\n if (!isTauri())\n return\n\n const { openUrl } = await import('@tauri-apps/plugin-opener')\n const redirectTo = resolveTauriRedirect(redirectOverride, scheme)\n\n const { codeVerifier, codeChallenge } = await generatePKCE()\n localStorage.setItem('gau-pkce-verifier', codeVerifier)\n\n const params = new URLSearchParams()\n params.set('redirectTo', redirectTo)\n if (profile)\n params.set('profile', String(profile))\n params.set('code_challenge', codeChallenge)\n const authUrl = `${resolveAbsoluteBase(baseUrl)}/${provider}?${params.toString()}`\n await openUrl(authUrl)\n}\n\nexport async function setupTauriListener(\n handler: (url: string) => Promise<void>,\n): Promise<(() => void) | void> {\n if (!isTauri())\n return\n\n const { listen } = await import('@tauri-apps/api/event')\n try {\n const unlisten = await listen<string>('deep-link', async (event) => {\n await handler(event.payload)\n })\n return unlisten\n }\n catch (err) {\n console.error(err)\n }\n}\n\nexport async function handleTauriDeepLink(url: string, baseUrl: string, scheme: string, onToken: (token: string) => void) {\n const parsed = new URL(url)\n const baseOrigin = resolveOrigin(baseUrl)\n if (parsed.protocol !== `${scheme}:` && (!baseOrigin || parsed.origin !== baseOrigin))\n return\n\n const queryParams = new URLSearchParams(parsed.search)\n const code = queryParams.get('code')\n if (code) {\n const verifier = localStorage.getItem('gau-pkce-verifier')\n if (!verifier) {\n console.error('No PKCE verifier found')\n return\n }\n localStorage.removeItem('gau-pkce-verifier')\n\n try {\n const res = await fetch(`${baseUrl}/token`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ code, codeVerifier: verifier }),\n })\n if (res.ok) {\n const data = await res.json()\n if (data.token)\n onToken(data.token)\n }\n else {\n console.error('Failed to exchange code for token')\n }\n }\n catch (e) {\n console.error('Error exchanging code for token:', e)\n }\n }\n}\n\nexport async function linkAccountWithTauri<const TAuth = unknown, P extends ProviderIds<TAuth> = ProviderIds<TAuth>, PR extends (ProfileName<TAuth, P> | string) | undefined = undefined>(\n provider: P,\n baseUrl: string,\n scheme: string = 'gau',\n redirectOverride?: string,\n profile?: PR,\n) {\n if (!isTauri())\n return\n\n const { openUrl } = await import('@tauri-apps/plugin-opener')\n\n const redirectTo = resolveTauriRedirect(redirectOverride, scheme)\n\n const token = getSessionToken()\n if (!token) {\n console.error('No session token found, cannot link account.')\n return\n }\n\n const params = new URLSearchParams()\n params.set('redirectTo', redirectTo)\n params.set('token', token)\n if (profile)\n params.set('profile', String(profile))\n const linkUrl = `${resolveAbsoluteBase(baseUrl)}/link/${provider}?${params.toString()}`\n await openUrl(linkUrl)\n}\n\nexport async function startAuthBridge(\n baseUrl: string,\n scheme: string,\n onToken: (token: string) => Promise<void> | void,\n): Promise<(() => void) | void> {\n if (!isTauri())\n return\n\n const unlisten = await setupTauriListener(async (url) => {\n handleTauriDeepLink(url, baseUrl, scheme, onToken)\n })\n return unlisten\n}\n","import { BROWSER } from 'esm-env'\n\nexport const SESSION_TOKEN_KEY = '__gau-session-token'\n\nexport const REFRESHED_TOKEN_HEADER = 'X-Refreshed-Token'\n\nexport function storeSessionToken(token: string) {\n if (!BROWSER)\n return\n try {\n localStorage.setItem(SESSION_TOKEN_KEY, token)\n }\n catch {}\n}\n\nexport function getSessionToken(): string | null {\n if (!BROWSER)\n return null\n try {\n return localStorage.getItem(SESSION_TOKEN_KEY)\n }\n catch {\n return null\n }\n}\n\nexport function clearSessionToken() {\n if (!BROWSER)\n return\n try {\n localStorage.removeItem(SESSION_TOKEN_KEY)\n }\n catch {}\n}\n\nexport function handleRefreshedToken(response: Response): void {\n if (!BROWSER)\n return\n const refreshed = response.headers.get(REFRESHED_TOKEN_HEADER)\n if (refreshed)\n storeSessionToken(refreshed)\n}\n\nexport async function generatePKCE() {\n if (!BROWSER || !window.crypto || !window.crypto.subtle)\n throw new Error('PKCE relies on window.crypto, which is not available in this environment.')\n\n function base64UrlEncode(array: Uint8Array): string {\n return btoa(String.fromCharCode(...array))\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '')\n }\n\n const verifierLength = 43\n const randomValues = new Uint8Array(verifierLength)\n window.crypto.getRandomValues(randomValues)\n const codeVerifier = base64UrlEncode(randomValues)\n\n const encoder = new TextEncoder()\n const data = encoder.encode(codeVerifier)\n const hash = await window.crypto.subtle.digest('SHA-256', data)\n const codeChallenge = base64UrlEncode(new Uint8Array(hash))\n\n return { codeVerifier, codeChallenge }\n}\n"],"mappings":"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","names":["BROWSER","BROWSER"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{NULL_SESSION as r,createAuth as e,getSessionTokenFromRequest as n,toClientSession as t}from"./chunk-NHENQLYI.js";var o=new WeakMap;function i(r){return"providerMap"in r&&"signJWT"in r?r:e(r)}async function s(e,t){const{token:i}=n(t),s=function(r){let e=o.get(r);return e||(e=Array.from(r.providerMap.keys()),o.set(r,e)),[...e]}(e);if(!i)return{...r,providers:s};try{const n=await e.validateSession(i);return n?{...n,providers:s}:{...r,providers:s}}catch{return{...r,providers:s}}}function u(r,e,n){let o=n?Promise.resolve(n):null,i=null;const u=()=>o??=s(r,e);return{getServerSession:u,getSession:()=>i??=u().then(t)}}export{i as resolveAuth,s as resolveServerSession,u as createRequestSessionCache};//# sourceMappingURL=chunk-MXZ363UZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/serverSession.ts"],"sourcesContent":["import type { OAuthProvider } from '../oauth'\nimport type { CreateAuthOptions, ProviderIds } from './createAuth'\nimport type { GauServerSession, GauSession } from './index'\nimport { createAuth, NULL_SESSION, toClientSession } from './index'\nimport { getSessionTokenFromRequest } from './utils'\n\nexport type AuthInstance<TProviders extends OAuthProvider<any>[]> = ReturnType<typeof createAuth<TProviders>>\n\nconst providerIdsCache = new WeakMap<object, readonly string[]>()\n\nexport function resolveAuth<const TProviders extends OAuthProvider<any>[]>(\n optionsOrAuth: CreateAuthOptions<TProviders> | AuthInstance<TProviders>,\n): AuthInstance<TProviders> {\n const isInstance = 'providerMap' in optionsOrAuth && 'signJWT' in optionsOrAuth\n return isInstance\n ? optionsOrAuth as AuthInstance<TProviders>\n : createAuth(optionsOrAuth)\n}\n\nexport function getAuthProviders<const TProviders extends OAuthProvider<any>[]>(\n auth: AuthInstance<TProviders>,\n): ProviderIds<AuthInstance<TProviders>>[] {\n let providers = providerIdsCache.get(auth)\n if (!providers) {\n providers = Array.from(auth.providerMap.keys())\n providerIdsCache.set(auth, providers)\n }\n return [...providers] as ProviderIds<AuthInstance<TProviders>>[]\n}\n\nexport async function resolveServerSession<const TProviders extends OAuthProvider<any>[]>(\n auth: AuthInstance<TProviders>,\n request: Request,\n): Promise<GauServerSession<ProviderIds<AuthInstance<TProviders>>>> {\n const { token: sessionToken } = getSessionTokenFromRequest(request)\n const providers = getAuthProviders(auth)\n\n if (!sessionToken)\n return { ...NULL_SESSION, providers }\n\n try {\n const validated = await auth.validateSession(sessionToken)\n if (!validated)\n return { ...NULL_SESSION, providers }\n\n return { ...validated, providers }\n }\n catch {\n return { ...NULL_SESSION, providers }\n }\n}\n\nexport function createRequestSessionCache<const TProviders extends OAuthProvider<any>[]>(\n auth: AuthInstance<TProviders>,\n request: Request,\n preloadedServerSession?: GauServerSession<ProviderIds<AuthInstance<TProviders>>>,\n) {\n let cachedServer: Promise<GauServerSession<ProviderIds<AuthInstance<TProviders>>>> | null = preloadedServerSession\n ? Promise.resolve(preloadedServerSession)\n : null\n let cachedClient: Promise<GauSession<ProviderIds<AuthInstance<TProviders>>>> | null = null\n\n const getServerSession = (): Promise<GauServerSession<ProviderIds<AuthInstance<TProviders>>>> => {\n return cachedServer ??= resolveServerSession(auth, request)\n }\n\n const getSession = (): Promise<GauSession<ProviderIds<AuthInstance<TProviders>>>> => {\n return cachedClient ??= getServerSession().then(toClientSession)\n }\n\n return {\n getServerSession,\n getSession,\n }\n}\n"],"mappings":";;;;;;;;AAQA,IAAM,mBAAmB,oBAAI,QAAmC;AAEzD,SAAS,YACd,eAC0B;AAC1B,QAAM,aAAa,iBAAiB,iBAAiB,aAAa;AAClE,SAAO,aACH,gBACA,WAAW,aAAa;AAC9B;AAEO,SAAS,iBACd,MACyC;AACzC,MAAI,YAAY,iBAAiB,IAAI,IAAI;AACzC,MAAI,CAAC,WAAW;AACd,gBAAY,MAAM,KAAK,KAAK,YAAY,KAAK,CAAC;AAC9C,qBAAiB,IAAI,MAAM,SAAS;AAAA,EACtC;AACA,SAAO,CAAC,GAAG,SAAS;AACtB;AAEA,eAAsB,qBACpB,MACA,SACkE;AAClE,QAAM,EAAE,OAAO,aAAa,IAAI,2BAA2B,OAAO;AAClE,QAAM,YAAY,iBAAiB,IAAI;AAEvC,MAAI,CAAC;AACH,WAAO,EAAE,GAAG,cAAc,UAAU;AAEtC,MAAI;AACF,UAAM,YAAY,MAAM,KAAK,gBAAgB,YAAY;AACzD,QAAI,CAAC;AACH,aAAO,EAAE,GAAG,cAAc,UAAU;AAEtC,WAAO,EAAE,GAAG,WAAW,UAAU;AAAA,EACnC,QACM;AACJ,WAAO,EAAE,GAAG,cAAc,UAAU;AAAA,EACtC;AACF;AAEO,SAAS,0BACd,MACA,SACA,wBACA;AACA,MAAI,eAAwF,yBACxF,QAAQ,QAAQ,sBAAsB,IACtC;AACJ,MAAI,eAAkF;AAEtF,QAAM,mBAAmB,MAAwE;AAC/F,WAAO,iBAAiB,qBAAqB,MAAM,OAAO;AAAA,EAC5D;AAEA,QAAM,aAAa,MAAkE;AACnF,WAAO,iBAAiB,iBAAiB,EAAE,KAAK,eAAe;AAAA,EACjE;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{htmlResponse as e,renderCancelledPage as t,renderSuccessPage as r}from"./chunk-VB2ML4Q5.js";import{createOAuthUris as n}from"./chunk-VXWI4D7H.js";import{createJWTSignatureMessage as o,encodeJWT as s,JWSRegisteredHeaders as i,JWTRegisteredClaims as a,parseJWT as c}from"@oslojs/jwt";import{parse as l,serialize as d}from"cookie";var u={path:"/",sameSite:"lax",secure:!0,httpOnly:!0};function f(e){const t=new Map;if(e){const r=l(e);for(const e in r)t.set(e,r[e])}return t}var h=class{constructor(e,t){this.requestCookies=e,this.defaultOptions=t}#e=[];get(e){return this.requestCookies.get(e)}set(e,t,r){const n={...this.defaultOptions,...r};this.#e.push([e,t,n])}delete(e,t){this.set(e,"",{...t,expires:new Date(0),maxAge:0})}toHeaders(){const e=new Headers;for(const[t,r,n]of this.#e)e.append("Set-Cookie",d(t,r,n));return e}},p="__gau-csrf-token",w="__gau-session-token",g="__gau-session-stash",A="__gau-session-strategy",m="__gau-linking-token",E="__gau-pkce-code-verifier",T="__gau-callback-uri",I="__gau-provider-options",O="__gau-client-challenge",k=600;import{parse as y,serialize as U}from"cookie";function N(e){const t=f(e.headers.get("Cookie")).get(w);if(t)return{token:t,source:"cookie"};const r=e.headers.get("Authorization");return r?.startsWith("Bearer ")?{token:r.substring(7),source:"bearer"}:{}}function _({adapter:e,providers:t,basePath:r="/api/auth",jwt:n={},session:o={},cookies:s={},onOAuthExchange:i,mapExternalProfile:a,onBeforeLinkAccount:c,onAfterLinkAccount:l,trustHosts:d=[],autoLink:f="verifiedEmail",allowDifferentEmails:h=!0,updateUserInfoOnLink:p=!1,roles:A={},cors:m=!0,profiles:E,onError:T,errorRedirect:I,impersonation:O}){const{algorithm:k="ES256",secret:_,iss:v,aud:R,ttl:D=604800}=n,C={...u,...s},x=o.strategy??"auto";if("ES256"===k&&void 0!==_&&"string"!=typeof _)throw new oe("For ES256, the secret option must be a string.");const b=new Map(t.map(e=>[e.id,e])),P=!1!==m&&{allowedOrigins:(!0===m?"all":m.allowedOrigins)??"all",allowCredentials:(!0===m||m.allowCredentials)??!0,allowedHeaders:(!0===m?void 0:m.allowedHeaders)??["Content-Type","Authorization","Cookie"],allowedMethods:(!0===m?void 0:m.allowedMethods)??["GET","POST","OPTIONS"],exposeHeaders:!0===m?void 0:m.exposeHeaders,maxAge:!0===m?void 0:m.maxAge},H=E??{},M={defaultRole:A.defaultRole??"user",resolveOnCreate:A.resolveOnCreate,adminRoles:A.adminRoles??["admin"],adminUserIds:A.adminUserIds??[]},F=O?.enabled?{enabled:!0,allowedRoles:O.allowedRoles??M.adminRoles,cannotImpersonate:O.cannotImpersonate??M.adminRoles,maxTTL:O.maxTTL??3600,onImpersonate:O.onImpersonate}:null;async function V(e,t={}){return de(e,function(e={}){const t={ttl:e.ttl,iss:e.iss??v,aud:e.aud??R,sub:e.sub};if("HS256"===k)return{algorithm:k,secret:e.secret??_,...t};{if(void 0!==e.secret&&"string"!=typeof e.secret)throw new oe("For ES256, the secret option must be a string.");const r=e.secret??_;return{algorithm:k,privateKey:e.privateKey,secret:r,...t}}}(t))}async function K(e,t={}){const r=function(e={}){const t={iss:e.iss??v,aud:e.aud??R};if("HS256"===k)return{algorithm:k,secret:e.secret??_,...t};{if(void 0!==e.secret&&"string"!=typeof e.secret)throw new oe("For ES256, the secret option must be a string.");const r=e.secret??_;return{algorithm:k,publicKey:e.publicKey,secret:r,...t}}}(t);try{return await ue(e,r)}catch{return null}}async function W(e,t={},r=D){return V({sub:e,...t},{ttl:r})}async function j(e,t={}){const{data:r={},ttl:n=D}=t,o=await W(e,r,n),s={...C,maxAge:n};return{token:o,cookie:U(w,o,s),cookieName:w,maxAge:n}}return{...e,providerMap:b,basePath:r,cookieOptions:C,jwt:{ttl:D},onOAuthExchange:i,mapExternalProfile:a,onBeforeLinkAccount:c,onAfterLinkAccount:l,signJWT:V,verifyJWT:K,createSession:W,validateSession:async function(t){const r=await K(t);if(!r)return null;const n=await e.getUserAndAccounts(r.sub);if(!n)return null;const{user:o,accounts:s}=n,i=Boolean(o&&(o.role&&M.adminRoles.includes(o.role)||M.adminUserIds.length>0&&M.adminUserIds.includes(o.id)));return{user:o?{...o,isAdmin:i}:null,session:{id:t,...r},accounts:s}},issueSession:j,refreshSession:async function(t,r={}){let n,o;if("string"==typeof t)n=t,o="token";else{const e=N(t);if(!e.token||!e.source)return null;n=e.token,o=e.source}const s=await K(n);if(!s||!s.sub)return null;if(null!=r.threshold&&r.threshold>0&&r.threshold<1){const{iat:e}=s;if(e){if(Math.floor(Date.now()/1e3)-e<(r.ttl??D)*r.threshold)return null}}if(!await e.getUser(s.sub))return null;const{sub:i,iat:a,exp:c,iss:l,aud:d,nbf:u,jti:f,...h}=s;return{...await j(s.sub,{data:h,ttl:r.ttl}),source:o}},getAccessToken:async function(t,r){const n=b.get(r);if(!n)return null;const o=(await e.getAccounts(t)).find(e=>e.provider===r);if(!o||!o.accessToken)return null;const s=Math.floor(Date.now()/1e3);if(!("number"==typeof o.expiresAt&&o.expiresAt<=s))return{accessToken:o.accessToken,expiresAt:o.expiresAt??null};if(!o.refreshToken||!n.refreshAccessToken)return null;try{const r=await n.refreshAccessToken(o.refreshToken,{}),s={userId:t,provider:o.provider,providerAccountId:o.providerAccountId,accessToken:r.accessToken??o.accessToken,refreshToken:r.refreshToken??o.refreshToken,expiresAt:r.expiresAt??null,idToken:r.idToken??o.idToken??null,tokenType:r.tokenType??o.tokenType??null,scope:r.scope??o.scope??null};return await(e.updateAccount?.(s)),{accessToken:s.accessToken,expiresAt:s.expiresAt}}catch{return null}},trustHosts:d,autoLink:f,allowDifferentEmails:h,profiles:H,updateUserInfoOnLink:p,sessionStrategy:x,development:!1,roles:M,cors:P,onError:T,errorRedirect:I,startImpersonation:async function(t,r,n={}){if(!F)throw new S(L.IMPERSONATION_DISABLED);const o=await e.getUser(t);if(!o)throw new S(L.USER_NOT_FOUND,`Admin user "${t}" not found`);const s=!!o.role&&F.allowedRoles.includes(o.role),i=M.adminUserIds.includes(t);if(!s&&!i)throw new S(L.IMPERSONATION_NOT_ALLOWED);const a=await e.getUser(r);if(!a)throw new S(L.USER_NOT_FOUND,`Target user "${r}" not found`);if(a.role&&F.cannotImpersonate.includes(a.role))throw new S(L.IMPERSONATION_TARGET_PROTECTED);F.onImpersonate&&await F.onImpersonate({adminUserId:t,targetUserId:r,reason:n.reason,timestamp:Date.now()});const c=Math.min(n.ttl??F.maxTTL,F.maxTTL),l=Math.floor(Date.now()/1e3)+c,d=await W(r,{impersonatedBy:t,impersonationExpiresAt:l},c),u={...C,maxAge:c},f=U(w,d,u),h=await V({adminUserId:t},{ttl:2*F.maxTTL});return{token:d,cookie:f,originalCookie:U(g,h,u),maxAge:c}},endImpersonation:async function(t){const r=t.headers.get("cookie");if(!r)return null;const n=y(r)[g];if(!n)return null;const o=await K(n);if(!o?.adminUserId)return null;if(!await e.getUser(o.adminUserId))return null;const s=await j(o.adminUserId),i=U(g,"",{...C,expires:new Date(0),maxAge:0});return{token:s.token,cookie:s.cookie,clearCookies:[i]}},impersonation:F}}var v={CSRF_INVALID:"Invalid CSRF token",PKCE_MISSING:"Missing PKCE code verifier",PKCE_CHALLENGE_MISSING:"Missing PKCE challenge",OAUTH_CANCELLED:"Authentication was cancelled",PROVIDER_NOT_FOUND:"Provider not found",AUTHORIZATION_URL_FAILED:"Could not create authorization URL",USER_NOT_FOUND:"User not found",USER_CREATE_FAILED:"Failed to create user",ACCOUNT_ALREADY_LINKED:"Account already linked to another user",ACCOUNT_LINK_FAILED:"Failed to link account",ACCOUNT_NOT_LINKED:"Account not linked",CANNOT_UNLINK_LAST_ACCOUNT:"Cannot unlink the last account",EMAIL_ALREADY_EXISTS:"An account with this email already exists",EMAIL_MISMATCH:"Email mismatch between existing account and provider",LINKING_NOT_ALLOWED:"Linking not allowed",LINK_ONLY_PROVIDER:"Sign-in with this provider is disabled. Please link it to an existing account.",UNAUTHORIZED:"Unauthorized",FORBIDDEN:"Forbidden",SESSION_INVALID:"Invalid session",SESSION_VALIDATION_FAILED:"Failed to validate session",TOKEN_INVALID:"Invalid token",TOKEN_EXPIRED:"Token expired",CODE_VERIFIER_INVALID:"Invalid code verifier",NOT_FOUND:"Not found",METHOD_NOT_ALLOWED:"Method not allowed",INVALID_REQUEST:"Invalid request",INVALID_REDIRECT_URL:"Invalid redirect URL",UNTRUSTED_HOST:"Untrusted redirect host",UNKNOWN_PROFILE:"Unknown profile",INTERNAL_ERROR:"An unexpected error occurred",IMPERSONATION_DISABLED:"Impersonation is not enabled",IMPERSONATION_NOT_ALLOWED:"You are not allowed to impersonate users",IMPERSONATION_TARGET_PROTECTED:"Cannot impersonate users with protected roles"},L=Object.fromEntries(Object.keys(v).map(e=>[e,e])),R={CSRF_INVALID:403,UNAUTHORIZED:401,FORBIDDEN:403,NOT_FOUND:404,METHOD_NOT_ALLOWED:405,INTERNAL_ERROR:500,USER_CREATE_FAILED:500,ACCOUNT_LINK_FAILED:500,AUTHORIZATION_URL_FAILED:500,SESSION_VALIDATION_FAILED:500,ACCOUNT_ALREADY_LINKED:409,EMAIL_ALREADY_EXISTS:409,LINKING_NOT_ALLOWED:403,IMPERSONATION_DISABLED:403,IMPERSONATION_NOT_ALLOWED:403,IMPERSONATION_TARGET_PROTECTED:403},S=class extends Error{code;status;redirectUrl;cause;constructor(e,t,r){const n="object"==typeof t?t:r??{};super("string"==typeof t?t:v[e]),this.name="GauError",this.code=e,this.status=n.status??R[e]??400,this.redirectUrl=n.redirectUrl,this.cause=n.cause}toJSON(){return{error:this.message,code:this.code,...this.redirectUrl&&{redirectUrl:this.redirectUrl}}}};function D(e,t){const r=new URL(e,"http://placeholder");return r.searchParams.set("code",t.code),r.searchParams.set("message",t.message),r.searchParams.set("status",String(t.status)),t.redirectUrl&&r.searchParams.set("redirect",t.redirectUrl),r.pathname+r.search}function C(e,t){if("GET"!==e.method)return!1;const r=new URL(e.url).pathname.substring(t.length).split("/").filter(Boolean);return(1!==r.length||"session"!==r[0])&&(1===r.length||2===r.length&&("callback"===r[0]||"link"===r[0]))}async function x(e,t){const{error:r,request:n}=e;if(t.onError)try{const r=await t.onError(e);if(r)return r}catch(e){console.error("onError handler threw:",e)}const o=C(n,t.basePath);if(t.errorRedirect&&o){const e=D(t.errorRedirect,r);return new Response(null,{status:302,headers:{Location:e}})}if(o){const{renderErrorPage:e,htmlResponse:t}=await import("./templates-5FGVYTQS.js");return t(e({title:"Authentication Error",message:r.message,code:r.code,redirectUrl:r.redirectUrl}),r.status)}return new Response(JSON.stringify(r.toJSON()),{status:r.status,headers:{"Content-Type":"application/json; charset=utf-8"}})}async function b(e,t){if(e&&"function"==typeof e.onAfterLinkAccount)try{await e.onAfterLinkAccount(t)}catch(e){console.error("onAfterLinkAccount hook error:",e)}}function P(e,t){return t.toHeaders().forEach((t,r)=>e.headers.append(r,t)),e}function H(e,t,r={}){e.delete(p),e.delete(E),t&&e.delete(T),e.delete(I),r.clientChallenge&&e.delete(O)}function M(e){try{return atob(e??"")||"/"}catch{return"/"}}function F(e){return e&&e.includes(".")?M(e.split(".")[1]):"/"}function V(e,t){try{return e()}catch{return t}}function K(e,t,r={}){return{accessToken:r.requireAccessToken?e.accessToken():V(()=>e.accessToken()??t?.accessToken??null,t?.accessToken??null),refreshToken:V(()=>e.refreshToken(),t?.refreshToken??null),expiresAt:V(()=>{const r=e.accessTokenExpiresAt();return r?Math.floor(r.getTime()/1e3):t?.expiresAt??void 0},t?.expiresAt??void 0),tokenType:V(()=>e.tokenType?.()??t?.tokenType??null,t?.tokenType??null),scope:V(()=>e.scopes()?.join(" ")??t?.scope??null,t?.scope??null),idToken:V(()=>e.idToken(),t?.idToken??null)}}async function W(n,o,s){const i=o.providerMap.get(s);if(!i)throw new S(L.PROVIDER_NOT_FOUND);const a=new URL(n.url),c=a.searchParams.get("code"),l=a.searchParams.get("state"),d=a.searchParams.get("error");if(!c||!l||d)return e(t({redirectUrl:F(l)}));const u=f(n.headers.get("Cookie")),g=new h(u,o.cookieOptions),{savedState:A,redirectTo:k}=function(e){if(!e.includes("."))return{savedState:e,redirectTo:"/"};const[t=e,r]=e.split(".");return{savedState:t,redirectTo:M(r)}}(l),y=g.get(p);if(!y||y!==A)throw new S(L.CSRF_INVALID,{redirectUrl:k});const U=g.get(E);if(!U)throw new S(L.PKCE_MISSING,{redirectUrl:k});const N=g.get(T),_=g.get(I);let v;if(_)try{const e=atob(_),t=JSON.parse(e);v=t?.overrides}catch{}const R=g.get(m);R&&g.delete(m);const{isLinking:D,session:C}=await async function(e,t){return t?{isLinking:!0,session:await e.validateSession(t)}:{isLinking:!1,session:null}}(o,R??void 0);if(D&&!C)return H(g,N,{clientChallenge:!0}),P(ie(k),g);const{user:x,tokens:V}=await i.validateCallback(c,U,N??void 0,v);{const e=await async function(e,t){if(!e||"function"!=typeof e.onOAuthExchange)return{handled:!1};try{const r=await e.onOAuthExchange(t);return r&&"object"==typeof r?r:{handled:!1}}catch(e){return console.error("onOAuthExchange hook error:",e),{handled:!1}}}(o,{request:n,providerId:s,state:l,code:c,codeVerifier:U,callbackUri:N,redirectTo:k,cookies:g,providerUser:x,tokens:V,isLinking:D,sessionUserId:C?.user?.id});if(e.handled)return H(g,N,{clientChallenge:!0}),P(e.response,g)}const W=await async function(e,t){if(!e||"function"!=typeof e.mapExternalProfile)return t.providerUser;try{const r=await e.mapExternalProfile(t);return r?{...t.providerUser,...r}:t.providerUser}catch(e){return console.error("mapExternalProfile hook error:",e),t.providerUser}}(o,{request:n,providerId:s,providerUser:x,tokens:V,isLinking:D});if(!D&&!0===o.providerMap.get(s)?.linkOnly)throw H(g,N),new S(L.LINK_ONLY_PROVIDER,{redirectUrl:k});let j=null;const B=await o.getUserByAccount(s,W.id);if(D){if(j=C.user,!j)throw new S(L.USER_NOT_FOUND,{redirectUrl:k});if(B&&B.id!==j.id)throw new S(L.ACCOUNT_ALREADY_LINKED,{redirectUrl:k});if(!1===o.allowDifferentEmails){const e=j.email,t=W.email;if(e&&t&&e!==t)throw new S(L.EMAIL_MISMATCH,{redirectUrl:k})}if(j){const e={id:j.id};let t=!1;if(o.updateUserInfoOnLink?(W.name&&W.name!==j.name&&(e.name=W.name,t=!0),W.avatar&&W.avatar!==j.image&&(e.image=W.avatar,t=!0)):(!j.name&&W.name&&(e.name=W.name,t=!0),!j.image&&W.avatar&&(e.image=W.avatar,t=!0)),j.email&&W.email&&j.email===W.email&&!0===W.emailVerified&&(!j.emailVerified||o.updateUserInfoOnLink)&&(e.emailVerified=!0,t=!0),t)try{j=await o.updateUser(e)}catch(e){console.error("Failed to update user info on link:",e)}}}else j=B;if(!j){const e=o.autoLink??"verifiedEmail";if(W.email&&("always"===e||"verifiedEmail"===e&&!0===W.emailVerified)){const e=await o.getUserByEmail(W.email);e&&(j=W.emailVerified&&!e.emailVerified?await o.updateUser({id:e.id,emailVerified:!0}):e)}if(!j)try{if(W.email&&!0===W.emailVerified&&!1===o.autoLink){if(await o.getUserByEmail(W.email))throw new S(L.EMAIL_ALREADY_EXISTS,{redirectUrl:k})}let e;try{e=o.roles.resolveOnCreate?.({providerId:s,profile:W,request:n})}catch(e){console.error("roles.resolveOnCreate threw:",e)}const t=!0===W.emailVerified?W.email:null;j=await o.createUser({name:W.name,email:t,image:W.avatar,emailVerified:W.emailVerified,role:e??o.roles.defaultRole})}catch(e){if(e instanceof S)throw e;throw console.error("Failed to create user:",e),new S(L.USER_CREATE_FAILED,{cause:e,redirectUrl:k})}}if(j&&W.email){const{email:e,emailVerified:t}=j,{email:r,emailVerified:n}=W,s={id:j.id};let i=!1;if(e||!0!==n)e!==r||!0!==n||t||(s.emailVerified=!0,i=!0);else{const e=await o.getUserByEmail(r);e&&e.id!==j.id||(s.email=r,s.emailVerified=!0,i=!0)}if(i)try{j=await o.updateUser(s)}catch(e){console.error("Failed to update user after sign-in:",e)}}if(B)try{const e=(await o.getAccounts(j.id)).find(e=>e.provider===s&&e.providerAccountId===W.id);if(e&&o.updateAccount){const t=K(V,{accessToken:e.accessToken??null,refreshToken:e.refreshToken??null,expiresAt:e.expiresAt??void 0,tokenType:e.tokenType??null,scope:e.scope??null,idToken:e.idToken??null});await o.updateAccount({userId:j.id,provider:s,providerAccountId:W.id,accessToken:t.accessToken??void 0,refreshToken:t.refreshToken,expiresAt:t.expiresAt,tokenType:t.tokenType,scope:t.scope,idToken:t.idToken}),await b(o,{request:n,providerId:s,userId:j.id,providerUser:W,tokens:V,action:"update"})}}catch(e){console.error("Failed to update account tokens on sign-in:",e)}else{{const e=await async function(e,t){if(!e||"function"!=typeof e.onBeforeLinkAccount)return{allow:!0};try{return await e.onBeforeLinkAccount(t)||{allow:!0}}catch(e){return console.error("onBeforeLinkAccount hook error:",e),{allow:!0}}}(o,{request:n,providerId:s,userId:j.id,providerUser:W,tokens:V});if(!1===e.allow){const t=e.response??(()=>{throw new S(L.LINKING_NOT_ALLOWED,{redirectUrl:k})})();return H(g,N,{clientChallenge:!0}),P(t,g)}}try{const e=K(V,void 0,{requireAccessToken:!0});await o.linkAccount({userId:j.id,provider:s,providerAccountId:W.id,accessToken:e.accessToken,refreshToken:e.refreshToken,expiresAt:e.expiresAt,tokenType:e.tokenType,scope:e.scope,idToken:e.idToken}),await b(o,{request:n,providerId:s,userId:j.id,providerUser:W,tokens:V,action:"link"})}catch(e){throw console.error("Error linking account:",e),new S(L.ACCOUNT_LINK_FAILED,{cause:e,redirectUrl:k})}}const J=await o.createSession(j.id);return async function(t,n,o,s,i,a,c,l){const d=new URL(t.url),u=new URL(s,t.url),f="token"===n.sessionStrategy,h="cookie"===n.sessionStrategy,p="http:"!==u.protocol&&"https:"!==u.protocol,g=d.host!==u.host;if(f||!h&&(p||g)){const t=new URL(u),i=c.get(O);if(!i)throw new S(L.PKCE_CHALLENGE_MISSING,{redirectUrl:s});const a=await n.signJWT({sub:o.id,challenge:i},{ttl:60});return t.searchParams.set("code",a),H(c,l,{clientChallenge:!0}),P(e(r({redirectUrl:t.toString()})),c)}return c.set(w,i,{maxAge:n.jwt.ttl,sameSite:n.development?"lax":"none",secure:!n.development}),H(c,l),P("false"===a.searchParams.get("redirect")?se({user:{...o,isAdmin:Boolean(o.role&&n.roles.adminRoles.includes(o.role)||n.roles.adminUserIds.includes(o.id)),accounts:await n.getAccounts(o.id)}}):ie(s),c)}(n,o,j,k,J,a,g,N)}function j(e,t){if(!1===t.cors)return!1;const r=t.cors;if("all"===r.allowedOrigins)return!0;if("trust"===r.allowedOrigins){if("all"===t.trustHosts)return!0;try{const r=new URL(e);return t.trustHosts.includes(r.host)||t.trustHosts.includes(r.hostname)}catch{return!1}}if(r.allowedOrigins.includes("*"))return!0;try{const t=new URL(e);return r.allowedOrigins.includes(e)||r.allowedOrigins.includes(t.origin)||r.allowedOrigins.includes(t.host)||r.allowedOrigins.includes(t.hostname)}catch{return r.allowedOrigins.includes(e)}}function B(e,t,r){if(!1===r.cors)return t;const n=e.headers.get("Origin")||e.headers.get("origin");if(!n)return t;if(!j(n,r))return t;const o=r.cors;t.headers.set("Vary","Origin");const s=o.allowCredentials,i="all"!==o.allowedOrigins||s?n:"*";return t.headers.set("Access-Control-Allow-Origin",i),s&&t.headers.set("Access-Control-Allow-Credentials","true"),t.headers.set("Access-Control-Allow-Headers",o.allowedHeaders.join(", ")),t.headers.set("Access-Control-Allow-Methods",o.allowedMethods.join(", ")),o.exposeHeaders?.length&&t.headers.set("Access-Control-Expose-Headers",o.exposeHeaders.join(", ")),t}function J(e,t){if(!1===t.cors)return new Response(null,{status:204});const r=e.headers.get("Origin")||e.headers.get("origin"),n=t.cors,o={};if(r&&j(r,t)){const e=n.allowCredentials,t="all"!==n.allowedOrigins||e?r:"*";o["Access-Control-Allow-Origin"]=t,e&&(o["Access-Control-Allow-Credentials"]="true")}return o["Access-Control-Allow-Headers"]=n.allowedHeaders.join(", "),o["Access-Control-Allow-Methods"]=n.allowedMethods.join(", "),null!=n.maxAge&&(o["Access-Control-Max-Age"]=String(n.maxAge)),n.exposeHeaders?.length&&(o["Access-Control-Expose-Headers"]=n.exposeHeaders.join(", ")),new Response(null,{status:204,headers:o})}function q(e,t,r){if("all"===t)return!0;const n=e.headers.get("origin");if(!n)return!1;let o;try{o=new URL(n).host}catch{return!1}if(r){if(o.startsWith("localhost")||o.startsWith("127.0.0.1"))return!0}const s=new URL(e.url),i=s.host;return n===`${s.protocol}//${i}`||t.includes(o)}async function G(e,t,r,o){const s=t.providerMap.get(r);if(!s)throw new S(L.PROVIDER_NOT_FOUND);const{state:i,codeVerifier:a}=n(),c=new URL(e.url),l=c.searchParams.get("redirectTo"),d=c.searchParams.get("profile"),u=c.searchParams.get("prompt");if(l){let r;try{if(l.startsWith("//"))throw new Error("Protocol-relative URL not allowed");r=new URL(l,c.origin)}catch{throw new S(L.INVALID_REDIRECT_URL,'Invalid "redirectTo" URL',{status:400})}const n=r.host,o=n===new URL(e.url).host,s="all"===t.trustHosts||t.trustHosts.includes(n);if(("http:"===r.protocol||"https:"===r.protocol)&&!o&&!s)throw new S(L.UNTRUSTED_HOST)}const w=l?`${i}.${btoa(l)}`:i;let g,A,k,y,U=c.searchParams.get("callbackUri");if(!U&&s.requiresRedirectUri&&(U=`${c.origin}${t.basePath}/callback/${r}`),d){const e=(t.profiles?.[r]??{})[d];if(!e)throw new S(L.UNKNOWN_PROFILE,`Unknown profile "${d}" for provider "${r}"`,{status:400});e.redirectUri&&(U=e.redirectUri),e.scopes&&(g=e.scopes),e.params&&(A={...e.params??{}});const{tenant:n,prompt:s}=e;if(null==n&&null==s||(k={...k??{},tenant:n,prompt:s}),!o&&!0===e.linkOnly)throw new S(L.LINK_ONLY_PROVIDER,"This profile is link-only. Please link it to an existing account.",{status:400})}if(u&&(A={...A??{},prompt:u}),!o&&!0===s.linkOnly)throw new S(L.LINK_ONLY_PROVIDER);try{y=await s.getAuthorizationUrl(w,a,{redirectUri:U??void 0,scopes:g,params:A,overrides:k})}catch(e){console.error("Error getting authorization URL:",e),y=null}if(!y)throw new S(L.AUTHORIZATION_URL_FAILED,"Could not create authorization URL",{status:500});const N=f(e.headers.get("Cookie")),_=new h(N,t.cookieOptions),v={maxAge:600,sameSite:t.development?"lax":"none",secure:!t.development};_.set(p,i,v),_.set(E,a,v),o?_.set(m,o,v):_.delete(m,{sameSite:t.development?"lax":"none",secure:!t.development}),U&&_.set(T,U,v);const R=JSON.stringify({params:A??{},overrides:k??{}});_.set(I,btoa(R),v);const D=c.searchParams.get("code_challenge");D&&_.set(O,D,v);if("false"===c.searchParams.get("redirect")){const e=se({url:y.toString()});return _.toHeaders().forEach((t,r)=>{e.headers.append(r,t)}),e}const C=ie(y.toString());return _.toHeaders().forEach((e,t)=>{C.headers.append(t,e)}),C}async function Y(e,t,r){const n=new URL(e.url);let o=N(e).token;if(o||(o=n.searchParams.get("token")??void 0),!o)throw new S(L.UNAUTHORIZED);if(!await t.validateSession(o))throw new S(L.UNAUTHORIZED);n.searchParams.delete("token");return G(new Request(n.toString(),e),t,r,o)}async function Z(e,t,r){const n=N(e).token;if(!n)throw new S(L.UNAUTHORIZED);const o=await t.validateSession(n);if(!o||!o.user)throw new S(L.UNAUTHORIZED);const s=o.accounts??[];if(s.length<=1)throw new S(L.CANNOT_UNLINK_LAST_ACCOUNT);const i=s.find(e=>e.provider===r);if(!i)throw new S(L.ACCOUNT_NOT_LINKED,`Provider "${r}" not linked`);await t.unlinkAccount(r,i.providerAccountId);if((await t.getAccounts(o.user.id)).length>0&&o.user.email)try{await t.updateUser({id:o.user.id,email:null,emailVerified:!1})}catch(e){console.error("Failed to clear stale email after unlinking:",e)}return se({message:"Account unlinked successfully"})}async function z(e,t,r){return G(e,t,r,null)}async function X(e,t){const r=f(e.headers.get("Cookie")),n=new h(r,t.cookieOptions);n.delete(w,{sameSite:t.development?"lax":"none",secure:!t.development}),n.delete(m,{sameSite:t.development?"lax":"none",secure:!t.development});const o=se({message:"Signed out"});return n.toHeaders().forEach((e,t)=>{o.headers.append(t,e)}),o}async function Q(e,t){const{token:r}=N(e),n=Array.from(t.providerMap.keys());if(!r)return se({...re,providers:n});try{const e=await t.validateSession(r);return e?se({...ne(e),providers:n}):se({...re,providers:n},{status:401})}catch(e){throw console.error("Error validating session:",e),new S(L.SESSION_VALIDATION_FAILED,{cause:e})}}async function ee(e,t){if("POST"!==e.method)throw new S(L.METHOD_NOT_ALLOWED);let r;try{r=await e.json()}catch{throw new S(L.INVALID_REQUEST,"Invalid JSON body",{status:400})}const{code:n,codeVerifier:o}=r;if(!n||!o)throw new S(L.INVALID_REQUEST,"Missing code or codeVerifier",{status:400});const s=await t.verifyJWT(n);if(!s)throw new S(L.TOKEN_EXPIRED,"Invalid or expired code");const{sub:i,challenge:a}=s,c=(new TextEncoder).encode(o),l=await crypto.subtle.digest("SHA-256",c),d=Array.from(new Uint8Array(l));if(a!==btoa(String.fromCharCode(...d)).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,""))throw new S(L.CODE_VERIFIER_INVALID);return se({token:await t.createSession(i)})}function te(e){const{basePath:t}=e;return async function(r){if("OPTIONS"===r.method)return J(r,e);const n=new URL(r.url);if(!n.pathname.startsWith(t)){const n=new S(L.NOT_FOUND);return B(r,await x({error:n,request:r},{basePath:t,onError:e.onError,errorRedirect:e.errorRedirect}),e)}try{if("POST"===r.method&&!q(r,e.trustHosts,e.development)){const t=r.headers.get("origin")??"unknown",n=e.development?`Untrusted origin: '${t}'. Add this origin to 'trustHosts' in createAuth() or ensure you are using 'localhost' or '127.0.0.1' for development.`:"Forbidden";throw new S(L.FORBIDDEN,n,{status:403})}const o=n.pathname.substring(t.length).split("/").filter(Boolean),s=o[0];if(!s)throw new S(L.NOT_FOUND);let i;if("GET"===r.method)if("session"===s)i=await Q(r,e);else if(2===o.length&&"link"===o[0])i=await Y(r,e,o[1]);else if(2===o.length&&"callback"===o[0])i=await W(r,e,o[1]);else{if(1!==o.length)throw new S(L.NOT_FOUND);i=await z(r,e,s)}else{if("POST"!==r.method)throw new S(L.METHOD_NOT_ALLOWED);if(1===o.length&&"signout"===s)i=await X(r,e);else if(1===o.length&&"token"===s)i=await ee(r,e);else{if(2!==o.length||"unlink"!==o[0])throw new S(L.NOT_FOUND);i=await Z(r,e,o[1])}}try{i.headers.set("Cache-Control","no-store, private"),i.headers.set("Pragma","no-cache"),i.headers.set("Expires","0")}catch{}return B(r,i,e)}catch(n){if(n instanceof S){return B(r,await x({error:n,request:r},{basePath:t,onError:e.onError,errorRedirect:e.errorRedirect}),e)}console.error("Unexpected error in gau handler:",n);const o=new S(L.INTERNAL_ERROR,{cause:n});return B(r,await x({error:o,request:r},{basePath:t,onError:e.onError,errorRedirect:e.errorRedirect}),e)}}}var re={user:null,session:null,accounts:null};function ne(e){const t=e.session&&(({id:e,...t})=>t)(e.session);return{user:e.user,session:t,accounts:e.accounts?.map(e=>({provider:e.provider,providerAccountId:e.providerAccountId}))??null,providers:e.providers}}var oe=class extends Error{cause;constructor(e,t){super(e),this.name="AuthError",this.cause=t}};function se(e,t={}){const r=new Headers(t.headers);return r.has("Content-Type")||r.set("Content-Type","application/json; charset=utf-8"),new Response(JSON.stringify(e),{...t,headers:r})}function ie(e,t=302){return new Response(null,{status:t,headers:{Location:e}})}var ae="X-Refreshed-Token";function ce(e){return null!=e?.impersonatedBy}async function le(e){try{const t=function(e){const t=e.replace(/-/g,"+").replace(/_/g,"/"),r=(4-t.length%4)%4,n=t.padEnd(t.length+r,"=");try{const e=atob(n),t=e.length,r=new Uint8Array(t);for(let n=0;n<t;n++)r[n]=e.charCodeAt(n);return r}catch{throw new oe("Invalid base64url string")}}(e),r=await crypto.subtle.importKey("pkcs8",t.slice(),{name:"ECDSA",namedCurve:"P-256"},!0,["sign"]),n=await crypto.subtle.exportKey("jwk",r);delete n.d,n.key_ops=["verify"];return{privateKey:r,publicKey:await crypto.subtle.importKey("jwk",n,{name:"ECDSA",namedCurve:"P-256"},!0,["verify"])}}catch(e){if(e instanceof oe)throw e;throw new oe("Invalid secret. Must be a base64url-encoded PKCS#8 private key for ES256. Use `bunx gau secret` to generate one.",e)}}async function de(e,t={}){let{algorithm:r="ES256",ttl:n,iss:i,aud:a,sub:c,privateKey:l,secret:d}=t;if("ES256"===r){if(!l){if("string"!=typeof d)throw new oe("Missing secret for ES256 signing. It must be a base64url-encoded string.");({privateKey:l}=await le(d))}}else if("HS256"===r&&!d)throw new oe("Missing secret for HS256 signing");const u=Math.floor(Date.now()/1e3),f={iat:u,iss:i,aud:a,sub:c,...e};null!=n&&n>0&&(f.exp=u+n);const h="HS256"===r,p=h?"HS256":"ES256",w=JSON.stringify({alg:p,typ:"JWT"}),g=JSON.stringify(f),A=o(w,g);let m;if(h){const e="string"==typeof d?(new TextEncoder).encode(d):d,t=await crypto.subtle.importKey("raw",e,{name:"HMAC",hash:"SHA-256"},!1,["sign"]);m=new Uint8Array(await crypto.subtle.sign("HMAC",t,A))}else m=new Uint8Array(await crypto.subtle.sign({name:"ECDSA",hash:"SHA-256"},l,A));return s(w,g,m)}async function ue(e,t){let{algorithm:r="ES256",publicKey:n,secret:o,iss:s,aud:l}=t;if("ES256"===r&&!n){if("string"!=typeof o)throw new oe("Missing secret for ES256 verification. Must be a base64url-encoded string.");({publicKey:n}=await le(o))}if("HS256"===r&&!o)throw new oe("Missing secret for HS256 verification");const[d,u,f,h]=c(e),p=new i(d).algorithm();let w=!1;if("HS256"===r){if("HS256"!==p)throw new Error(`JWT algorithm is "${p}", but verifier was configured for "HS256"`);const e="string"==typeof o?(new TextEncoder).encode(o):o,t=await crypto.subtle.importKey("raw",e,{name:"HMAC",hash:"SHA-256"},!1,["sign"]);w=function(e,t){let r=e.length^t.length;const n=Math.max(e.length,t.length);for(let o=0;o<n;o++)r|=(e[o]??0)^(t[o]??0);return 0===r}(new Uint8Array(await crypto.subtle.sign("HMAC",t,h)),new Uint8Array(f))}else{if("ES256"!==p)throw new oe(`JWT algorithm is "${p}", but verifier was configured for "ES256"`);const e=new Uint8Array(f);if(w=await crypto.subtle.verify({name:"ECDSA",hash:"SHA-256"},n,e,h),!w&&64===e.length)try{const t=function(e){if(64!==e.length)throw new Error("Invalid raw signature length");let t=e.slice(0,32),r=e.slice(32),n=0;for(;n<t.length-1&&0===t[n];)n++;t=t.slice(n);let o=0;for(;o<r.length-1&&0===r[o];)o++;if(r=r.slice(o),t.length>0&&128&t[0]){const e=new Uint8Array(t.length+1);e[0]=0,e.set(t,1),t=e}if(r.length>0&&128&r[0]){const e=new Uint8Array(r.length+1);e[0]=0,e.set(r,1),r=e}const s=t.length,i=r.length,a=2+s+2+i,c=new Uint8Array(2+a);return c[0]=48,c[1]=a,c[2]=2,c[3]=s,c.set(t,4),c[4+s]=2,c[5+s]=i,c.set(r,6+s),c}(e);w=await crypto.subtle.verify({name:"ECDSA",hash:"SHA-256"},n,t,h)}catch{w=!1}}if(!w)throw new oe("Invalid JWT signature");const g=new a(u);if(g.hasExpiration()&&!g.verifyExpiration())throw new oe("JWT expired");if(g.hasNotBefore()&&!g.verifyNotBefore())throw new oe("JWT not yet valid");if(s&&u.iss!==s)throw new oe("Invalid JWT issuer");if(l){const e=Array.isArray(l)?l:[l],t=u.aud?Array.isArray(u.aud)?u.aud:[u.aud]:[];if(!e.some(e=>t.includes(e)))throw new oe("Invalid JWT audience")}return u}export{u as DEFAULT_COOKIE_SERIALIZE_OPTIONS,f as parseCookies,h as Cookies,p as CSRF_COOKIE_NAME,w as SESSION_COOKIE_NAME,g as SESSION_STASH_COOKIE_NAME,A as SESSION_STRATEGY_COOKIE_NAME,m as LINKING_TOKEN_COOKIE_NAME,E as PKCE_COOKIE_NAME,T as CALLBACK_URI_COOKIE_NAME,I as PROVIDER_OPTIONS_COOKIE_NAME,O as CLIENT_CHALLENGE_COOKIE_NAME,k as CSRF_MAX_AGE,de as sign,ue as verify,N as getSessionTokenFromRequest,_ as createAuth,v as ErrorMessages,L as ErrorCodes,R as ErrorStatuses,S as GauError,D as createErrorRedirectUrl,C as isUserFacingRequest,x as handleError,W as handleCallback,B as applyCors,J as handlePreflight,q as verifyRequestOrigin,Y as handleLink,Z as handleUnlink,z as handleSignIn,X as handleSignOut,Q as handleSession,ee as handleToken,te as createHandler,re as NULL_SESSION,ne as toClientSession,oe as AuthError,se as json,ie as redirect,ae as REFRESHED_TOKEN_HEADER,ce as isImpersonating};//# sourceMappingURL=chunk-NHENQLYI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/jwt/jwt.ts","../src/core/cookies.ts","../src/core/createAuth.ts","../src/core/utils.ts","../src/core/errors.ts","../src/core/hooks.ts","../src/core/handlers/callback.ts","../src/core/handlers/cors.ts","../src/core/handlers/utils.ts","../src/core/handlers/link.ts","../src/core/handlers/login.ts","../src/core/handlers/session.ts","../src/core/handlers/token.ts","../src/core/handler.ts","../src/core/index.ts","../src/jwt/utils.ts"],"sourcesContent":["/// <reference types=\"node\" />\nimport {\n createJWTSignatureMessage,\n encodeJWT,\n JWSRegisteredHeaders,\n JWTRegisteredClaims,\n parseJWT,\n} from '@oslojs/jwt'\nimport { AuthError } from '../core/index'\nimport { constantTimeEqual, deriveKeysFromSecret, rawToDer } from './utils'\n\nexport type SupportedAlgorithm = 'ES256' | 'HS256'\n\ninterface CommonSignOptions {\n /** Time-to-live in seconds (exp claim). If omitted the token will not expire. */\n ttl?: number\n}\n\nexport type SignOptions\n = | ({ algorithm?: 'ES256', privateKey?: CryptoKey, secret?: string }\n & CommonSignOptions & { iss?: string, aud?: string | string[], sub?: string })\n | ({ algorithm: 'HS256', secret?: string | Uint8Array, privateKey?: never }\n & CommonSignOptions & { iss?: string, aud?: string | string[], sub?: string })\n\n/**\n * Create a signed JWT.\n * Defaults to ES256 when a privateKey is supplied. Falls back to HS256 when a secret is supplied.\n */\nexport async function sign<T extends Record<string, unknown>>(payload: T, options: SignOptions = {}): Promise<string> {\n let { algorithm = 'ES256', ttl, iss, aud, sub, privateKey, secret } = options\n\n if (algorithm === 'ES256') {\n if (!privateKey) {\n if (typeof secret !== 'string')\n throw new AuthError('Missing secret for ES256 signing. It must be a base64url-encoded string.');\n\n ({ privateKey } = await deriveKeysFromSecret(secret))\n }\n }\n else if (algorithm === 'HS256' && !secret) {\n throw new AuthError('Missing secret for HS256 signing')\n }\n\n const now = Math.floor(Date.now() / 1000)\n\n const jwtPayload: Record<string, unknown> = { iat: now, iss, aud, sub, ...payload }\n\n if (ttl != null && ttl > 0)\n jwtPayload.exp = now + ttl\n\n const isHS256 = algorithm === 'HS256'\n const alg: SupportedAlgorithm = isHS256 ? 'HS256' : 'ES256'\n\n const headerJSON = JSON.stringify({ alg, typ: 'JWT' })\n const payloadJSON = JSON.stringify(jwtPayload)\n\n const signatureMessage = createJWTSignatureMessage(headerJSON, payloadJSON)\n\n let signature: Uint8Array\n\n if (isHS256) {\n // HS256 (HMAC-SHA256)\n const secretBytes = typeof secret === 'string'\n ? new TextEncoder().encode(secret)\n : secret\n\n const cryptoKey = await crypto.subtle.importKey(\n 'raw',\n secretBytes as BufferSource,\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign'],\n )\n\n signature = new Uint8Array(await crypto.subtle.sign('HMAC', cryptoKey, signatureMessage as BufferSource))\n }\n else {\n // ES256 (ECDSA-SHA256)\n // Runtimes like Bun's return the raw (r||s) signature directly, not DER-encoded.\n signature = new Uint8Array(\n await crypto.subtle.sign(\n { name: 'ECDSA', hash: 'SHA-256' },\n privateKey!,\n signatureMessage as BufferSource,\n ),\n )\n }\n\n return encodeJWT(headerJSON, payloadJSON, signature)\n}\n\nexport type VerifyOptions\n = | { algorithm?: 'ES256', publicKey?: CryptoKey, secret?: string, iss?: string, aud?: string | string[] }\n | { algorithm: 'HS256', secret?: string | Uint8Array, publicKey?: never, iss?: string, aud?: string | string[] }\n\n/**\n * Verify a JWT and return its payload when the signature is valid.\n * The algorithm is inferred from options – ES256 by default.\n * Throws when verification fails or the token is expired.\n */\nexport async function verify<T = Record<string, unknown>>(token: string, options: VerifyOptions): Promise<T> {\n let { algorithm = 'ES256', publicKey, secret, iss, aud } = options\n\n if (algorithm === 'ES256') {\n if (!publicKey) {\n if (typeof secret !== 'string')\n throw new AuthError('Missing secret for ES256 verification. Must be a base64url-encoded string.');\n\n ({ publicKey } = await deriveKeysFromSecret(secret))\n }\n }\n\n if (algorithm === 'HS256' && !secret)\n throw new AuthError('Missing secret for HS256 verification')\n\n const [header, payload, signature, signatureMessage] = parseJWT(token)\n\n const headerParams = new JWSRegisteredHeaders(header)\n const headerAlg = headerParams.algorithm()\n\n let validSignature = false\n\n // HS256 verification path\n if (algorithm === 'HS256') {\n if (headerAlg !== 'HS256')\n throw new Error(`JWT algorithm is \"${headerAlg}\", but verifier was configured for \"HS256\"`)\n\n const secretBytes = typeof secret === 'string'\n ? new TextEncoder().encode(secret)\n : secret\n\n const cryptoKey = await crypto.subtle.importKey(\n 'raw',\n secretBytes as BufferSource,\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign'],\n )\n\n const expectedSig = new Uint8Array(await crypto.subtle.sign('HMAC', cryptoKey, signatureMessage as BufferSource))\n validSignature = constantTimeEqual(expectedSig, new Uint8Array(signature))\n }\n // ES256 verification path (default)\n else {\n if (headerAlg !== 'ES256')\n throw new AuthError(`JWT algorithm is \"${headerAlg}\", but verifier was configured for \"ES256\"`)\n\n const signatureBytes = new Uint8Array(signature)\n\n // Runtimes like Node.js return DER-encoded signatures. Others (Bun) return raw (r||s).\n // We try DER first, as it's more common in Node environments.\n validSignature = await crypto.subtle.verify(\n { name: 'ECDSA', hash: 'SHA-256' },\n publicKey!,\n signatureBytes as BufferSource,\n signatureMessage as BufferSource,\n )\n\n if (!validSignature && signatureBytes.length === 64) {\n // If DER verification fails and the signature is 64 bytes, it might be a raw signature.\n // Convert it to DER and try again.\n try {\n const derSig = rawToDer(signatureBytes)\n validSignature = await crypto.subtle.verify(\n { name: 'ECDSA', hash: 'SHA-256' },\n publicKey!,\n derSig as BufferSource,\n signatureMessage as BufferSource,\n )\n }\n catch {\n // rawToDer can throw if the signature is not 64 bytes, but we already checked.\n // This catch is for other unexpected errors.\n validSignature = false\n }\n }\n }\n\n if (!validSignature)\n throw new AuthError('Invalid JWT signature')\n\n const claims = new JWTRegisteredClaims(payload)\n if (claims.hasExpiration() && !claims.verifyExpiration())\n throw new AuthError('JWT expired')\n if (claims.hasNotBefore() && !claims.verifyNotBefore())\n throw new AuthError('JWT not yet valid')\n if (iss && (payload as any).iss !== iss)\n throw new AuthError('Invalid JWT issuer')\n\n if (aud) {\n const expectedAudience = Array.isArray(aud) ? aud : [aud]\n const tokenAudience = (payload as any).aud\n ? (Array.isArray((payload as any).aud) ? (payload as any).aud : [(payload as any).aud])\n : []\n\n if (!expectedAudience.some(audValue => tokenAudience.includes(audValue)))\n throw new AuthError('Invalid JWT audience')\n }\n\n return payload as T\n}\n","import type { SerializeOptions } from 'cookie'\nimport { parse, serialize } from 'cookie'\n\nexport const DEFAULT_COOKIE_SERIALIZE_OPTIONS: SerializeOptions = {\n path: '/',\n sameSite: 'lax',\n secure: true,\n httpOnly: true,\n}\n\nexport type Cookie = [string, string, SerializeOptions]\n\nexport function parseCookies(cookieHeader: string | null | undefined): Map<string, string> {\n const cookies = new Map<string, string>()\n if (cookieHeader) {\n const parsed = parse(cookieHeader)\n for (const name in parsed)\n cookies.set(name, parsed[name]!)\n }\n return cookies\n}\n\nexport class Cookies {\n #new: Cookie[] = []\n\n constructor(\n private readonly requestCookies: Map<string, string>,\n private readonly defaultOptions: SerializeOptions,\n ) {}\n\n get(name: string): string | undefined {\n return this.requestCookies.get(name)\n }\n\n set(name: string, value: string, options?: SerializeOptions): void {\n const combinedOptions = { ...this.defaultOptions, ...options }\n this.#new.push([name, value, combinedOptions])\n }\n\n delete(name: string, options?: Omit<SerializeOptions, 'expires' | 'maxAge'>): void {\n this.set(name, '', { ...options, expires: new Date(0), maxAge: 0 })\n }\n\n toHeaders(): Headers {\n const headers = new Headers()\n for (const [name, value, options] of this.#new)\n headers.append('Set-Cookie', serialize(name, value, options))\n\n return headers\n }\n}\n\nexport const CSRF_COOKIE_NAME = '__gau-csrf-token'\nexport const SESSION_COOKIE_NAME = '__gau-session-token'\nexport const SESSION_STASH_COOKIE_NAME = '__gau-session-stash'\nexport const SESSION_STRATEGY_COOKIE_NAME = '__gau-session-strategy'\nexport const LINKING_TOKEN_COOKIE_NAME = '__gau-linking-token'\nexport const PKCE_COOKIE_NAME = '__gau-pkce-code-verifier'\nexport const CALLBACK_URI_COOKIE_NAME = '__gau-callback-uri'\nexport const PROVIDER_OPTIONS_COOKIE_NAME = '__gau-provider-options'\nexport const CLIENT_CHALLENGE_COOKIE_NAME = '__gau-client-challenge'\n\nexport const CSRF_MAX_AGE = 60 * 10 // 10 minutes\n","import type { OAuth2Tokens } from 'arctic'\nimport type { SerializeOptions } from 'cookie'\nimport type { SignOptions, VerifyOptions } from '../jwt'\nimport type { AuthUser, OAuthProvider, OAuthProviderConfig, ProviderProfileOverrides } from '../oauth'\nimport type { Cookies } from './cookies'\nimport type { Adapter, GauServerSession } from './index'\nimport { parse, serialize } from 'cookie'\nimport { sign, verify } from '../jwt'\nimport { DEFAULT_COOKIE_SERIALIZE_OPTIONS, SESSION_COOKIE_NAME, SESSION_STASH_COOKIE_NAME } from './cookies'\nimport { AuthError, ErrorCodes, GauError } from './index'\nimport { getSessionTokenFromRequest } from './utils'\n\ntype ProviderId<P> = P extends OAuthProvider<infer T> ? T : never\nexport type ProviderIds<T> = T extends { providerMap: Map<infer K extends string, any> } ? K : string\n\nexport type ProfileName<T, P extends string> = T extends { profiles: infer R }\n ? P extends keyof R\n ? keyof R[P]\n : never\n : never\n\nexport interface ImpersonationConfig {\n enabled: boolean\n /** Roles that can impersonate others. Defaults to adminRoles from roles config. */\n allowedRoles?: string[]\n /** Roles that cannot be impersonated. Defaults to adminRoles from roles config. */\n cannotImpersonate?: string[]\n /** Maximum impersonation duration in seconds. Defaults to 3600 (1 hour). */\n maxTTL?: number\n /**\n * Hook called when impersonation starts.\n * Use this to log impersonation events.\n */\n onImpersonate?: (context: {\n adminUserId: string\n targetUserId: string\n reason?: string\n timestamp: number\n }) => void | Promise<void>\n}\n\ntype ResolvedImpersonationConfig = Required<Pick<ImpersonationConfig, 'enabled' | 'allowedRoles' | 'cannotImpersonate' | 'maxTTL'>> & Pick<ImpersonationConfig, 'onImpersonate'>\n\nexport interface StartImpersonationOptions {\n /** Session duration in seconds (capped by maxTTL). */\n ttl?: number\n /** Reason for impersonation, passed to onImpersonate hook. */\n reason?: string\n}\n\nexport interface ImpersonationResult {\n /** The impersonation session JWT. */\n token: string\n /** Set-Cookie header for the impersonation session. */\n cookie: string\n /** Set-Cookie header for stashing the admin's original session. */\n originalCookie: string\n /** The maxAge in seconds. */\n maxAge: number\n}\n\nexport interface EndImpersonationResult {\n /** The restored admin session token. */\n token: string\n /** Set-Cookie header for restoring the admin session. */\n cookie: string\n /** Array of Set-Cookie headers to clear the stash cookie. */\n clearCookies: string[]\n}\n\nexport interface CreateAuthOptions<TProviders extends OAuthProvider[]> {\n /** The database adapter to use for storing users and accounts. */\n adapter: Adapter\n /** Array of OAuth providers to support. */\n providers: TProviders\n /** Base path for authentication routes (defaults to '/api/auth'). */\n basePath?: string\n /** Session management options */\n session?: {\n /** Strategy to use for sessions: 'auto' (default), 'cookie', or 'token'. */\n strategy?: 'auto' | 'cookie' | 'token'\n }\n /** Configuration for JWT signing and verification. */\n jwt?: {\n /** Signing algorithm: 'ES256' (default) or 'HS256'. */\n algorithm?: 'ES256' | 'HS256'\n /** Secret for HS256 or base64url-encoded private key for ES256 (overrides AUTH_SECRET). */\n secret?: string\n /** Issuer claim (iss) for JWTs. */\n iss?: string\n /** Audience claim (aud) for JWTs. */\n aud?: string\n /** Default time-to-live in seconds for JWTs (defaults to 1 day). */\n ttl?: number\n }\n /** Custom options for session cookies. */\n cookies?: Partial<SerializeOptions>\n /**\n * Hook that fires right after provider.validateCallback() returns tokens,\n * but before any user lookup/link/create logic. Return { handled: true, response }\n * to short-circuit the default flow and send a custom response.\n */\n onOAuthExchange?: (context: {\n request: Request\n providerId: string\n state: string\n code: string\n codeVerifier: string\n callbackUri?: string | null\n redirectTo: string\n cookies: Cookies\n providerUser: AuthUser\n tokens: OAuth2Tokens\n isLinking: boolean\n sessionUserId?: string\n }) => Promise<{ handled: true, response: Response } | { handled: false }>\n /** Map/override the provider's profile right after token exchange. */\n mapExternalProfile?: (context: {\n request: Request\n providerId: string\n providerUser: AuthUser\n tokens: OAuth2Tokens\n isLinking: boolean\n }) => Promise<AuthUser | Partial<AuthUser> | null | undefined>\n /** Gate the link action just before persisting an account. */\n onBeforeLinkAccount?: (context: {\n request: Request\n providerId: string\n userId: string\n providerUser: AuthUser\n tokens: OAuth2Tokens\n }) => Promise<{ allow: true } | { allow: false, response?: Response }>\n /** Observe or augment after link/update tokens. */\n onAfterLinkAccount?: (context: {\n request: Request\n providerId: string\n userId: string\n providerUser: AuthUser\n tokens: OAuth2Tokens\n action: 'link' | 'update'\n }) => Promise<void>\n /** Trusted hosts for CSRF protection: 'all' or array of hostnames (defaults to []). */\n trustHosts?: 'all' | string[]\n /** Account linking behavior: 'verifiedEmail' (default), 'always', or false. */\n autoLink?: 'verifiedEmail' | 'always' | false\n /** Allow linking providers whose primary emails differ from the user's current primary email. Defaults to true. */\n allowDifferentEmails?: boolean\n /** When linking a new provider, update missing user info (name/image/emailVerified) from provider profile. Defaults to false. */\n updateUserInfoOnLink?: boolean\n /** Optional configuration for role-based access control. */\n roles?: {\n /** Default role for newly created users. */\n defaultRole?: string\n /** Dynamically resolve the role at the moment of user creation. Return undefined to fall back to defaultRole. */\n resolveOnCreate?: (context: { providerId: string, profile: any, request: Request }) => string | undefined\n /** Roles that are considered admin-like for helper predicates and `session.user.isAdmin`. */\n adminRoles?: string[]\n /** Users that are always treated as admin for helper predicates and `session.user.isAdmin`. */\n adminUserIds?: string[]\n }\n /**\n * CORS configuration. When true (default): request Origin & allow credentials\n * When false, CORS headers are not added at all.\n * Provide an object to fine-tune behaviour.\n */\n cors?: true | false | {\n /**\n * Allowed origins.\n * - 'all' (default) allows any origin (reflected when credentials enabled),\n * - 'trust' reuses the createAuth trustHosts list\n * - specify an explicit array of full origins (e.g. https://app.example.com)\n * or hostnames (e.g. app.example.com).\n * When array contains '*', it's treated as 'all'.\n */\n allowedOrigins?: 'all' | 'trust' | string[]\n /** Whether to send Access-Control-Allow-Credentials (defaults to true). */\n allowCredentials?: boolean\n /** Allowed headers (defaults to ['Content-Type','Authorization','Cookie']). */\n allowedHeaders?: string[]\n /** Allowed methods (defaults to ['GET','POST','OPTIONS']). */\n allowedMethods?: string[]\n /** Exposed headers (optional). */\n exposeHeaders?: string[]\n /** Preflight max age in seconds (optional). */\n maxAge?: number\n }\n /**\n * Named, server-defined profiles that group provider specific settings.\n * Clients can reference a profile by name (e.g. signIn('github', { profile: 'myprofile' })).\n */\n profiles?: ProfilesConfig<TProviders>\n /**\n * Custom error handler. Return a Response to override default behavior.\n * Return undefined to use default handling (errorRedirect or HTML page).\n *\n * @example\n * onError: ({ error, request }) => {\n * console.error('Auth error:', error.code, error.message)\n * if (error.code === 'CSRF_INVALID') {\n * return redirect('/login?error=session_expired')\n * }\n * }\n */\n onError?: (context: {\n error: GauError\n request: Request\n }) => Response | Promise<Response | undefined> | undefined\n /**\n * URL to redirect user-facing errors to.\n * Error details passed as query params: ?code=...&message=...&status=...&redirect=...\n *\n * If not set, gau renders its built-in error page for user-facing errors,\n * or returns JSON for API errors.\n *\n * @example\n * errorRedirect: '/auth/error' // Your custom error page\n */\n errorRedirect?: string\n /**\n * User impersonation.\n * When enabled, admins can impersonate other users for support/debugging.\n */\n impersonation?: ImpersonationConfig\n}\n\nexport interface IssueSessionOptions {\n /** Custom claims to include in the session JWT. */\n data?: Record<string, unknown>\n /** Time-to-live in seconds (defaults to auth's configured jwt.ttl). */\n ttl?: number\n}\n\nexport interface IssueSessionResult {\n /** The raw JWT session token (for Bearer auth or storage). */\n token: string\n /** The serialized Set-Cookie header value (for web apps). */\n cookie: string\n /** The cookie name used by gau. */\n cookieName: string\n /** The maxAge in seconds. */\n maxAge: number\n}\n\nexport interface RefreshSessionOptions {\n /** Override the default TTL for the new token. */\n ttl?: number\n /**\n * Only refresh if past this fraction of TTL (0-1).\n * Example: 0.5 means only refresh if session is past 50% of its lifetime.\n */\n threshold?: number\n}\n\nexport interface RefreshSessionResult extends IssueSessionResult {\n /**\n * How the original token was provided.\n * - 'cookie': Token was extracted from the Cookie header\n * - 'bearer': Token was extracted from Authorization: Bearer header\n * - 'token': A raw token string was passed directly\n */\n source: 'cookie' | 'bearer' | 'token'\n}\n\nexport type Auth<TProviders extends OAuthProvider[] = any> = Adapter & {\n providerMap: Map<ProviderId<TProviders[number]>, TProviders[number]>\n basePath: string\n cookieOptions: SerializeOptions\n jwt: { ttl: number }\n onOAuthExchange?: CreateAuthOptions<TProviders>['onOAuthExchange']\n mapExternalProfile?: CreateAuthOptions<TProviders>['mapExternalProfile']\n onBeforeLinkAccount?: CreateAuthOptions<TProviders>['onBeforeLinkAccount']\n onAfterLinkAccount?: CreateAuthOptions<TProviders>['onAfterLinkAccount']\n signJWT: <U extends Record<string, unknown>>(payload: U, customOptions?: Partial<SignOptions>) => Promise<string>\n verifyJWT: <U = Record<string, unknown>>(token: string, customOptions?: Partial<VerifyOptions>) => Promise<U | null>\n createSession: (userId: string, data?: Record<string, unknown>, ttl?: number) => Promise<string>\n validateSession: (token: string) => Promise<GauServerSession | null>\n /**\n * Issue a session for a user, returning both the token and a Set-Cookie header.\n * Useful for guest login, invite redemption, admin impersonation, etc.\n */\n issueSession: (userId: string, options?: IssueSessionOptions) => Promise<IssueSessionResult>\n /**\n * Refresh an existing session, issuing a new token with extended TTL.\n * Preserves custom claims from the original token.\n *\n * @param tokenOrRequest - The existing session token, or a Request to extract the token from\n * @param options.ttl - Override the default TTL for the new token\n * @param options.threshold - Only refresh if past this fraction of TTL (0-1).\n * When set, returns null if below threshold.\n * Example: 0.5 means only refresh if session is past 50% of its lifetime.\n * @returns The refreshed session with source info, or null if invalid/expired/below threshold\n */\n refreshSession: (tokenOrRequest: string | Request, options?: RefreshSessionOptions) => Promise<RefreshSessionResult | null>\n /**\n * Get a valid access token for a linked provider. If the stored token is expired and a refresh token exists,\n * this will refresh it using the provider's refreshAccessToken and persist rotated tokens.\n */\n getAccessToken: (userId: string, providerId: string) => Promise<{ accessToken: string, expiresAt?: number | null } | null>\n /**\n * Start impersonating a target user.\n * Requires impersonation to be enabled and the admin user to have appropriate permissions.\n *\n * @param adminUserId - The ID of the user initiating impersonation (must have allowed role)\n * @param targetUserId - The ID of the user to impersonate\n * @param options - Optional configuration for the impersonation session\n * @returns ImpersonationResult with tokens and cookies, or null if impersonation is not allowed\n */\n startImpersonation: (adminUserId: string, targetUserId: string, options?: StartImpersonationOptions) => Promise<ImpersonationResult | null>\n /**\n * End an active impersonation session and restore the admin's original session.\n * Extracts the stashed session from the request cookies.\n *\n * @param request - The request containing the stashed session cookie\n * @returns EndImpersonationResult with restored session, or null if no stash found\n */\n endImpersonation: (request: Request) => Promise<EndImpersonationResult | null>\n trustHosts: 'all' | string[]\n autoLink: 'verifiedEmail' | 'always' | false\n allowDifferentEmails: boolean\n updateUserInfoOnLink: boolean\n sessionStrategy: 'auto' | 'cookie' | 'token'\n development: boolean\n roles: {\n defaultRole: string\n resolveOnCreate?: (context: { providerId: string, profile: any, request: Request }) => string | undefined\n adminRoles: string[]\n adminUserIds: string[]\n }\n cors: false | {\n allowedOrigins: 'all' | 'trust' | string[]\n allowCredentials: boolean\n allowedHeaders: string[]\n allowedMethods: string[]\n exposeHeaders?: string[]\n maxAge?: number\n }\n profiles: ResolvedProfiles<TProviders>\n onError?: CreateAuthOptions<TProviders>['onError']\n errorRedirect?: string\n impersonation: ImpersonationConfig | null\n}\n\nexport interface ProfileDefinition {\n scopes?: string[]\n redirectUri?: string\n /** When true, this profile can only be linked to an existing session; standalone sign-in is disabled. */\n linkOnly?: boolean\n /** Additional provider-specific authorization params. */\n params?: Record<string, string>\n}\n\ntype ProviderIdOfArray<TProviders extends OAuthProvider[]> = ProviderId<TProviders[number]>\ntype ProviderConfigFor<TProviders extends OAuthProvider[], K extends string>\n = Extract<TProviders[number], OAuthProvider<K, any>> extends OAuthProvider<any, infer C> ? C : OAuthProviderConfig\n\nexport type ProfilesConfig<TProviders extends OAuthProvider[]> = Partial<{\n [K in ProviderIdOfArray<TProviders>]: Record<string, ProfileDefinition & ProviderProfileOverrides<ProviderConfigFor<TProviders, K>>>\n}>\nexport type ResolvedProfiles<TProviders extends OAuthProvider[]> = ProfilesConfig<TProviders>\n\nexport function createAuth<const TProviders extends OAuthProvider[]>({\n adapter,\n providers,\n basePath = '/api/auth',\n jwt: jwtConfig = {},\n session: sessionConfig = {},\n cookies: cookieConfig = {},\n onOAuthExchange,\n mapExternalProfile,\n onBeforeLinkAccount,\n onAfterLinkAccount,\n trustHosts = [],\n autoLink = 'verifiedEmail',\n allowDifferentEmails = true,\n updateUserInfoOnLink = false,\n roles: rolesConfig = {},\n cors = true,\n profiles: profilesConfig,\n onError,\n errorRedirect,\n impersonation: impersonationConfig,\n}: CreateAuthOptions<TProviders>): Auth<TProviders> {\n const { algorithm = 'ES256', secret, iss, aud, ttl: defaultTTL = 3600 * 24 * 7 } = jwtConfig\n const cookieOptions = { ...DEFAULT_COOKIE_SERIALIZE_OPTIONS, ...cookieConfig }\n\n const sessionStrategy: 'auto' | 'cookie' | 'token' = sessionConfig.strategy ?? 'auto'\n\n if (algorithm === 'ES256' && secret !== undefined && typeof secret !== 'string')\n throw new AuthError('For ES256, the secret option must be a string.')\n\n const providerMap = new Map(providers.map(p => [p.id, p]))\n\n const resolvedCors: Auth['cors'] = cors === false\n ? false\n : {\n allowedOrigins: (cors === true ? 'all' : cors.allowedOrigins) ?? 'all',\n allowCredentials: (cors === true ? true : cors.allowCredentials) ?? true,\n allowedHeaders: (cors === true ? undefined : cors.allowedHeaders) ?? ['Content-Type', 'Authorization', 'Cookie'],\n allowedMethods: (cors === true ? undefined : cors.allowedMethods) ?? ['GET', 'POST', 'OPTIONS'],\n exposeHeaders: cors === true ? undefined : cors.exposeHeaders,\n maxAge: cors === true ? undefined : cors.maxAge,\n }\n\n const resolvedProfiles = (profilesConfig ?? {}) as ResolvedProfiles<TProviders>\n const resolvedRoles = {\n defaultRole: rolesConfig.defaultRole ?? 'user',\n resolveOnCreate: rolesConfig.resolveOnCreate,\n adminRoles: rolesConfig.adminRoles ?? ['admin'],\n adminUserIds: rolesConfig.adminUserIds ?? [],\n }\n\n const resolvedImpersonation: ResolvedImpersonationConfig | null = impersonationConfig?.enabled\n ? {\n enabled: true,\n allowedRoles: impersonationConfig.allowedRoles ?? resolvedRoles.adminRoles,\n cannotImpersonate: impersonationConfig.cannotImpersonate ?? resolvedRoles.adminRoles,\n maxTTL: impersonationConfig.maxTTL ?? 3600,\n onImpersonate: impersonationConfig.onImpersonate,\n }\n : null\n\n function buildSignOptions(custom: Partial<SignOptions> = {}): SignOptions {\n const base = { ttl: custom.ttl, iss: custom.iss ?? iss, aud: custom.aud ?? aud, sub: custom.sub }\n if (algorithm === 'HS256') {\n return { algorithm, secret: custom.secret ?? secret, ...base }\n }\n else {\n if (custom.secret !== undefined && typeof custom.secret !== 'string')\n throw new AuthError('For ES256, the secret option must be a string.')\n const esSecret = custom.secret ?? secret\n return { algorithm, privateKey: custom.privateKey, secret: esSecret, ...base }\n }\n }\n\n function buildVerifyOptions(custom: Partial<VerifyOptions> = {}): VerifyOptions {\n const base = { iss: custom.iss ?? iss, aud: custom.aud ?? aud }\n if (algorithm === 'HS256') {\n return { algorithm, secret: custom.secret ?? secret, ...base }\n }\n else {\n if (custom.secret !== undefined && typeof custom.secret !== 'string')\n throw new AuthError('For ES256, the secret option must be a string.')\n const esSecret = custom.secret ?? secret\n return { algorithm, publicKey: custom.publicKey, secret: esSecret, ...base }\n }\n }\n\n async function signJWT<U extends Record<string, unknown>>(payload: U, customOptions: Partial<SignOptions> = {}): Promise<string> {\n return sign(payload, buildSignOptions(customOptions))\n }\n\n async function verifyJWT<U = Record<string, unknown>>(token: string, customOptions: Partial<VerifyOptions> = {}): Promise<U | null> {\n const options = buildVerifyOptions(customOptions)\n try {\n return await verify<U>(token, options)\n }\n catch {\n return null\n }\n }\n\n async function createSession(userId: string, data: Record<string, unknown> = {}, ttl = defaultTTL): Promise<string> {\n const payload = { sub: userId, ...data }\n return signJWT(payload, { ttl })\n }\n\n async function issueSession(userId: string, options: IssueSessionOptions = {}): Promise<IssueSessionResult> {\n const { data = {}, ttl = defaultTTL } = options\n const token = await createSession(userId, data, ttl)\n\n const cookieOpts: SerializeOptions = {\n ...cookieOptions,\n maxAge: ttl,\n }\n\n const cookie = serialize(SESSION_COOKIE_NAME, token, cookieOpts)\n\n return {\n token,\n cookie,\n cookieName: SESSION_COOKIE_NAME,\n maxAge: ttl,\n }\n }\n\n async function refreshSession(tokenOrRequest: string | Request, options: RefreshSessionOptions = {}): Promise<RefreshSessionResult | null> {\n let token: string | undefined\n let source: RefreshSessionResult['source']\n\n if (typeof tokenOrRequest === 'string') {\n token = tokenOrRequest\n source = 'token'\n }\n else {\n const extracted = getSessionTokenFromRequest(tokenOrRequest)\n if (!extracted.token || !extracted.source)\n return null\n token = extracted.token\n source = extracted.source\n }\n\n const payload = await verifyJWT<{ sub: string, iat?: number } & Record<string, unknown>>(token)\n if (!payload || !payload.sub)\n return null\n\n if (options.threshold != null && options.threshold > 0 && options.threshold < 1) {\n const { iat } = payload\n if (iat) {\n const now = Math.floor(Date.now() / 1000)\n const sessionAge = now - iat\n const ttl = options.ttl ?? defaultTTL\n const thresholdSeconds = ttl * options.threshold\n\n if (sessionAge < thresholdSeconds)\n return null\n }\n }\n\n const user = await adapter.getUser(payload.sub)\n if (!user)\n return null\n const { sub, iat, exp, iss, aud, nbf, jti, ...customClaims } = payload\n\n const result = await issueSession(payload.sub, {\n data: customClaims,\n ttl: options.ttl,\n })\n\n return { ...result, source }\n }\n\n async function validateSession(token: string): Promise<GauServerSession | null> {\n const payload = await verifyJWT<{ sub: string } & Record<string, unknown>>(token)\n if (!payload)\n return null\n\n const userAndAccounts = await adapter.getUserAndAccounts(payload.sub)\n if (!userAndAccounts)\n return null\n\n const { user, accounts } = userAndAccounts\n const isAdmin = Boolean(\n user\n && (\n (user.role && resolvedRoles.adminRoles.includes(user.role))\n || (resolvedRoles.adminUserIds.length > 0 && resolvedRoles.adminUserIds.includes(user.id))\n ),\n )\n const sessionUser = user ? { ...user, isAdmin } : null\n\n return { user: sessionUser, session: { id: token, ...payload }, accounts }\n }\n\n async function getAccessToken(userId: string, providerId: string) {\n const provider = providerMap.get(providerId)\n if (!provider)\n return null\n\n const accounts = await adapter.getAccounts(userId)\n const account = accounts.find(a => a.provider === providerId)\n if (!account || !account.accessToken)\n return null\n\n const now = Math.floor(Date.now() / 1000)\n const isExpired = typeof account.expiresAt === 'number' ? account.expiresAt <= now : false\n\n if (!isExpired)\n return { accessToken: account.accessToken, expiresAt: account.expiresAt ?? null }\n\n if (!account.refreshToken || !provider.refreshAccessToken)\n return null\n\n try {\n const refreshed = await provider.refreshAccessToken(account.refreshToken, {})\n const updated = {\n userId,\n provider: account.provider,\n providerAccountId: account.providerAccountId,\n accessToken: refreshed.accessToken ?? account.accessToken,\n refreshToken: refreshed.refreshToken ?? account.refreshToken,\n expiresAt: refreshed.expiresAt ?? null,\n idToken: refreshed.idToken ?? account.idToken ?? null,\n tokenType: refreshed.tokenType ?? account.tokenType ?? null,\n scope: refreshed.scope ?? account.scope ?? null,\n }\n await adapter.updateAccount?.(updated)\n return { accessToken: updated.accessToken!, expiresAt: updated.expiresAt }\n }\n catch {\n return null\n }\n }\n\n async function startImpersonation(\n adminUserId: string,\n targetUserId: string,\n options: StartImpersonationOptions = {},\n ): Promise<ImpersonationResult | null> {\n if (!resolvedImpersonation)\n throw new GauError(ErrorCodes.IMPERSONATION_DISABLED)\n\n const adminUser = await adapter.getUser(adminUserId)\n if (!adminUser)\n throw new GauError(ErrorCodes.USER_NOT_FOUND, `Admin user \"${adminUserId}\" not found`)\n\n const hasAllowedRole = adminUser.role\n ? resolvedImpersonation.allowedRoles.includes(adminUser.role)\n : false\n const isAdminUserId = resolvedRoles.adminUserIds.includes(adminUserId)\n\n if (!hasAllowedRole && !isAdminUserId)\n throw new GauError(ErrorCodes.IMPERSONATION_NOT_ALLOWED)\n\n const targetUser = await adapter.getUser(targetUserId)\n if (!targetUser)\n throw new GauError(ErrorCodes.USER_NOT_FOUND, `Target user \"${targetUserId}\" not found`)\n\n if (targetUser.role && resolvedImpersonation.cannotImpersonate.includes(targetUser.role))\n throw new GauError(ErrorCodes.IMPERSONATION_TARGET_PROTECTED)\n\n if (resolvedImpersonation.onImpersonate) {\n await resolvedImpersonation.onImpersonate({\n adminUserId,\n targetUserId,\n reason: options.reason,\n timestamp: Date.now(),\n })\n }\n\n const ttl = Math.min(options.ttl ?? resolvedImpersonation.maxTTL, resolvedImpersonation.maxTTL)\n const expiresAt = Math.floor(Date.now() / 1000) + ttl\n\n const impersonationToken = await createSession(targetUserId, {\n impersonatedBy: adminUserId,\n impersonationExpiresAt: expiresAt,\n }, ttl)\n\n const cookieOpts: SerializeOptions = {\n ...cookieOptions,\n maxAge: ttl,\n }\n\n const cookie = serialize(SESSION_COOKIE_NAME, impersonationToken, cookieOpts)\n\n const stashToken = await signJWT({ adminUserId }, { ttl: resolvedImpersonation.maxTTL * 2 })\n const stashCookie = serialize(SESSION_STASH_COOKIE_NAME, stashToken, cookieOpts)\n\n return {\n token: impersonationToken,\n cookie,\n originalCookie: stashCookie,\n maxAge: ttl,\n }\n }\n\n async function endImpersonation(request: Request): Promise<EndImpersonationResult | null> {\n const cookieHeader = request.headers.get('cookie')\n if (!cookieHeader)\n return null\n\n const parsedCookies = parse(cookieHeader)\n const stashToken = parsedCookies[SESSION_STASH_COOKIE_NAME]\n\n if (!stashToken)\n return null\n\n const stashPayload = await verifyJWT<{ adminUserId: string }>(stashToken)\n if (!stashPayload?.adminUserId)\n return null\n const adminUser = await adapter.getUser(stashPayload.adminUserId)\n if (!adminUser)\n return null\n\n const restoredSession = await issueSession(stashPayload.adminUserId)\n\n const clearStashCookie = serialize(SESSION_STASH_COOKIE_NAME, '', {\n ...cookieOptions,\n expires: new Date(0),\n maxAge: 0,\n })\n\n return {\n token: restoredSession.token,\n cookie: restoredSession.cookie,\n clearCookies: [clearStashCookie],\n }\n }\n\n return {\n ...adapter,\n providerMap: providerMap as Map<ProviderId<TProviders[number]>, TProviders[number]>,\n basePath,\n cookieOptions,\n jwt: {\n ttl: defaultTTL,\n },\n onOAuthExchange,\n mapExternalProfile,\n onBeforeLinkAccount,\n onAfterLinkAccount,\n signJWT,\n verifyJWT,\n createSession,\n validateSession,\n issueSession,\n refreshSession,\n getAccessToken,\n trustHosts,\n autoLink,\n allowDifferentEmails,\n profiles: resolvedProfiles,\n updateUserInfoOnLink,\n sessionStrategy,\n development: false,\n roles: resolvedRoles,\n cors: resolvedCors,\n onError,\n errorRedirect,\n startImpersonation,\n endImpersonation,\n impersonation: resolvedImpersonation,\n }\n}\n","import { parseCookies, SESSION_COOKIE_NAME } from './cookies'\n\nexport type SessionTokenSource = 'cookie' | 'bearer'\n\n/**\n * Extract the session token from a Request.\n * Prefers Cookie, then falls back to Authorization: Bearer.\n */\nexport function getSessionTokenFromRequest(request: Request): { token?: string, source?: SessionTokenSource } {\n const cookies = parseCookies(request.headers.get('Cookie'))\n const cookieToken = cookies.get(SESSION_COOKIE_NAME)\n if (cookieToken)\n return { token: cookieToken, source: 'cookie' }\n\n const authHeader = request.headers.get('Authorization')\n if (authHeader?.startsWith('Bearer '))\n return { token: authHeader.substring(7), source: 'bearer' }\n\n return {}\n}\n","export const ErrorMessages = {\n // OAuth Flow Errors\n CSRF_INVALID: 'Invalid CSRF token',\n PKCE_MISSING: 'Missing PKCE code verifier',\n PKCE_CHALLENGE_MISSING: 'Missing PKCE challenge',\n OAUTH_CANCELLED: 'Authentication was cancelled',\n PROVIDER_NOT_FOUND: 'Provider not found',\n AUTHORIZATION_URL_FAILED: 'Could not create authorization URL',\n\n // User Errors\n USER_NOT_FOUND: 'User not found',\n USER_CREATE_FAILED: 'Failed to create user',\n ACCOUNT_ALREADY_LINKED: 'Account already linked to another user',\n ACCOUNT_LINK_FAILED: 'Failed to link account',\n ACCOUNT_NOT_LINKED: 'Account not linked',\n CANNOT_UNLINK_LAST_ACCOUNT: 'Cannot unlink the last account',\n EMAIL_ALREADY_EXISTS: 'An account with this email already exists',\n EMAIL_MISMATCH: 'Email mismatch between existing account and provider',\n LINKING_NOT_ALLOWED: 'Linking not allowed',\n LINK_ONLY_PROVIDER: 'Sign-in with this provider is disabled. Please link it to an existing account.',\n\n // Session Errors\n UNAUTHORIZED: 'Unauthorized',\n FORBIDDEN: 'Forbidden',\n SESSION_INVALID: 'Invalid session',\n SESSION_VALIDATION_FAILED: 'Failed to validate session',\n\n // Token Errors\n TOKEN_INVALID: 'Invalid token',\n TOKEN_EXPIRED: 'Token expired',\n CODE_VERIFIER_INVALID: 'Invalid code verifier',\n\n // Request Errors\n NOT_FOUND: 'Not found',\n METHOD_NOT_ALLOWED: 'Method not allowed',\n INVALID_REQUEST: 'Invalid request',\n INVALID_REDIRECT_URL: 'Invalid redirect URL',\n UNTRUSTED_HOST: 'Untrusted redirect host',\n UNKNOWN_PROFILE: 'Unknown profile',\n\n // Internal Errors\n INTERNAL_ERROR: 'An unexpected error occurred',\n\n // Impersonation Errors\n IMPERSONATION_DISABLED: 'Impersonation is not enabled',\n IMPERSONATION_NOT_ALLOWED: 'You are not allowed to impersonate users',\n IMPERSONATION_TARGET_PROTECTED: 'Cannot impersonate users with protected roles',\n} as const\n\nexport type ErrorCode = keyof typeof ErrorMessages\n\nexport const ErrorCodes: { [K in ErrorCode]: K } = Object.fromEntries(\n Object.keys(ErrorMessages).map(k => [k, k]),\n) as { [K in ErrorCode]: K }\n\n/**\n * Default HTTP status codes for each error code.\n * Errors not listed here default to 400.\n */\nexport const ErrorStatuses: Partial<Record<ErrorCode, number>> = {\n CSRF_INVALID: 403,\n UNAUTHORIZED: 401,\n FORBIDDEN: 403,\n NOT_FOUND: 404,\n METHOD_NOT_ALLOWED: 405,\n INTERNAL_ERROR: 500,\n USER_CREATE_FAILED: 500,\n ACCOUNT_LINK_FAILED: 500,\n AUTHORIZATION_URL_FAILED: 500,\n SESSION_VALIDATION_FAILED: 500,\n ACCOUNT_ALREADY_LINKED: 409,\n EMAIL_ALREADY_EXISTS: 409,\n LINKING_NOT_ALLOWED: 403,\n IMPERSONATION_DISABLED: 403,\n IMPERSONATION_NOT_ALLOWED: 403,\n IMPERSONATION_TARGET_PROTECTED: 403,\n}\n\nexport interface GauErrorOptions {\n /** HTTP status code (uses default for error code if not specified) */\n status?: number\n /** URL to redirect to after showing error (for OAuth flow errors) */\n redirectUrl?: string\n /** Original error that caused this error */\n cause?: unknown\n}\n\nexport class GauError extends Error {\n readonly code: ErrorCode\n readonly status: number\n readonly redirectUrl?: string\n override readonly cause?: unknown\n\n constructor(\n code: ErrorCode,\n messageOrOptions?: string | GauErrorOptions,\n options?: GauErrorOptions,\n ) {\n const message = typeof messageOrOptions === 'string'\n ? messageOrOptions\n : ErrorMessages[code]\n const opts = typeof messageOrOptions === 'object'\n ? messageOrOptions\n : options ?? {}\n\n super(message)\n this.name = 'GauError'\n this.code = code\n this.status = opts.status ?? ErrorStatuses[code] ?? 400\n this.redirectUrl = opts.redirectUrl\n this.cause = opts.cause\n }\n\n toJSON() {\n return {\n error: this.message,\n code: this.code,\n ...(this.redirectUrl && { redirectUrl: this.redirectUrl }),\n }\n }\n}\n\nexport function createErrorRedirectUrl(baseUrl: string, error: GauError): string {\n const url = new URL(baseUrl, 'http://placeholder')\n url.searchParams.set('code', error.code)\n url.searchParams.set('message', error.message)\n url.searchParams.set('status', String(error.status))\n if (error.redirectUrl)\n url.searchParams.set('redirect', error.redirectUrl)\n\n return url.pathname + url.search\n}\n\nexport interface ErrorContext {\n error: GauError\n request: Request\n}\n\nexport interface ErrorHandlerConfig {\n basePath: string\n onError?: (context: ErrorContext) => Response | Promise<Response | undefined> | undefined\n errorRedirect?: string\n}\n\nexport function isUserFacingRequest(request: Request, basePath: string): boolean {\n // POST requests are always API calls\n if (request.method !== 'GET')\n return false\n\n const url = new URL(request.url)\n const path = url.pathname.substring(basePath.length)\n const parts = path.split('/').filter(Boolean)\n\n // GET /session is an API call\n if (parts.length === 1 && parts[0] === 'session')\n return false\n\n // GET /:provider (sign-in start) - user-facing\n if (parts.length === 1)\n return true\n\n // GET /callback/:provider or GET /link/:provider - user-facing\n if (parts.length === 2 && (parts[0] === 'callback' || parts[0] === 'link'))\n return true\n\n return false\n}\n\nexport async function handleError(\n context: ErrorContext,\n config: ErrorHandlerConfig,\n): Promise<Response> {\n const { error, request } = context\n\n // 1. Try custom onError handler\n if (config.onError) {\n try {\n const response = await config.onError(context)\n if (response)\n return response\n }\n catch (e) {\n console.error('onError handler threw:', e)\n }\n }\n\n const userFacing = isUserFacingRequest(request, config.basePath)\n\n // 2. Try errorRedirect for user-facing requests\n if (config.errorRedirect && userFacing) {\n const redirectUrl = createErrorRedirectUrl(config.errorRedirect, error)\n return new Response(null, {\n status: 302,\n headers: { Location: redirectUrl },\n })\n }\n\n // 3. Default handling\n if (userFacing) {\n const { renderErrorPage, htmlResponse } = await import('./templates')\n const html = renderErrorPage({\n title: 'Authentication Error',\n message: error.message,\n code: error.code,\n redirectUrl: error.redirectUrl,\n })\n return htmlResponse(html, error.status)\n }\n\n return new Response(JSON.stringify(error.toJSON()), {\n status: error.status,\n headers: { 'Content-Type': 'application/json; charset=utf-8' },\n })\n}\n","import type { OAuth2Tokens } from 'arctic'\nimport type { Cookies } from './cookies'\nimport type { Auth } from './createAuth'\n\nexport interface OAuthExchangeContext {\n request: Request\n providerId: string\n state: string\n code: string\n codeVerifier: string\n callbackUri?: string | null\n redirectTo: string\n cookies: Cookies\n providerUser: any\n tokens: OAuth2Tokens\n isLinking: boolean\n sessionUserId?: string\n}\n\nexport type OAuthExchangeResult = { handled: true, response: Response } | { handled: false }\n\nexport async function runOnOAuthExchange(auth: Auth | undefined, ctx: OAuthExchangeContext): Promise<OAuthExchangeResult> {\n if (!auth || typeof auth.onOAuthExchange !== 'function')\n return { handled: false }\n try {\n const res = await auth.onOAuthExchange(ctx)\n if (!res || typeof res !== 'object')\n return { handled: false }\n return res\n }\n catch (e) {\n console.error('onOAuthExchange hook error:', e)\n return { handled: false }\n }\n}\n\nexport interface MapExternalProfileContext {\n request: Request\n providerId: string\n providerUser: any\n tokens: OAuth2Tokens\n isLinking: boolean\n}\n\nexport async function maybeMapExternalProfile(auth: Auth | undefined, ctx: MapExternalProfileContext): Promise<any> {\n if (!auth || typeof auth.mapExternalProfile !== 'function')\n return ctx.providerUser\n try {\n const mapped = await auth.mapExternalProfile(ctx)\n if (!mapped)\n return ctx.providerUser\n return { ...ctx.providerUser, ...mapped }\n }\n catch (e) {\n console.error('mapExternalProfile hook error:', e)\n return ctx.providerUser\n }\n}\n\nexport interface BeforeLinkAccountContext {\n request: Request\n providerId: string\n userId: string\n providerUser: any\n tokens: OAuth2Tokens\n}\n\nexport async function runOnBeforeLinkAccount(auth: Auth | undefined, ctx: BeforeLinkAccountContext): Promise<{ allow: true } | { allow: false, response?: Response }> {\n if (!auth || typeof auth.onBeforeLinkAccount !== 'function')\n return { allow: true }\n try {\n const res = await auth.onBeforeLinkAccount(ctx)\n if (!res)\n return { allow: true }\n return res\n }\n catch (e) {\n console.error('onBeforeLinkAccount hook error:', e)\n return { allow: true }\n }\n}\n\nexport interface AfterLinkAccountContext extends BeforeLinkAccountContext { action: 'link' | 'update' }\n\nexport async function runOnAfterLinkAccount(auth: Auth | undefined, ctx: AfterLinkAccountContext): Promise<void> {\n if (!auth || typeof auth.onAfterLinkAccount !== 'function')\n return\n try {\n await auth.onAfterLinkAccount(ctx)\n }\n catch (e) {\n console.error('onAfterLinkAccount hook error:', e)\n }\n}\n","import type { Auth } from '../createAuth'\nimport type { User } from '../index'\nimport {\n CALLBACK_URI_COOKIE_NAME,\n CLIENT_CHALLENGE_COOKIE_NAME,\n Cookies,\n CSRF_COOKIE_NAME,\n LINKING_TOKEN_COOKIE_NAME,\n parseCookies,\n PKCE_COOKIE_NAME,\n PROVIDER_OPTIONS_COOKIE_NAME,\n SESSION_COOKIE_NAME,\n} from '../cookies'\nimport { ErrorCodes, GauError } from '../errors'\nimport { maybeMapExternalProfile, runOnAfterLinkAccount, runOnBeforeLinkAccount, runOnOAuthExchange } from '../hooks'\nimport { json, redirect } from '../index'\nimport { htmlResponse, renderCancelledPage, renderSuccessPage } from '../templates'\n\ntype Session = Awaited<ReturnType<Auth['validateSession']>>\ninterface TokenSnapshot {\n accessToken: string | null\n refreshToken: string | null\n expiresAt: number | undefined\n tokenType: string | null\n scope: string | null\n idToken: string | null\n}\n\nfunction appendCookieHeaders(response: Response, cookies: Cookies): Response {\n cookies.toHeaders().forEach((value, key) => response.headers.append(key, value))\n return response\n}\n\nfunction clearTemporaryCookies(cookies: Cookies, callbackUri?: string | null, options: { clientChallenge?: boolean } = {}): void {\n cookies.delete(CSRF_COOKIE_NAME)\n cookies.delete(PKCE_COOKIE_NAME)\n if (callbackUri)\n cookies.delete(CALLBACK_URI_COOKIE_NAME)\n cookies.delete(PROVIDER_OPTIONS_COOKIE_NAME)\n if (options.clientChallenge)\n cookies.delete(CLIENT_CHALLENGE_COOKIE_NAME)\n}\n\nfunction parseRedirectTarget(encodedRedirect?: string): string {\n try {\n return atob(encodedRedirect ?? '') || '/'\n }\n catch {\n return '/'\n }\n}\n\nfunction parseCallbackState(state: string): { savedState: string, redirectTo: string } {\n if (!state.includes('.'))\n return { savedState: state, redirectTo: '/' }\n\n const [savedState = state, encodedRedirect] = state.split('.')\n return {\n savedState,\n redirectTo: parseRedirectTarget(encodedRedirect),\n }\n}\n\nfunction resolveCancelledRedirectTarget(state: string | null): string {\n if (!state || !state.includes('.'))\n return '/'\n\n return parseRedirectTarget(state.split('.')[1])\n}\n\nasync function resolveLinkingSession(auth: Auth, linkingToken: string | undefined): Promise<{ isLinking: boolean, session: Session }> {\n if (!linkingToken)\n return { isLinking: false, session: null }\n\n return {\n isLinking: true,\n session: await auth.validateSession(linkingToken),\n }\n}\n\nfunction readOptionalToken<T>(read: () => T, fallback: T): T {\n try {\n return read()\n }\n catch {\n return fallback\n }\n}\n\nfunction normalizeTokens(tokens: any, fallback?: Partial<TokenSnapshot>, options: { requireAccessToken?: boolean } = {}): TokenSnapshot {\n return {\n accessToken: options.requireAccessToken\n ? tokens.accessToken()\n : readOptionalToken(() => tokens.accessToken() ?? fallback?.accessToken ?? null, fallback?.accessToken ?? null),\n refreshToken: readOptionalToken(() => tokens.refreshToken(), fallback?.refreshToken ?? null),\n expiresAt: readOptionalToken(() => {\n const expiresAtDate = tokens.accessTokenExpiresAt()\n return expiresAtDate ? Math.floor(expiresAtDate.getTime() / 1000) : fallback?.expiresAt ?? undefined\n }, fallback?.expiresAt ?? undefined),\n tokenType: readOptionalToken(() => tokens.tokenType?.() ?? fallback?.tokenType ?? null, fallback?.tokenType ?? null),\n scope: readOptionalToken(() => tokens.scopes()?.join(' ') ?? fallback?.scope ?? null, fallback?.scope ?? null),\n idToken: readOptionalToken(() => tokens.idToken(), fallback?.idToken ?? null),\n }\n}\n\nasync function buildFinalResponse(\n request: Request,\n auth: Auth,\n user: User,\n redirectTo: string,\n sessionToken: string,\n url: URL,\n cookies: Cookies,\n callbackUri?: string | null,\n): Promise<Response> {\n const requestUrl = new URL(request.url)\n const redirectUrl = new URL(redirectTo, request.url)\n\n const forceToken = auth.sessionStrategy === 'token'\n const forceCookie = auth.sessionStrategy === 'cookie'\n\n const isCustomScheme = redirectUrl.protocol !== 'http:' && redirectUrl.protocol !== 'https:'\n const isCrossHost = requestUrl.host !== redirectUrl.host\n\n if (forceToken || (!forceCookie && (isCustomScheme || isCrossHost))) {\n const destination = new URL(redirectUrl)\n const clientChallenge = cookies.get(CLIENT_CHALLENGE_COOKIE_NAME)\n\n if (!clientChallenge)\n throw new GauError(ErrorCodes.PKCE_CHALLENGE_MISSING, { redirectUrl: redirectTo })\n\n const authCode = await auth.signJWT({\n sub: user.id,\n challenge: clientChallenge,\n }, { ttl: 60 })\n\n destination.searchParams.set('code', authCode)\n\n clearTemporaryCookies(cookies, callbackUri, { clientChallenge: true })\n return appendCookieHeaders(htmlResponse(renderSuccessPage({ redirectUrl: destination.toString() })), cookies)\n }\n\n cookies.set(SESSION_COOKIE_NAME, sessionToken, {\n maxAge: auth.jwt.ttl,\n sameSite: auth.development ? 'lax' : 'none',\n secure: !auth.development,\n })\n clearTemporaryCookies(cookies, callbackUri)\n\n const response = url.searchParams.get('redirect') === 'false'\n ? json({\n user: {\n ...user,\n isAdmin: Boolean(\n (user.role && auth.roles.adminRoles.includes(user.role))\n || auth.roles.adminUserIds.includes(user.id),\n ),\n accounts: await auth.getAccounts(user.id),\n },\n })\n : redirect(redirectTo)\n\n return appendCookieHeaders(response, cookies)\n}\n\nexport async function handleCallback(request: Request, auth: Auth, providerId: string): Promise<Response> {\n const provider = auth.providerMap.get(providerId)\n if (!provider)\n throw new GauError(ErrorCodes.PROVIDER_NOT_FOUND)\n\n const url = new URL(request.url)\n const code = url.searchParams.get('code')\n const state = url.searchParams.get('state')\n const error = url.searchParams.get('error')\n\n if (!code || !state || error)\n return htmlResponse(renderCancelledPage({ redirectUrl: resolveCancelledRedirectTarget(state) }))\n\n const requestCookies = parseCookies(request.headers.get('Cookie'))\n const cookies = new Cookies(requestCookies, auth.cookieOptions)\n\n const { savedState, redirectTo } = parseCallbackState(state)\n\n const csrfToken = cookies.get(CSRF_COOKIE_NAME)\n\n if (!csrfToken || csrfToken !== savedState)\n throw new GauError(ErrorCodes.CSRF_INVALID, { redirectUrl: redirectTo })\n\n const codeVerifier = cookies.get(PKCE_COOKIE_NAME)\n if (!codeVerifier)\n throw new GauError(ErrorCodes.PKCE_MISSING, { redirectUrl: redirectTo })\n\n const callbackUri = cookies.get(CALLBACK_URI_COOKIE_NAME)\n const providerOptionsRaw = cookies.get(PROVIDER_OPTIONS_COOKIE_NAME)\n let providerOverrides: any | undefined\n if (providerOptionsRaw) {\n try {\n const decoded = atob(providerOptionsRaw)\n const parsed = JSON.parse(decoded)\n providerOverrides = parsed?.overrides\n }\n catch {}\n }\n const linkingToken = cookies.get(LINKING_TOKEN_COOKIE_NAME)\n\n if (linkingToken)\n cookies.delete(LINKING_TOKEN_COOKIE_NAME)\n\n const { isLinking, session: linkingSession } = await resolveLinkingSession(auth, linkingToken ?? undefined)\n\n if (isLinking && !linkingSession) {\n clearTemporaryCookies(cookies, callbackUri, { clientChallenge: true })\n return appendCookieHeaders(redirect(redirectTo), cookies)\n }\n\n const { user: rawProviderUser, tokens } = await provider.validateCallback(code, codeVerifier, callbackUri ?? undefined, providerOverrides)\n\n {\n const hookResult = await runOnOAuthExchange(auth, {\n request,\n providerId,\n state,\n code,\n codeVerifier,\n callbackUri,\n redirectTo,\n cookies,\n providerUser: rawProviderUser,\n tokens,\n isLinking,\n sessionUserId: linkingSession?.user?.id,\n })\n if (hookResult.handled) {\n clearTemporaryCookies(cookies, callbackUri, { clientChallenge: true })\n return appendCookieHeaders(hookResult.response, cookies)\n }\n }\n\n const providerUser = await maybeMapExternalProfile(auth, {\n request,\n providerId,\n providerUser: rawProviderUser,\n tokens,\n isLinking,\n })\n\n // Enforce provider-level link-only when not linking (profile-level enforced at redirect time)\n if (!isLinking && (auth.providerMap.get(providerId)?.linkOnly === true)) {\n clearTemporaryCookies(cookies, callbackUri)\n throw new GauError(ErrorCodes.LINK_ONLY_PROVIDER, { redirectUrl: redirectTo })\n }\n\n let user: User | null = null\n\n const userFromAccount = await auth.getUserByAccount(providerId, providerUser.id)\n\n if (isLinking) {\n user = linkingSession!.user\n\n if (!user)\n throw new GauError(ErrorCodes.USER_NOT_FOUND, { redirectUrl: redirectTo })\n\n if (userFromAccount && userFromAccount.id !== user.id)\n throw new GauError(ErrorCodes.ACCOUNT_ALREADY_LINKED, { redirectUrl: redirectTo })\n\n if (auth.allowDifferentEmails === false) {\n const currentEmail = user.email\n const providerEmail = providerUser.email\n if (currentEmail && providerEmail && currentEmail !== providerEmail)\n throw new GauError(ErrorCodes.EMAIL_MISMATCH, { redirectUrl: redirectTo })\n }\n\n if (user) {\n const update: Partial<User> & { id: string } = { id: user.id }\n let needsUpdate = false\n\n if (auth.updateUserInfoOnLink) {\n if (providerUser.name && providerUser.name !== user.name) {\n update.name = providerUser.name\n needsUpdate = true\n }\n if (providerUser.avatar && providerUser.avatar !== user.image) {\n update.image = providerUser.avatar\n needsUpdate = true\n }\n }\n else {\n if (!user.name && providerUser.name) {\n update.name = providerUser.name\n needsUpdate = true\n }\n if (!user.image && providerUser.avatar) {\n update.image = providerUser.avatar\n needsUpdate = true\n }\n }\n\n if (\n user.email\n && providerUser.email\n && user.email === providerUser.email\n && providerUser.emailVerified === true\n && (!user.emailVerified || auth.updateUserInfoOnLink)\n ) {\n update.emailVerified = true\n needsUpdate = true\n }\n\n if (needsUpdate) {\n try {\n user = await auth.updateUser(update)\n }\n catch (e) {\n console.error('Failed to update user info on link:', e)\n }\n }\n }\n }\n else {\n user = userFromAccount\n }\n\n if (!user) {\n const autoLink = auth.autoLink ?? 'verifiedEmail'\n const shouldLinkByEmail = providerUser.email && (\n (autoLink === 'always')\n || (autoLink === 'verifiedEmail' && providerUser.emailVerified === true)\n )\n if (shouldLinkByEmail) {\n const existingUser = await auth.getUserByEmail(providerUser.email!)\n if (existingUser) {\n // If the email is verified by the new provider, and the existing user's email is not,\n // update the user's email verification status.\n if (providerUser.emailVerified && !existingUser.emailVerified) {\n user = await auth.updateUser({\n id: existingUser.id,\n emailVerified: true,\n })\n }\n else {\n user = existingUser\n }\n }\n }\n if (!user) {\n try {\n if (providerUser.email && providerUser.emailVerified === true && auth.autoLink === false) {\n const existingWithSameEmail = await auth.getUserByEmail(providerUser.email)\n if (existingWithSameEmail)\n throw new GauError(ErrorCodes.EMAIL_ALREADY_EXISTS, { redirectUrl: redirectTo })\n }\n\n let resolvedRole: string | undefined\n try {\n resolvedRole = auth.roles.resolveOnCreate?.({ providerId, profile: providerUser, request: request as unknown as Request })\n }\n catch (e) {\n console.error('roles.resolveOnCreate threw:', e)\n }\n\n const emailToStore = providerUser.emailVerified === true ? providerUser.email : null\n\n user = await auth.createUser({\n name: providerUser.name,\n email: emailToStore,\n image: providerUser.avatar,\n emailVerified: providerUser.emailVerified,\n role: resolvedRole ?? auth.roles.defaultRole,\n })\n }\n catch (error) {\n if (error instanceof GauError)\n throw error\n console.error('Failed to create user:', error)\n throw new GauError(ErrorCodes.USER_CREATE_FAILED, { cause: error, redirectUrl: redirectTo })\n }\n }\n }\n\n // self-healing: update user's email if it's missing or unverified and the provider returns a verified email\n if (user && providerUser.email) {\n const { email: currentEmail, emailVerified: currentEmailVerified } = user\n const { email: providerEmail, emailVerified: providerEmailVerified } = providerUser\n\n const update: Partial<User> & { id: string } = { id: user.id }\n let needsUpdate = false\n\n // user has no primary email. promote the provider's email but only if it's verified\n // and does not already belong to another user.\n if (!currentEmail && providerEmailVerified === true) {\n const existingEmailUser = await auth.getUserByEmail(providerEmail)\n if (!existingEmailUser || existingEmailUser.id === user.id) {\n update.email = providerEmail\n update.emailVerified = true\n needsUpdate = true\n }\n }\n // user has an unverified primary email, and the provider confirms this same email is verified.\n else if (\n currentEmail === providerEmail\n && providerEmailVerified === true\n && !currentEmailVerified\n ) {\n update.emailVerified = true\n needsUpdate = true\n }\n\n if (needsUpdate) {\n try {\n user = await auth.updateUser(update)\n }\n catch (error) {\n console.error('Failed to update user after sign-in:', error)\n }\n }\n }\n\n if (!userFromAccount) {\n {\n const pre = await runOnBeforeLinkAccount(auth, {\n request,\n providerId,\n userId: user.id,\n providerUser,\n tokens,\n })\n if (pre.allow === false) {\n const response = pre.response ?? (() => {\n throw new GauError(ErrorCodes.LINKING_NOT_ALLOWED, { redirectUrl: redirectTo })\n })()\n clearTemporaryCookies(cookies, callbackUri, { clientChallenge: true })\n return appendCookieHeaders(response, cookies)\n }\n }\n\n try {\n const normalizedTokens = normalizeTokens(tokens, undefined, { requireAccessToken: true })\n\n await auth.linkAccount({\n userId: user.id,\n provider: providerId,\n providerAccountId: providerUser.id,\n accessToken: normalizedTokens.accessToken,\n refreshToken: normalizedTokens.refreshToken,\n expiresAt: normalizedTokens.expiresAt,\n tokenType: normalizedTokens.tokenType,\n scope: normalizedTokens.scope,\n idToken: normalizedTokens.idToken,\n })\n await runOnAfterLinkAccount(auth, {\n request,\n providerId,\n userId: user.id,\n providerUser,\n tokens,\n action: 'link',\n })\n }\n catch (error) {\n console.error('Error linking account:', error)\n throw new GauError(ErrorCodes.ACCOUNT_LINK_FAILED, { cause: error, redirectUrl: redirectTo })\n }\n }\n else {\n // Existing account: update stored tokens on sign-in (access/refresh/expires/idToken/etc.)\n try {\n const accounts = await auth.getAccounts(user!.id)\n const existing = accounts.find(a => a.provider === providerId && a.providerAccountId === providerUser.id)\n\n if (existing && auth.updateAccount) {\n const normalizedTokens = normalizeTokens(tokens, {\n accessToken: existing.accessToken ?? null,\n refreshToken: existing.refreshToken ?? null,\n expiresAt: existing.expiresAt ?? undefined,\n tokenType: existing.tokenType ?? null,\n scope: existing.scope ?? null,\n idToken: existing.idToken ?? null,\n })\n\n await auth.updateAccount({\n userId: user!.id,\n provider: providerId,\n providerAccountId: providerUser.id,\n accessToken: normalizedTokens.accessToken ?? undefined,\n refreshToken: normalizedTokens.refreshToken,\n expiresAt: normalizedTokens.expiresAt,\n tokenType: normalizedTokens.tokenType,\n scope: normalizedTokens.scope,\n idToken: normalizedTokens.idToken,\n })\n await runOnAfterLinkAccount(auth, {\n request,\n providerId,\n userId: user!.id,\n providerUser,\n tokens,\n action: 'update',\n })\n }\n }\n catch (error) {\n console.error('Failed to update account tokens on sign-in:', error)\n }\n }\n\n const sessionToken = await auth.createSession(user.id)\n return buildFinalResponse(request, auth, user, redirectTo, sessionToken, url, cookies, callbackUri)\n}\n","import type { Auth } from '../createAuth'\n\nfunction originAllowed(origin: string, auth: Auth): boolean {\n if (auth.cors === false)\n return false\n const cfg = auth.cors\n if (cfg.allowedOrigins === 'all')\n return true\n if (cfg.allowedOrigins === 'trust') {\n if (auth.trustHosts === 'all')\n return true\n try {\n const u = new URL(origin)\n return auth.trustHosts.includes(u.host) || auth.trustHosts.includes(u.hostname)\n }\n catch {\n return false\n }\n }\n if (cfg.allowedOrigins.includes('*'))\n return true\n try {\n const u = new URL(origin)\n return cfg.allowedOrigins.includes(origin) || cfg.allowedOrigins.includes(u.origin) || cfg.allowedOrigins.includes(u.host) || cfg.allowedOrigins.includes(u.hostname)\n }\n catch {\n return cfg.allowedOrigins.includes(origin)\n }\n}\n\nexport function applyCors(request: Request, response: Response, auth: Auth): Response {\n if (auth.cors === false)\n return response\n\n const origin = request.headers.get('Origin') || request.headers.get('origin')\n if (!origin)\n return response\n\n if (!originAllowed(origin, auth))\n return response\n\n const cfg = auth.cors\n response.headers.set('Vary', 'Origin')\n const allowCreds = cfg.allowCredentials\n const allowOriginValue = (cfg.allowedOrigins === 'all' && !allowCreds) ? '*' : origin\n response.headers.set('Access-Control-Allow-Origin', allowOriginValue)\n if (allowCreds)\n response.headers.set('Access-Control-Allow-Credentials', 'true')\n response.headers.set('Access-Control-Allow-Headers', cfg.allowedHeaders.join(', '))\n response.headers.set('Access-Control-Allow-Methods', cfg.allowedMethods.join(', '))\n if (cfg.exposeHeaders?.length)\n response.headers.set('Access-Control-Expose-Headers', cfg.exposeHeaders.join(', '))\n return response\n}\n\nexport function handlePreflight(request: Request, auth: Auth): Response {\n if (auth.cors === false)\n return new Response(null, { status: 204 })\n\n const origin = request.headers.get('Origin') || request.headers.get('origin')\n const cfg = auth.cors\n const headers: Record<string, string> = {}\n if (origin && originAllowed(origin, auth)) {\n const allowCreds = cfg.allowCredentials\n const allowOriginValue = (cfg.allowedOrigins === 'all' && !allowCreds) ? '*' : origin\n headers['Access-Control-Allow-Origin'] = allowOriginValue\n if (allowCreds)\n headers['Access-Control-Allow-Credentials'] = 'true'\n }\n headers['Access-Control-Allow-Headers'] = cfg.allowedHeaders.join(', ')\n headers['Access-Control-Allow-Methods'] = cfg.allowedMethods.join(', ')\n if (cfg.maxAge != null)\n headers['Access-Control-Max-Age'] = String(cfg.maxAge)\n if (cfg.exposeHeaders?.length)\n headers['Access-Control-Expose-Headers'] = cfg.exposeHeaders.join(', ')\n return new Response(null, { status: 204, headers })\n}\n","import type { Auth } from '../createAuth'\nimport { createOAuthUris } from '../../oauth/utils'\nimport {\n CALLBACK_URI_COOKIE_NAME,\n CLIENT_CHALLENGE_COOKIE_NAME,\n Cookies,\n CSRF_COOKIE_NAME,\n CSRF_MAX_AGE,\n LINKING_TOKEN_COOKIE_NAME,\n parseCookies,\n PKCE_COOKIE_NAME,\n PROVIDER_OPTIONS_COOKIE_NAME,\n} from '../cookies'\nimport { ErrorCodes, GauError } from '../errors'\nimport { json, redirect } from '../index'\n\nexport function verifyRequestOrigin(request: Request, trustHosts: 'all' | string[], development: boolean): boolean {\n if (trustHosts === 'all')\n return true\n\n const origin = request.headers.get('origin')\n\n if (!origin)\n return false\n\n let originHost: string\n try {\n originHost = new URL(origin).host\n }\n catch {\n return false\n }\n\n if (development) {\n const isLocal = originHost.startsWith('localhost') || originHost.startsWith('127.0.0.1')\n if (isLocal)\n return true\n }\n\n const requestUrl = new URL(request.url)\n const requestHost = requestUrl.host\n const requestOrigin = `${requestUrl.protocol}//${requestHost}`\n\n if (origin === requestOrigin)\n return true\n\n return trustHosts.includes(originHost)\n}\n\nexport async function prepareOAuthRedirect(\n request: Request,\n auth: Auth,\n providerId: string,\n linkingToken: string | null,\n): Promise<Response> {\n const provider = auth.providerMap.get(providerId)\n if (!provider)\n throw new GauError(ErrorCodes.PROVIDER_NOT_FOUND)\n\n const { state: originalState, codeVerifier } = createOAuthUris()\n const url = new URL(request.url)\n const redirectTo = url.searchParams.get('redirectTo')\n const profileName = url.searchParams.get('profile')\n const promptParam = url.searchParams.get('prompt')\n\n if (redirectTo) {\n let parsedRedirect: URL\n try {\n if (redirectTo.startsWith('//'))\n throw new Error('Protocol-relative URL not allowed')\n parsedRedirect = new URL(redirectTo, url.origin)\n }\n catch {\n throw new GauError(ErrorCodes.INVALID_REDIRECT_URL, 'Invalid \"redirectTo\" URL', { status: 400 })\n }\n\n const redirectHost = parsedRedirect.host\n const currentHost = new URL(request.url).host\n\n const isSameHost = redirectHost === currentHost\n const isTrusted = auth.trustHosts === 'all' || auth.trustHosts.includes(redirectHost)\n const isHttp = parsedRedirect.protocol === 'http:' || parsedRedirect.protocol === 'https:'\n\n if (isHttp && !isSameHost && !isTrusted)\n throw new GauError(ErrorCodes.UNTRUSTED_HOST)\n }\n\n const state = redirectTo ? `${originalState}.${btoa(redirectTo)}` : originalState\n let callbackUri = url.searchParams.get('callbackUri')\n if (!callbackUri && provider.requiresRedirectUri)\n callbackUri = `${url.origin}${auth.basePath}/callback/${providerId}`\n\n let scopesOverride: string[] | undefined\n let extraParams: Record<string, string> | undefined\n let overrides: any | undefined\n if (profileName) {\n const providerProfiles = auth.profiles?.[providerId] ?? {}\n const selected = providerProfiles[profileName]\n if (!selected)\n throw new GauError(ErrorCodes.UNKNOWN_PROFILE, `Unknown profile \"${profileName}\" for provider \"${providerId}\"`, { status: 400 })\n if (selected.redirectUri)\n callbackUri = selected.redirectUri\n if (selected.scopes)\n scopesOverride = selected.scopes\n if (selected.params)\n extraParams = { ...(selected.params ?? {}) }\n const { tenant, prompt } = selected as any\n if (tenant != null || prompt != null)\n overrides = { ...(overrides ?? {}), tenant, prompt }\n if (!linkingToken && selected.linkOnly === true)\n throw new GauError(ErrorCodes.LINK_ONLY_PROVIDER, 'This profile is link-only. Please link it to an existing account.', { status: 400 })\n }\n\n if (promptParam)\n extraParams = { ...(extraParams ?? {}), prompt: promptParam }\n\n if (!linkingToken && (provider.linkOnly === true))\n throw new GauError(ErrorCodes.LINK_ONLY_PROVIDER)\n\n let authUrl: URL | null\n try {\n authUrl = await provider.getAuthorizationUrl(state, codeVerifier, {\n redirectUri: callbackUri ?? undefined,\n scopes: scopesOverride,\n params: extraParams,\n overrides,\n })\n }\n catch (error) {\n console.error('Error getting authorization URL:', error)\n authUrl = null\n }\n\n if (!authUrl)\n throw new GauError(ErrorCodes.AUTHORIZATION_URL_FAILED, 'Could not create authorization URL', { status: 500 })\n\n const requestCookies = parseCookies(request.headers.get('Cookie'))\n const cookies = new Cookies(requestCookies, auth.cookieOptions)\n\n const temporaryCookieOptions = {\n maxAge: CSRF_MAX_AGE,\n sameSite: auth.development ? 'lax' : 'none',\n secure: !auth.development,\n } as const\n\n cookies.set(CSRF_COOKIE_NAME, originalState, temporaryCookieOptions)\n cookies.set(PKCE_COOKIE_NAME, codeVerifier, temporaryCookieOptions)\n if (linkingToken) {\n cookies.set(LINKING_TOKEN_COOKIE_NAME, linkingToken, temporaryCookieOptions)\n }\n else {\n cookies.delete(LINKING_TOKEN_COOKIE_NAME, {\n sameSite: auth.development ? 'lax' : 'none',\n secure: !auth.development,\n })\n }\n\n if (callbackUri)\n cookies.set(CALLBACK_URI_COOKIE_NAME, callbackUri, temporaryCookieOptions)\n\n const serializedOptions = JSON.stringify({ params: extraParams ?? {}, overrides: overrides ?? {} })\n cookies.set(PROVIDER_OPTIONS_COOKIE_NAME, btoa(serializedOptions), temporaryCookieOptions)\n\n const codeChallenge = url.searchParams.get('code_challenge')\n if (codeChallenge)\n cookies.set(CLIENT_CHALLENGE_COOKIE_NAME, codeChallenge, temporaryCookieOptions)\n\n const redirectParam = url.searchParams.get('redirect')\n\n if (redirectParam === 'false') {\n const response = json({ url: authUrl.toString() })\n cookies.toHeaders().forEach((value, key) => {\n response.headers.append(key, value)\n })\n return response\n }\n\n const response = redirect(authUrl.toString())\n cookies.toHeaders().forEach((value, key) => {\n response.headers.append(key, value)\n })\n\n return response\n}\n","import type { Auth } from '../createAuth'\nimport { ErrorCodes, GauError } from '../errors'\nimport { json } from '../index'\nimport { getSessionTokenFromRequest } from '../utils'\nimport { prepareOAuthRedirect } from './utils'\n\nexport async function handleLink(request: Request, auth: Auth, providerId: string): Promise<Response> {\n const url = new URL(request.url)\n let sessionToken = getSessionTokenFromRequest(request).token\n\n if (!sessionToken)\n sessionToken = url.searchParams.get('token') ?? undefined\n\n if (!sessionToken)\n throw new GauError(ErrorCodes.UNAUTHORIZED)\n\n const session = await auth.validateSession(sessionToken)\n if (!session)\n throw new GauError(ErrorCodes.UNAUTHORIZED)\n\n url.searchParams.delete('token')\n const cleanRequest = new Request(url.toString(), request as Request)\n\n return prepareOAuthRedirect(cleanRequest, auth, providerId, sessionToken)\n}\n\nexport async function handleUnlink(request: Request, auth: Auth, providerId: string): Promise<Response> {\n const sessionToken = getSessionTokenFromRequest(request).token\n\n if (!sessionToken)\n throw new GauError(ErrorCodes.UNAUTHORIZED)\n\n const session = await auth.validateSession(sessionToken)\n if (!session || !session.user)\n throw new GauError(ErrorCodes.UNAUTHORIZED)\n\n const accounts = session.accounts ?? []\n\n if (accounts.length <= 1)\n throw new GauError(ErrorCodes.CANNOT_UNLINK_LAST_ACCOUNT)\n\n const accountToUnlink = accounts.find(a => a.provider === providerId)\n if (!accountToUnlink)\n throw new GauError(ErrorCodes.ACCOUNT_NOT_LINKED, `Provider \"${providerId}\" not linked`)\n\n await auth.unlinkAccount(providerId, accountToUnlink.providerAccountId)\n\n const remainingAccounts = await auth.getAccounts(session.user.id)\n\n // if there are remaining accounts, we need to potentially update the user's primary info\n // TODO: for now we just clear the email\n if (remainingAccounts.length > 0 && session.user.email) {\n try {\n await auth.updateUser({\n id: session.user.id,\n email: null,\n emailVerified: false,\n })\n }\n catch (error) {\n console.error('Failed to clear stale email after unlinking:', error)\n }\n }\n\n return json({ message: 'Account unlinked successfully' })\n}\n","import type { Auth } from '../createAuth'\nimport { Cookies, LINKING_TOKEN_COOKIE_NAME, parseCookies, SESSION_COOKIE_NAME } from '../cookies'\n\nimport { json } from '../index'\nimport { prepareOAuthRedirect } from './utils'\n\nexport async function handleSignIn(request: Request, auth: Auth, providerId: string): Promise<Response> {\n return prepareOAuthRedirect(request, auth, providerId, null)\n}\n\nexport async function handleSignOut(request: Request, auth: Auth): Promise<Response> {\n const requestCookies = parseCookies(request.headers.get('Cookie'))\n const cookies = new Cookies(requestCookies, auth.cookieOptions)\n cookies.delete(SESSION_COOKIE_NAME, {\n sameSite: auth.development ? 'lax' : 'none',\n secure: !auth.development,\n })\n cookies.delete(LINKING_TOKEN_COOKIE_NAME, {\n sameSite: auth.development ? 'lax' : 'none',\n secure: !auth.development,\n })\n\n const response = json({ message: 'Signed out' })\n cookies.toHeaders().forEach((value, key) => {\n response.headers.append(key, value)\n })\n\n return response\n}\n","import type { Auth } from '../createAuth'\nimport { ErrorCodes, GauError } from '../errors'\nimport { json, NULL_SESSION, toClientSession } from '../index'\nimport { getSessionTokenFromRequest } from '../utils'\n\nexport async function handleSession(request: Request, auth: Auth): Promise<Response> {\n const { token: sessionToken } = getSessionTokenFromRequest(request)\n\n const providers = Array.from(auth.providerMap.keys())\n\n if (!sessionToken)\n return json({ ...NULL_SESSION, providers })\n\n try {\n const sessionData = await auth.validateSession(sessionToken)\n\n if (!sessionData)\n return json({ ...NULL_SESSION, providers }, { status: 401 })\n\n return json({ ...toClientSession(sessionData), providers })\n }\n catch (error) {\n console.error('Error validating session:', error)\n throw new GauError(ErrorCodes.SESSION_VALIDATION_FAILED, { cause: error })\n }\n}\n","import type { Auth } from '../createAuth'\nimport { ErrorCodes, GauError } from '../errors'\nimport { json } from '../index'\n\nexport async function handleToken(request: Request, auth: Auth): Promise<Response> {\n if (request.method !== 'POST')\n throw new GauError(ErrorCodes.METHOD_NOT_ALLOWED)\n\n let body: any\n try {\n body = await request.json()\n }\n catch {\n throw new GauError(ErrorCodes.INVALID_REQUEST, 'Invalid JSON body', { status: 400 })\n }\n\n const { code, codeVerifier } = body\n\n if (!code || !codeVerifier)\n throw new GauError(ErrorCodes.INVALID_REQUEST, 'Missing code or codeVerifier', { status: 400 })\n\n const payload = await auth.verifyJWT<{ sub: string, challenge: string }>(code)\n if (!payload)\n throw new GauError(ErrorCodes.TOKEN_EXPIRED, 'Invalid or expired code')\n\n const { sub: userId, challenge } = payload\n\n const encoder = new TextEncoder()\n const data = encoder.encode(codeVerifier)\n const hashBuffer = await crypto.subtle.digest('SHA-256', data)\n const hashArray = Array.from(new Uint8Array(hashBuffer))\n const expectedChallenge = btoa(String.fromCharCode(...hashArray))\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '')\n\n if (challenge !== expectedChallenge)\n throw new GauError(ErrorCodes.CODE_VERIFIER_INVALID)\n\n const sessionToken = await auth.createSession(userId)\n\n return json({ token: sessionToken })\n}\n","import type { Auth } from './createAuth'\nimport { ErrorCodes, GauError, handleError } from './errors'\nimport {\n applyCors,\n handleCallback,\n handleLink,\n handlePreflight,\n handleSession,\n handleSignIn,\n handleSignOut,\n handleToken,\n handleUnlink,\n verifyRequestOrigin,\n} from './handlers'\n\nexport function createHandler(auth: Auth): (request: Request) => Promise<Response> {\n const { basePath } = auth\n\n return async function (request: Request): Promise<Response> {\n if (request.method === 'OPTIONS')\n return handlePreflight(request, auth)\n\n const url = new URL(request.url)\n\n if (!url.pathname.startsWith(basePath)) {\n const error = new GauError(ErrorCodes.NOT_FOUND)\n const response = await handleError(\n { error, request },\n { basePath, onError: auth.onError, errorRedirect: auth.errorRedirect },\n )\n return applyCors(request, response, auth)\n }\n\n try {\n // CSRF protection for POST requests\n if (request.method === 'POST' && !verifyRequestOrigin(request, auth.trustHosts, auth.development)) {\n const origin = request.headers.get('origin') ?? 'unknown'\n const message = auth.development\n ? `Untrusted origin: '${origin}'. Add this origin to 'trustHosts' in createAuth() or ensure you are using 'localhost' or '127.0.0.1' for development.`\n : 'Forbidden'\n throw new GauError(ErrorCodes.FORBIDDEN, message, { status: 403 })\n }\n\n const path = url.pathname.substring(basePath.length)\n const parts = path.split('/').filter(Boolean)\n const action = parts[0]\n\n if (!action)\n throw new GauError(ErrorCodes.NOT_FOUND)\n\n let response: Response\n\n if (request.method === 'GET') {\n if (action === 'session')\n response = await handleSession(request, auth)\n else if (parts.length === 2 && parts[0] === 'link')\n response = await handleLink(request, auth, parts[1] as string)\n else if (parts.length === 2 && parts[0] === 'callback')\n response = await handleCallback(request, auth, parts[1] as string)\n else if (parts.length === 1)\n response = await handleSignIn(request, auth, action)\n else\n throw new GauError(ErrorCodes.NOT_FOUND)\n }\n else if (request.method === 'POST') {\n if (parts.length === 1 && action === 'signout')\n response = await handleSignOut(request, auth)\n else if (parts.length === 1 && action === 'token')\n response = await handleToken(request, auth)\n else if (parts.length === 2 && parts[0] === 'unlink')\n response = await handleUnlink(request, auth, parts[1] as string)\n else\n throw new GauError(ErrorCodes.NOT_FOUND)\n }\n else {\n throw new GauError(ErrorCodes.METHOD_NOT_ALLOWED)\n }\n\n // Add cache headers\n try {\n response.headers.set('Cache-Control', 'no-store, private')\n response.headers.set('Pragma', 'no-cache')\n response.headers.set('Expires', '0')\n }\n catch {}\n\n return applyCors(request, response, auth)\n }\n catch (error) {\n if (error instanceof GauError) {\n const response = await handleError(\n { error, request },\n { basePath, onError: auth.onError, errorRedirect: auth.errorRedirect },\n )\n return applyCors(request, response, auth)\n }\n\n // Unknown error - wrap in GauError\n console.error('Unexpected error in gau handler:', error)\n const gauError = new GauError(\n ErrorCodes.INTERNAL_ERROR,\n { cause: error },\n )\n const response = await handleError(\n { error: gauError, request },\n { basePath, onError: auth.onError, errorRedirect: auth.errorRedirect },\n )\n return applyCors(request, response, auth)\n }\n }\n}\n","export interface User {\n id: string\n name?: string | null\n email?: string | null\n emailVerified?: boolean | null\n image?: string | null\n role?: string | null\n isAdmin?: boolean\n}\n\nexport interface Session {\n id: string\n sub: string\n [key: string]: unknown\n}\n\nexport interface ClientAccount<TProviders extends string = string> {\n provider: TProviders\n providerAccountId: string\n}\n\n/**\n * Client-safe session data.\n */\nexport interface GauSession<TProviders extends string = string> {\n user: User | null\n session: Omit<Session, 'id'> | null\n accounts?: ClientAccount<TProviders>[] | null\n providers?: TProviders[]\n}\n\n/**\n * Full server-side session with complete account data including tokens.\n *\n * Never serialize this to the client - contains sensitive access/refresh tokens.\n */\nexport interface GauServerSession<TProviders extends string = string> {\n user: User | null\n session: Session | null\n accounts?: Account[] | null\n providers?: TProviders[]\n}\n\nexport const NULL_SESSION = {\n user: null,\n session: null,\n accounts: null,\n} as const\n\nexport function toClientSession<TProviders extends string = string>(\n serverSession: GauServerSession<TProviders>,\n): GauSession<TProviders> {\n const safeSession: Omit<Session, 'id'> | null = serverSession.session\n && (({ id: _id, ...rest }) => rest)(serverSession.session)\n\n return {\n user: serverSession.user,\n session: safeSession,\n accounts: serverSession.accounts?.map(acc => ({\n provider: acc.provider as TProviders,\n providerAccountId: acc.providerAccountId,\n })) ?? null,\n providers: serverSession.providers,\n }\n}\n\nexport interface NewUser extends Omit<User, 'id' | 'accounts' | 'isAdmin'> {\n id?: string\n}\n\nexport interface Account {\n userId: string\n provider: string\n providerAccountId: string\n type?: string // e.g. \"oauth\"\n accessToken?: string | null\n refreshToken?: string | null\n expiresAt?: number | null // epoch seconds\n idToken?: string | null\n scope?: string | null\n tokenType?: string | null\n sessionState?: string | null\n}\n\nexport interface NewAccount extends Account {}\n\nexport interface Adapter {\n getUser: (id: string) => Promise<User | null>\n getUserByEmail: (email: string) => Promise<User | null>\n getUserByAccount: (provider: string, providerAccountId: string) => Promise<User | null>\n getAccounts: (userId: string) => Promise<Account[]>\n getUserAndAccounts: (userId: string) => Promise<{ user: User, accounts: Account[] } | null>\n createUser: (data: NewUser) => Promise<User>\n linkAccount: (data: NewAccount) => Promise<void>\n unlinkAccount: (provider: string, providerAccountId: string) => Promise<void>\n updateAccount?: (data: Partial<Account> & { userId: string, provider: string, providerAccountId: string }) => Promise<void>\n updateUser: (data: Partial<User> & { id: string }) => Promise<User>\n deleteUser: (id: string) => Promise<void>\n}\n\nexport class AuthError extends Error {\n override readonly cause?: unknown\n constructor(message: string, cause?: unknown) {\n super(message)\n this.name = 'AuthError'\n this.cause = cause\n }\n}\n\nexport function json<T>(data: T, init: ResponseInit = {}): Response {\n const headers = new Headers(init.headers)\n if (!headers.has('Content-Type'))\n headers.set('Content-Type', 'application/json; charset=utf-8')\n return new Response(JSON.stringify(data), { ...init, headers })\n}\n\nexport function redirect(url: string, status: 302 | 303 = 302): Response {\n return new Response(null, {\n status,\n headers: {\n Location: url,\n },\n })\n}\n\nexport * from './cookies'\nexport * from './createAuth'\nexport * from './errors'\nexport * from './handler'\nexport * from './templates'\nexport * from './utils'\n\nexport const REFRESHED_TOKEN_HEADER = 'X-Refreshed-Token'\n\n/**\n * Helper to check if a session is an impersonation session.\n */\nexport function isImpersonating(session: Session | null): boolean {\n return session?.impersonatedBy != null\n}\n","import { AuthError } from '../core/index'\n\nexport function constantTimeEqual(a: Uint8Array, b: Uint8Array): boolean {\n let diff = a.length ^ b.length\n const len = Math.max(a.length, b.length)\n for (let i = 0; i < len; i++)\n diff |= (a[i] ?? 0) ^ (b[i] ?? 0)\n\n return diff === 0\n}\n\nfunction base64UrlToArray(base64Url: string): Uint8Array {\n const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/')\n const padLength = (4 - (base64.length % 4)) % 4\n const padded = base64.padEnd(base64.length + padLength, '=')\n try {\n const binary_string = atob(padded)\n const len = binary_string.length\n const bytes = new Uint8Array(len)\n for (let i = 0; i < len; i++)\n bytes[i] = binary_string.charCodeAt(i)\n\n return bytes\n }\n catch {\n throw new AuthError('Invalid base64url string')\n }\n}\n\nexport async function deriveKeysFromSecret(secret: string): Promise<{ privateKey: CryptoKey, publicKey: CryptoKey }> {\n try {\n const secretBytes = base64UrlToArray(secret)\n const privateKey = await crypto.subtle.importKey(\n 'pkcs8',\n secretBytes.slice(),\n { name: 'ECDSA', namedCurve: 'P-256' },\n true,\n ['sign'],\n )\n\n const jwk = await crypto.subtle.exportKey('jwk', privateKey)\n delete jwk.d\n jwk.key_ops = ['verify']\n\n const publicKey = await crypto.subtle.importKey(\n 'jwk',\n jwk,\n { name: 'ECDSA', namedCurve: 'P-256' },\n true,\n ['verify'],\n )\n return { privateKey, publicKey }\n }\n catch (error) {\n if (error instanceof AuthError)\n throw error\n throw new AuthError('Invalid secret. Must be a base64url-encoded PKCS#8 private key for ES256. Use `bunx gau secret` to generate one.', error)\n }\n}\n\n/**\n * Convert JWS raw signature (r || s) to DER-encoded format for WebCrypto.\n */\nexport function rawToDer(raw: Uint8Array): Uint8Array {\n if (raw.length !== 64)\n throw new Error('Invalid raw signature length')\n\n let r = raw.slice(0, 32)\n let s = raw.slice(32)\n\n let rOffset = 0\n while (rOffset < r.length - 1 && r[rOffset] === 0) rOffset++\n r = r.slice(rOffset)\n\n let sOffset = 0\n while (sOffset < s.length - 1 && s[sOffset] === 0) sOffset++\n s = s.slice(sOffset)\n\n if (r.length > 0 && r[0]! & 0x80) {\n const rPadded = new Uint8Array(r.length + 1)\n rPadded[0] = 0\n rPadded.set(r, 1)\n r = rPadded\n }\n if (s.length > 0 && s[0]! & 0x80) {\n const sPadded = new Uint8Array(s.length + 1)\n sPadded[0] = 0\n sPadded.set(s, 1)\n s = sPadded\n }\n\n const rLength = r.length\n const sLength = s.length\n const totalLength = 2 + rLength + 2 + sLength\n\n const der = new Uint8Array(2 + totalLength)\n der[0] = 0x30 // SEQUENCE\n der[1] = totalLength\n der[2] = 0x02 // INTEGER\n der[3] = rLength\n der.set(r, 4)\n der[4 + rLength] = 0x02 // INTEGER\n der[5 + rLength] = sLength\n der.set(s, 6 + rLength)\n\n return der\n}\n"],"mappings":"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","names":["parse","serialize","serialize","iat","iss","aud","parse","htmlResponse","error","response","response"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{is as e}from"drizzle-orm";import{MySqlDatabase as t}from"drizzle-orm/mysql-core";import{PgDatabase as r}from"drizzle-orm/pg-core";import{BaseSQLiteDatabase as n}from"drizzle-orm/sqlite-core";import{and as a,eq as c}from"drizzle-orm";function s(e,t){const r=e=>e?{...e}:null;return{getUser:async e=>r(await t.getUser(e)),getUserByEmail:async e=>r(await t.getUserByEmail(e)),getUserByAccount:async(e,n)=>r(await t.getUserByAccount(e,n)),getAccounts:async e=>await t.getAccounts(e),async getUserAndAccounts(e){const n=await t.getUserAndAccounts(e);return n?{user:r(n.user),accounts:n.accounts}:null},async createUser(n){const a=n.id??crypto.randomUUID(),c=await t.createUser(a,{...n,id:a,name:n.name??null,email:n.email??null,image:n.image??null,emailVerified:n.emailVerified??null,...e.role?{role:n.role??null}:{},createdAt:new Date,updatedAt:new Date});return r(c)},async linkAccount(e){await t.linkAccount({type:"oauth",...e})},async unlinkAccount(e,r){await t.unlinkAccount(e,r)},async updateAccount(e){await t.updateAccount(e)},async updateUser(e){const{id:n,...a}=e,c=await t.updateUser(n,{...a,updatedAt:new Date});return r(c)},async deleteUser(e){await t.deleteUser(e)}}}import{and as i,eq as o}from"drizzle-orm";import{sql as u}from"drizzle-orm";async function d(e,t){if("async"===e.session?.mode||"async"===e.mode)return e.transaction(t);e.run(u`BEGIN`);try{const r=await t(e);return e.run(u`COMMIT`),r}catch(t){throw e.run(u`ROLLBACK`),t}}function l(u,l,w){if(e(u,n))return function(e,t,r){return s(t,{getUser:async r=>await e.select().from(t).where(o(t.id,r)).get(),getUserByEmail:async r=>await e.select().from(t).where(o(t.email,r)).get(),async getUserByAccount(n,a){const c=await e.select().from(t).innerJoin(r,o(t.id,r.userId)).where(i(o(r.provider,n),o(r.providerAccountId,a))).get();return c?.users},getAccounts:async t=>await e.select().from(r).where(o(r.userId,t)).all(),async getUserAndAccounts(n){const a=await e.select().from(t).where(o(t.id,n)).leftJoin(r,o(t.id,r.userId)).all();return a.length?{user:a[0].users,accounts:a.map(e=>e.accounts).filter(Boolean)}:null},createUser:async(r,n)=>await d(e,async e=>(await e.insert(t).values(n).run(),await e.select().from(t).where(o(t.id,r)).get())),async linkAccount(t){await e.insert(r).values(t).run()},async unlinkAccount(t,n){await e.delete(r).where(i(o(r.provider,t),o(r.providerAccountId,n))).run()},async updateAccount(t){await e.update(r).set({accessToken:t.accessToken,refreshToken:t.refreshToken,expiresAt:t.expiresAt,idToken:t.idToken,tokenType:t.tokenType,scope:t.scope}).where(i(o(r.userId,t.userId),o(r.provider,t.provider),o(r.providerAccountId,t.providerAccountId))).run()},updateUser:async(r,n)=>await d(e,async e=>(await e.update(t).set(n).where(o(t.id,r)).run(),await e.select().from(t).where(o(t.id,r)).get())),async deleteUser(r){await e.delete(t).where(o(t.id,r)).run()}})}(u,l,w);if(e(u,t))return function(){throw new Error("MySQL adapter is not yet implemented.")}();if(e(u,r))return function(e,t,r){return s(t,{getUser:async r=>(await e.select().from(t).where(c(t.id,r)).limit(1).execute())[0],getUserByEmail:async r=>(await e.select().from(t).where(c(t.email,r)).limit(1).execute())[0],async getUserByAccount(n,s){const i=(await e.select().from(t).innerJoin(r,c(t.id,r.userId)).where(a(c(r.provider,n),c(r.providerAccountId,s))).limit(1).execute())[0];return i?.users},getAccounts:async t=>await e.select().from(r).where(c(r.userId,t)).execute(),async getUserAndAccounts(n){const a=await e.select().from(t).leftJoin(r,c(t.id,r.userId)).where(c(t.id,n)).execute();return a.length?{user:a[0].users,accounts:a.map(e=>e?.accounts).filter(Boolean)}:null},async createUser(r,n){const[a]=await e.insert(t).values(n).returning().execute();return a},async linkAccount(t){await e.insert(r).values(t).execute()},async unlinkAccount(t,n){await e.delete(r).where(a(c(r.provider,t),c(r.providerAccountId,n))).execute()},async updateAccount(t){await e.update(r).set({accessToken:t.accessToken,refreshToken:t.refreshToken,expiresAt:t.expiresAt,idToken:t.idToken,tokenType:t.tokenType,scope:t.scope}).where(a(c(r.userId,t.userId),c(r.provider,t.provider),c(r.providerAccountId,t.providerAccountId))).execute()},async updateUser(r,n){const[a]=await e.update(t).set(n).where(c(t.id,r)).returning().execute();return a},async deleteUser(r){await e.delete(t).where(c(t.id,r)).execute()}})}(u,l,w);throw new Error(`Unsupported database type (${typeof u}) in gau Drizzle adapter.`)}export{l as DrizzleAdapter};//# sourceMappingURL=chunk-V6AIGB33.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapters/drizzle/index.ts","../src/adapters/drizzle/mysql.ts","../src/adapters/drizzle/pg.ts","../src/adapters/drizzle/shared.ts","../src/adapters/drizzle/sqlite.ts","../src/adapters/drizzle/transaction.ts"],"sourcesContent":["import type { Adapter } from '../../core/index'\nimport type { AccountsTable, UsersTable } from './shared'\nimport { is } from 'drizzle-orm'\nimport { MySqlDatabase } from 'drizzle-orm/mysql-core'\nimport { PgDatabase } from 'drizzle-orm/pg-core'\n\nimport { BaseSQLiteDatabase } from 'drizzle-orm/sqlite-core'\nimport { MySqlDrizzleAdapter } from './mysql'\nimport { PostgresDrizzleAdapter } from './pg'\nimport { SQLiteDrizzleAdapter } from './sqlite'\n\nexport function DrizzleAdapter<\n U extends UsersTable,\n A extends AccountsTable,\n>(\n db:\n | BaseSQLiteDatabase<'sync' | 'async', any, any>\n | MySqlDatabase<any, any, any, any>\n | PgDatabase<any, any, any>,\n users: U,\n accounts: A,\n): Adapter {\n if (is(db, BaseSQLiteDatabase))\n return SQLiteDrizzleAdapter(db, users, accounts)\n\n if (is(db, MySqlDatabase))\n // @ts-expect-error Not implemented\n return MySqlDrizzleAdapter(db, users, accounts)\n\n if (is(db, PgDatabase))\n return PostgresDrizzleAdapter(db, users, accounts)\n\n throw new Error(\n `Unsupported database type (${typeof db}) in gau Drizzle adapter.`,\n )\n}\n","// TODO: Implement MySQL adapter for gau\nexport function MySqlDrizzleAdapter(): never {\n throw new Error('MySQL adapter is not yet implemented.')\n}\n","import type { InferInsertModel, InferSelectModel } from 'drizzle-orm'\nimport type { PgDatabase, PgTable } from 'drizzle-orm/pg-core'\nimport type { AccountsTable, UsersTable } from './shared'\nimport { and, eq } from 'drizzle-orm'\nimport { createDrizzleAdapter } from './shared'\n\nexport type { AccountsTable, UsersTable } from './shared'\n\nexport function PostgresDrizzleAdapter<\n DB extends PgDatabase<any, any, any>,\n U extends UsersTable,\n A extends AccountsTable,\n>(db: DB, Users: U, Accounts: A) {\n type DBAccount = InferSelectModel<A>\n type DBInsertAccount = InferInsertModel<A>\n\n return createDrizzleAdapter(Users, {\n async getUser(id) {\n const rows = await db\n .select()\n .from(Users as unknown as PgTable)\n .where(eq(Users.id, id))\n .limit(1)\n .execute()\n return rows[0] as InferSelectModel<U> | undefined\n },\n\n async getUserByEmail(email) {\n const rows = await db\n .select()\n .from(Users as unknown as PgTable)\n .where(eq(Users.email, email))\n .limit(1)\n .execute()\n return rows[0] as InferSelectModel<U> | undefined\n },\n\n async getUserByAccount(provider, providerAccountId) {\n const rows = await db\n .select()\n .from(Users as unknown as PgTable)\n .innerJoin(Accounts as unknown as PgTable, eq(Users.id, Accounts.userId))\n .where(and(\n eq(Accounts.provider, provider),\n eq(Accounts.providerAccountId, providerAccountId),\n ))\n .limit(1)\n .execute()\n const row = rows[0] as { users?: InferSelectModel<U> } | undefined\n return row?.users\n },\n\n async getAccounts(userId) {\n const rows = await db\n .select()\n .from(Accounts as unknown as PgTable)\n .where(eq(Accounts.userId, userId))\n .execute()\n return rows as DBAccount[]\n },\n\n async getUserAndAccounts(userId) {\n const rows = await db\n .select()\n .from(Users as unknown as PgTable)\n .leftJoin(Accounts as unknown as PgTable, eq(Users.id, Accounts.userId))\n .where(eq(Users.id, userId))\n .execute()\n\n if (!rows.length)\n return null\n\n return {\n user: (rows[0] as unknown as { users: InferSelectModel<U> }).users,\n accounts: rows\n .map((r: { accounts?: DBAccount } | undefined) => r?.accounts)\n .filter(Boolean) as DBAccount[],\n }\n },\n\n async createUser(_id, data) {\n const [inserted] = await db\n .insert(Users)\n .values(data)\n .returning()\n .execute()\n\n return inserted\n },\n\n async linkAccount(data) {\n await db\n .insert(Accounts)\n .values(data as DBInsertAccount)\n .execute()\n },\n\n async unlinkAccount(provider, providerAccountId) {\n await db\n .delete(Accounts)\n .where(and(\n eq(Accounts.provider, provider),\n eq(Accounts.providerAccountId, providerAccountId),\n ))\n .execute()\n },\n\n async updateAccount(data) {\n await db\n .update(Accounts)\n .set({\n accessToken: data.accessToken,\n refreshToken: data.refreshToken,\n expiresAt: data.expiresAt,\n idToken: data.idToken,\n tokenType: data.tokenType,\n scope: data.scope,\n } as Partial<DBInsertAccount>)\n .where(and(\n eq(Accounts.userId, data.userId),\n eq(Accounts.provider, data.provider),\n eq(Accounts.providerAccountId, data.providerAccountId),\n ))\n .execute()\n },\n\n async updateUser(id, data) {\n const [updated] = await db\n .update(Users)\n .set(data)\n .where(eq(Users.id, id))\n .returning()\n .execute()\n\n return updated\n },\n\n async deleteUser(id) {\n await db\n .delete(Users)\n .where(eq(Users.id, id))\n .execute()\n },\n })\n}\n","import type { AnyColumn, InferInsertModel, InferSelectModel, Table } from 'drizzle-orm'\nimport type { Account, Adapter, NewAccount, NewUser, User } from '../../core'\n\nexport type UsersTable = Table & {\n id: AnyColumn\n name: AnyColumn\n email: AnyColumn\n image: AnyColumn\n emailVerified: AnyColumn\n role?: AnyColumn\n createdAt: AnyColumn\n updatedAt: AnyColumn\n}\n\nexport type AccountsTable = Table & {\n userId: AnyColumn\n type: AnyColumn\n provider: AnyColumn\n providerAccountId: AnyColumn\n refreshToken: AnyColumn\n accessToken: AnyColumn\n expiresAt: AnyColumn\n tokenType: AnyColumn\n scope: AnyColumn\n idToken: AnyColumn\n sessionState?: AnyColumn\n}\n\ntype UpdateAccountData = Partial<Account> & {\n userId: string\n provider: string\n providerAccountId: string\n}\n\ninterface AdapterHooks<\n U extends UsersTable,\n A extends AccountsTable,\n> {\n getUser: (id: string) => Promise<InferSelectModel<U> | undefined>\n getUserByEmail: (email: string) => Promise<InferSelectModel<U> | undefined>\n getUserByAccount: (provider: string, providerAccountId: string) => Promise<InferSelectModel<U> | undefined>\n getAccounts: (userId: string) => Promise<InferSelectModel<A>[]>\n getUserAndAccounts: (userId: string) => Promise<{\n user: InferSelectModel<U> | null | undefined\n accounts: InferSelectModel<A>[]\n } | null>\n createUser: (id: string, data: InferInsertModel<U>) => Promise<InferSelectModel<U> | undefined>\n linkAccount: (data: InferInsertModel<A>) => Promise<void>\n unlinkAccount: (provider: string, providerAccountId: string) => Promise<void>\n updateAccount: (data: UpdateAccountData) => Promise<void>\n updateUser: (id: string, data: Partial<InferInsertModel<U>>) => Promise<InferSelectModel<U> | undefined>\n deleteUser: (id: string) => Promise<void>\n}\n\nexport function createDrizzleAdapter<\n U extends UsersTable,\n A extends AccountsTable,\n>(Users: U, hooks: AdapterHooks<U, A>): Adapter {\n type DBUser = InferSelectModel<U>\n type DBInsertUser = InferInsertModel<U>\n type DBInsertAccount = InferInsertModel<A>\n\n const toUser = (row: DBUser | undefined | null): User | null =>\n row ? ({ ...(row as any) }) : null\n\n return {\n async getUser(id) {\n return toUser(await hooks.getUser(id))\n },\n\n async getUserByEmail(email) {\n return toUser(await hooks.getUserByEmail(email))\n },\n\n async getUserByAccount(provider, providerAccountId) {\n return toUser(await hooks.getUserByAccount(provider, providerAccountId))\n },\n\n async getAccounts(userId) {\n return await hooks.getAccounts(userId) as Account[]\n },\n\n async getUserAndAccounts(userId) {\n const result = await hooks.getUserAndAccounts(userId)\n if (!result)\n return null\n\n return {\n user: toUser(result.user) as User,\n accounts: result.accounts as Account[],\n }\n },\n\n async createUser(data: NewUser) {\n const id = data.id ?? crypto.randomUUID()\n const result = await hooks.createUser(id, {\n ...data,\n id,\n name: data.name ?? null,\n email: data.email ?? null,\n image: data.image ?? null,\n emailVerified: data.emailVerified ?? null,\n ...(Users.role ? { role: data.role ?? null } : {}),\n createdAt: new Date(),\n updatedAt: new Date(),\n } as DBInsertUser)\n\n return toUser(result) as User\n },\n\n async linkAccount(data: NewAccount) {\n await hooks.linkAccount({\n type: 'oauth',\n ...data,\n } as DBInsertAccount)\n },\n\n async unlinkAccount(provider, providerAccountId) {\n await hooks.unlinkAccount(provider, providerAccountId)\n },\n\n async updateAccount(data) {\n await hooks.updateAccount(data)\n },\n\n async updateUser(partial) {\n const { id, ...rest } = partial\n const result = await hooks.updateUser(id, {\n ...rest,\n updatedAt: new Date(),\n } as Partial<DBInsertUser>)\n\n return toUser(result) as User\n },\n\n async deleteUser(id) {\n await hooks.deleteUser(id)\n },\n }\n}\n","import type { InferInsertModel, InferSelectModel } from 'drizzle-orm'\nimport type { BaseSQLiteDatabase } from 'drizzle-orm/sqlite-core'\nimport type { AccountsTable, UsersTable } from './shared'\nimport { and, eq } from 'drizzle-orm'\nimport { createDrizzleAdapter } from './shared'\nimport { transaction } from './transaction'\n\nexport type { AccountsTable, UsersTable } from './shared'\n\nexport function SQLiteDrizzleAdapter<\n DB extends BaseSQLiteDatabase<'sync' | 'async', any, any>,\n U extends UsersTable,\n A extends AccountsTable,\n>(db: DB, Users: U, Accounts: A) {\n type DBAccount = InferSelectModel<A>\n type DBInsertUser = InferInsertModel<U>\n type DBInsertAccount = InferInsertModel<A>\n\n return createDrizzleAdapter(Users, {\n async getUser(id) {\n return await db\n .select()\n .from(Users)\n .where(eq(Users.id, id))\n .get()\n },\n\n async getUserByEmail(email) {\n return await db\n .select()\n .from(Users)\n .where(eq(Users.email, email))\n .get()\n },\n\n async getUserByAccount(provider, providerAccountId) {\n const result = await db\n .select()\n .from(Users)\n .innerJoin(Accounts, eq(Users.id, Accounts.userId))\n .where(and(eq(Accounts.provider, provider), eq(Accounts.providerAccountId, providerAccountId)))\n .get()\n return result?.users\n },\n\n async getAccounts(userId) {\n return await db\n .select()\n .from(Accounts)\n .where(eq(Accounts.userId, userId))\n .all()\n },\n\n async getUserAndAccounts(userId) {\n const result = await db\n .select()\n .from(Users)\n .where(eq(Users.id, userId))\n .leftJoin(Accounts, eq(Users.id, Accounts.userId))\n .all()\n\n if (!result.length)\n return null\n\n return {\n user: result[0]!.users,\n accounts: result\n .map(row => row.accounts)\n .filter(Boolean) as DBAccount[],\n }\n },\n\n async createUser(id, data) {\n return await transaction(db, async (tx) => {\n await tx\n .insert(Users)\n .values(data as DBInsertUser)\n .run()\n\n return await tx.select().from(Users).where(eq(Users.id, id)).get()\n })\n },\n\n async linkAccount(data) {\n await db\n .insert(Accounts)\n .values(data as DBInsertAccount)\n .run()\n },\n\n async unlinkAccount(provider, providerAccountId) {\n await db\n .delete(Accounts)\n .where(and(eq(Accounts.provider, provider), eq(Accounts.providerAccountId, providerAccountId)))\n .run()\n },\n\n async updateAccount(data) {\n await db\n .update(Accounts)\n .set({\n accessToken: data.accessToken,\n refreshToken: data.refreshToken,\n expiresAt: data.expiresAt,\n idToken: data.idToken,\n tokenType: data.tokenType,\n scope: data.scope,\n })\n .where(and(\n eq(Accounts.userId, data.userId),\n eq(Accounts.provider, data.provider),\n eq(Accounts.providerAccountId, data.providerAccountId),\n ))\n .run()\n },\n\n async updateUser(id, data) {\n return await transaction(db, async (tx) => {\n await tx\n .update(Users)\n .set(data as Partial<DBInsertUser>)\n .where(eq(Users.id, id))\n .run()\n\n return await tx.select().from(Users).where(eq(Users.id, id)).get()\n })\n },\n\n async deleteUser(id) {\n await db.delete(Users).where(eq(Users.id, id)).run()\n },\n })\n}\n","import type { BaseSQLiteDatabase } from 'drizzle-orm/sqlite-core'\nimport { sql } from 'drizzle-orm'\n\n/**\n * A helper to run transactions across both sync (`better-sqlite3`)\n * and async (`libsql`) Drizzle drivers.\n *\n * It checks for the `mode` property on the Drizzle DB instance, which is\n * `'sync'` or `'async'`.\n *\n * @param db The Drizzle database instance.\n * @param callback The function to execute within the transaction.\n */\nexport async function transaction<T>(\n db: BaseSQLiteDatabase<'sync' | 'async', any, any>,\n callback: (\n tx: Omit<typeof db, 'transaction'>,\n ) => Promise<T>,\n): Promise<T> {\n const isAsync = (db as any).session?.mode === 'async' || (db as any).mode === 'async'\n\n if (isAsync)\n return db.transaction(callback)\n\n db.run(sql`BEGIN`)\n try {\n const result = await callback(db)\n db.run(sql`COMMIT`)\n return result\n }\n catch (e) {\n db.run(sql`ROLLBACK`)\n throw e\n }\n}\n"],"mappings":"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","names":["and","eq","eq","and"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{CodeChallengeMethod as e,generateCodeVerifier as t,generateState as n,OAuth2Client as r}from"arctic";function o(){return{state:n(),codeVerifier:t()}}function i(e){const t=new r(e.clientId,e.clientSecret,e.redirectUri??null);return n=>n&&n!==e.redirectUri?new r(e.clientId,e.clientSecret,n):t}function c(e,t){return{...e??{},...t??{}}}function s(e,t,n=[]){const r=new Set(n);for(const[n,o]of Object.entries(t??{}))r.has(n)||null==o||e.searchParams.set(n,String(o));return e}async function a(t){const n=await t.client.createAuthorizationURLWithPKCE(t.authorizationUrl,t.state,e.S256,t.codeVerifier,t.scopes);return s(n,c(t.configParams,t.params),t.omitParamKeys),s(n,t.extraParams),n}async function l(e){const t=new URLSearchParams({client_id:e.clientId,client_secret:e.clientSecret,grant_type:"refresh_token",refresh_token:e.refreshToken});e.scopes?.length&&t.set("scope",e.scopes.join(" "));const n=await fetch(e.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:t}),r=await n.json();if(!n.ok)throw r;return function(e,t){const n="number"==typeof e.expires_in?e.expires_in:"string"==typeof e.expires_in?Number(e.expires_in):void 0,r=Number.isFinite(n)?Math.floor(Date.now()/1e3)+Math.floor(n):null;return{accessToken:e.access_token,refreshToken:e.refresh_token??t,expiresAt:r,idToken:e.id_token??null,tokenType:e.token_type??null,scope:e.scope??null}}(r,e.refreshToken)}export{o as createOAuthUris,i as createOAuthClientResolver,c as mergeOAuthParams,a as createOAuthAuthorizationUrl,l as refreshOAuthAccessToken};//# sourceMappingURL=chunk-VXWI4D7H.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/oauth/utils.ts"],"sourcesContent":["import type { OAuthProviderConfig, RefreshedTokens } from './index'\nimport { CodeChallengeMethod, generateCodeVerifier, generateState, OAuth2Client } from 'arctic'\n\nexport function createOAuthUris() {\n const state = generateState()\n const codeVerifier = generateCodeVerifier()\n\n return {\n state,\n codeVerifier,\n }\n}\n\nexport function createOAuthClientResolver(config: Pick<OAuthProviderConfig, 'clientId' | 'clientSecret' | 'redirectUri'>) {\n const defaultClient = new OAuth2Client(config.clientId, config.clientSecret, config.redirectUri ?? null)\n\n return (redirectUri?: string) => {\n if (!redirectUri || redirectUri === config.redirectUri)\n return defaultClient\n\n return new OAuth2Client(config.clientId, config.clientSecret, redirectUri)\n }\n}\n\nexport function mergeOAuthParams(configParams?: Record<string, string>, optionParams?: Record<string, string>) {\n return { ...(configParams ?? {}), ...(optionParams ?? {}) }\n}\n\nexport function applyOAuthParams(url: URL, params?: Record<string, string>, omitKeys: string[] = []) {\n const omitted = new Set(omitKeys)\n\n for (const [key, value] of Object.entries(params ?? {})) {\n if (!omitted.has(key) && value != null)\n url.searchParams.set(key, String(value))\n }\n\n return url\n}\n\nexport async function createOAuthAuthorizationUrl(options: {\n client: OAuth2Client\n authorizationUrl: string\n state: string\n codeVerifier: string\n scopes: string[]\n configParams?: Record<string, string>\n params?: Record<string, string>\n extraParams?: Record<string, string>\n omitParamKeys?: string[]\n}) {\n const url = await options.client.createAuthorizationURLWithPKCE(\n options.authorizationUrl,\n options.state,\n CodeChallengeMethod.S256,\n options.codeVerifier,\n options.scopes,\n )\n\n applyOAuthParams(url, mergeOAuthParams(options.configParams, options.params), options.omitParamKeys)\n applyOAuthParams(url, options.extraParams)\n\n return url\n}\n\nexport function normalizeRefreshedTokens(tokens: Record<string, any>, refreshToken: string): RefreshedTokens {\n const expiresIn = typeof tokens.expires_in === 'number'\n ? tokens.expires_in\n : typeof tokens.expires_in === 'string'\n ? Number(tokens.expires_in)\n : undefined\n const expiresAt = Number.isFinite(expiresIn)\n ? Math.floor(Date.now() / 1000) + Math.floor(expiresIn as number)\n : null\n\n return {\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token ?? refreshToken,\n expiresAt,\n idToken: tokens.id_token ?? null,\n tokenType: tokens.token_type ?? null,\n scope: tokens.scope ?? null,\n }\n}\n\nexport async function refreshOAuthAccessToken(options: {\n tokenUrl: string\n clientId: string\n clientSecret: string\n refreshToken: string\n scopes?: string[]\n}) {\n const body = new URLSearchParams({\n client_id: options.clientId,\n client_secret: options.clientSecret,\n grant_type: 'refresh_token',\n refresh_token: options.refreshToken,\n })\n\n if (options.scopes?.length)\n body.set('scope', options.scopes.join(' '))\n\n const response = await fetch(options.tokenUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body,\n })\n const json = await response.json() as Record<string, any>\n\n if (!response.ok)\n throw json\n\n return normalizeRefreshedTokens(json, options.refreshToken)\n}\n"],"mappings":";AACA,SAAS,qBAAqB,sBAAsB,eAAe,oBAAoB;AAEhF,SAAS,kBAAkB;AAChC,QAAM,QAAQ,cAAc;AAC5B,QAAM,eAAe,qBAAqB;AAE1C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,0BAA0B,QAAgF;AACxH,QAAM,gBAAgB,IAAI,aAAa,OAAO,UAAU,OAAO,cAAc,OAAO,eAAe,IAAI;AAEvG,SAAO,CAAC,gBAAyB;AAC/B,QAAI,CAAC,eAAe,gBAAgB,OAAO;AACzC,aAAO;AAET,WAAO,IAAI,aAAa,OAAO,UAAU,OAAO,cAAc,WAAW;AAAA,EAC3E;AACF;AAEO,SAAS,iBAAiB,cAAuC,cAAuC;AAC7G,SAAO,EAAE,GAAI,gBAAgB,CAAC,GAAI,GAAI,gBAAgB,CAAC,EAAG;AAC5D;AAEO,SAAS,iBAAiB,KAAU,QAAiC,WAAqB,CAAC,GAAG;AACnG,QAAM,UAAU,IAAI,IAAI,QAAQ;AAEhC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,UAAU,CAAC,CAAC,GAAG;AACvD,QAAI,CAAC,QAAQ,IAAI,GAAG,KAAK,SAAS;AAChC,UAAI,aAAa,IAAI,KAAK,OAAO,KAAK,CAAC;AAAA,EAC3C;AAEA,SAAO;AACT;AAEA,eAAsB,4BAA4B,SAU/C;AACD,QAAM,MAAM,MAAM,QAAQ,OAAO;AAAA,IAC/B,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,oBAAoB;AAAA,IACpB,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV;AAEA,mBAAiB,KAAK,iBAAiB,QAAQ,cAAc,QAAQ,MAAM,GAAG,QAAQ,aAAa;AACnG,mBAAiB,KAAK,QAAQ,WAAW;AAEzC,SAAO;AACT;AAEO,SAAS,yBAAyB,QAA6B,cAAuC;AAC3G,QAAM,YAAY,OAAO,OAAO,eAAe,WAC3C,OAAO,aACP,OAAO,OAAO,eAAe,WAC3B,OAAO,OAAO,UAAU,IACxB;AACN,QAAM,YAAY,OAAO,SAAS,SAAS,IACvC,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,IAAI,KAAK,MAAM,SAAmB,IAC9D;AAEJ,SAAO;AAAA,IACL,aAAa,OAAO;AAAA,IACpB,cAAc,OAAO,iBAAiB;AAAA,IACtC;AAAA,IACA,SAAS,OAAO,YAAY;AAAA,IAC5B,WAAW,OAAO,cAAc;AAAA,IAChC,OAAO,OAAO,SAAS;AAAA,EACzB;AACF;AAEA,eAAsB,wBAAwB,SAM3C;AACD,QAAM,OAAO,IAAI,gBAAgB;AAAA,IAC/B,WAAW,QAAQ;AAAA,IACnB,eAAe,QAAQ;AAAA,IACvB,YAAY;AAAA,IACZ,eAAe,QAAQ;AAAA,EACzB,CAAC;AAED,MAAI,QAAQ,QAAQ;AAClB,SAAK,IAAI,SAAS,QAAQ,OAAO,KAAK,GAAG,CAAC;AAE5C,QAAM,WAAW,MAAM,MAAM,QAAQ,UAAU;AAAA,IAC7C,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,gBAAgB;AAAA,IAClB;AAAA,IACA;AAAA,EACF,CAAC;AACD,QAAM,OAAO,MAAM,SAAS,KAAK;AAEjC,MAAI,CAAC,SAAS;AACZ,UAAM;AAER,SAAO,yBAAyB,MAAM,QAAQ,YAAY;AAC5D;","names":[]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Adapter } from '../../core/index';
|
|
2
|
-
import type { AccountsTable, UsersTable } from './
|
|
2
|
+
import type { AccountsTable, UsersTable } from './shared';
|
|
3
3
|
import { MySqlDatabase } from 'drizzle-orm/mysql-core';
|
|
4
4
|
import { PgDatabase } from 'drizzle-orm/pg-core';
|
|
5
5
|
import { BaseSQLiteDatabase } from 'drizzle-orm/sqlite-core';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{DrizzleAdapter as o}from"../../../chunk-
|
|
1
|
+
import{DrizzleAdapter as o}from"../../../chunk-V6AIGB33.js";export{o as DrizzleAdapter};//# sourceMappingURL=index.js.map
|
|
@@ -1,28 +1,5 @@
|
|
|
1
|
-
import type { AnyColumn, Table } from 'drizzle-orm';
|
|
2
1
|
import type { PgDatabase } from 'drizzle-orm/pg-core';
|
|
3
|
-
import type {
|
|
4
|
-
export type UsersTable
|
|
5
|
-
|
|
6
|
-
name: AnyColumn;
|
|
7
|
-
email: AnyColumn;
|
|
8
|
-
image: AnyColumn;
|
|
9
|
-
emailVerified: AnyColumn;
|
|
10
|
-
role?: AnyColumn;
|
|
11
|
-
createdAt: AnyColumn;
|
|
12
|
-
updatedAt: AnyColumn;
|
|
13
|
-
};
|
|
14
|
-
export type AccountsTable = Table & {
|
|
15
|
-
userId: AnyColumn;
|
|
16
|
-
type: AnyColumn;
|
|
17
|
-
provider: AnyColumn;
|
|
18
|
-
providerAccountId: AnyColumn;
|
|
19
|
-
refreshToken: AnyColumn;
|
|
20
|
-
accessToken: AnyColumn;
|
|
21
|
-
expiresAt: AnyColumn;
|
|
22
|
-
tokenType: AnyColumn;
|
|
23
|
-
scope: AnyColumn;
|
|
24
|
-
idToken: AnyColumn;
|
|
25
|
-
sessionState?: AnyColumn;
|
|
26
|
-
};
|
|
27
|
-
export declare function PostgresDrizzleAdapter<DB extends PgDatabase<any, any, any>, U extends UsersTable, A extends AccountsTable>(db: DB, Users: U, Accounts: A): Adapter;
|
|
2
|
+
import type { AccountsTable, UsersTable } from './shared';
|
|
3
|
+
export type { AccountsTable, UsersTable } from './shared';
|
|
4
|
+
export declare function PostgresDrizzleAdapter<DB extends PgDatabase<any, any, any>, U extends UsersTable, A extends AccountsTable>(db: DB, Users: U, Accounts: A): import("../..").Adapter;
|
|
28
5
|
//# sourceMappingURL=pg.d.ts.map
|