@civic/auth 0.11.1-beta.0 → 0.11.1-beta.1
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/lib/logger.d.ts +1 -0
- package/dist/lib/logger.d.ts.map +1 -1
- package/dist/lib/logger.js +1 -0
- package/dist/lib/logger.js.map +1 -1
- package/dist/nextjs/routeHandler.js +1 -1
- package/dist/nextjs/routeHandler.js.map +1 -1
- package/dist/server/ServerAuthenticationResolver.d.ts.map +1 -1
- package/dist/server/ServerAuthenticationResolver.js +44 -52
- package/dist/server/ServerAuthenticationResolver.js.map +1 -1
- package/dist/shared/lib/AuthenticationRefresherImpl.d.ts.map +1 -1
- package/dist/shared/lib/AuthenticationRefresherImpl.js +28 -21
- package/dist/shared/lib/AuthenticationRefresherImpl.js.map +1 -1
- package/dist/shared/lib/BrowserAuthenticationRefresher.d.ts.map +1 -1
- package/dist/shared/lib/BrowserAuthenticationRefresher.js +6 -0
- package/dist/shared/lib/BrowserAuthenticationRefresher.js.map +1 -1
- package/dist/shared/version.d.ts +1 -1
- package/dist/shared/version.js +1 -1
- package/dist/shared/version.js.map +1 -1
- package/dist/vanillajs/auth/BackendAuthenticationRefresher.d.ts.map +1 -1
- package/dist/vanillajs/auth/BackendAuthenticationRefresher.js +7 -1
- package/dist/vanillajs/auth/BackendAuthenticationRefresher.js.map +1 -1
- package/dist/vanillajs/auth/SessionManager.d.ts.map +1 -1
- package/dist/vanillajs/auth/SessionManager.js +3 -8
- package/dist/vanillajs/auth/SessionManager.js.map +1 -1
- package/dist/vanillajs/auth/TokenRefresher.d.ts +10 -0
- package/dist/vanillajs/auth/TokenRefresher.d.ts.map +1 -1
- package/dist/vanillajs/auth/TokenRefresher.js +68 -5
- package/dist/vanillajs/auth/TokenRefresher.js.map +1 -1
- package/package.json +1 -1
- package/dist/nextjs/NextClientAuthenticationRefresher.d.ts +0 -8
- package/dist/nextjs/NextClientAuthenticationRefresher.d.ts.map +0 -1
- package/dist/nextjs/NextClientAuthenticationRefresher.js +0 -24
- package/dist/nextjs/NextClientAuthenticationRefresher.js.map +0 -1
- package/dist/nextjs/NextServerAuthenticationRefresherImpl.d.ts +0 -12
- package/dist/nextjs/NextServerAuthenticationRefresherImpl.d.ts.map +0 -1
- package/dist/nextjs/NextServerAuthenticationRefresherImpl.js +0 -25
- package/dist/nextjs/NextServerAuthenticationRefresherImpl.js.map +0 -1
package/dist/lib/logger.d.ts
CHANGED
package/dist/lib/logger.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,MAAM;IACrB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IACjD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;CAClD;AAsCD,eAAO,MAAM,YAAY,cAAe,MAAM,KAAG,MACrB,CAAC;AAG7B,eAAO,MAAM,OAAO
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,MAAM;IACrB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IACjD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;CAClD;AAsCD,eAAO,MAAM,YAAY,cAAe,MAAM,KAAG,MACrB,CAAC;AAG7B,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgCV,CAAC"}
|
package/dist/lib/logger.js
CHANGED
package/dist/lib/logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,YAAY,GAAG,aAAa,CAAC;AASnC,MAAM,WAAW;IACP,WAAW,CAAiB;IAC5B,UAAU,CAAiB;IAC3B,UAAU,CAAiB;IAC3B,WAAW,CAAiB;IAEpC,YAAY,SAAiB;QAC3B,+CAA+C;QAC/C,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC,GAAG,YAAY,IAAI,SAAS,QAAQ,CAAC,CAAC;QAC/D,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC,GAAG,YAAY,IAAI,SAAS,OAAO,CAAC,CAAC;QAC7D,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC,GAAG,YAAY,IAAI,SAAS,OAAO,CAAC,CAAC;QAC7D,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC,GAAG,YAAY,IAAI,SAAS,QAAQ,CAAC,CAAC;QAE/D,IAAI,CAAC,WAAW,CAAC,KAAK,GAAG,GAAG,CAAC;QAC7B,IAAI,CAAC,UAAU,CAAC,KAAK,GAAG,GAAG,CAAC;QAC5B,IAAI,CAAC,UAAU,CAAC,KAAK,GAAG,GAAG,CAAC;QAC5B,IAAI,CAAC,WAAW,CAAC,KAAK,GAAG,GAAG,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,GAAG,IAAe;QACvC,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;IACrC,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,GAAG,IAAe;QACtC,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;IACpC,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,GAAG,IAAe;QACtC,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;IACpC,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,GAAG,IAAe;QACvC,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;IACrC,CAAC;CACF;AAED,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,SAAiB,EAAU,EAAE,CACxD,IAAI,WAAW,CAAC,SAAS,CAAC,CAAC;AAE7B,4DAA4D;AAC5D,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,2BAA2B;IAC3B,MAAM,EAAE;QACN,MAAM,EAAE,YAAY,CAAC,YAAY,CAAC;QAClC,UAAU,EAAE,YAAY,CAAC,gBAAgB,CAAC;QAC1C,QAAQ,EAAE;YACR,IAAI,EAAE,YAAY,CAAC,mBAAmB,CAAC;SACxC;QACD,OAAO,EAAE,YAAY,CAAC,aAAa,CAAC;QACpC,KAAK,EAAE,YAAY,CAAC,YAAY,CAAC;QACjC,SAAS,EAAE,YAAY,CAAC,gBAAgB,CAAC;KAC1C;IACD,yBAAyB;IACzB,KAAK,EAAE;QACL,UAAU,EAAE,YAAY,CAAC,kBAAkB,CAAC;QAC5C,KAAK,EAAE,YAAY,CAAC,aAAa,CAAC;QAClC,OAAO,EAAE,YAAY,CAAC,eAAe,CAAC;KACvC;IACD,gCAAgC;IAChC,WAAW,EAAE;QACX,MAAM,EAAE,YAAY,CAAC,qBAAqB,CAAC;QAC3C,QAAQ,EAAE;YACR,IAAI,EAAE,YAAY,CAAC,4BAA4B,CAAC;SACjD;KACF;IACD,2BAA2B;IAC3B,QAAQ,EAAE;QACR,UAAU,EAAE,YAAY,CAAC,kBAAkB,CAAC;QAC5C,OAAO,EAAE,YAAY,CAAC,eAAe,CAAC;KACvC;IACD,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC;CACtB,CAAC","sourcesContent":["import debug from \"debug\";\n\nconst PACKAGE_NAME = \"@civic/auth\";\n\nexport interface Logger {\n debug(message: string, ...args: unknown[]): void;\n info(message: string, ...args: unknown[]): void;\n warn(message: string, ...args: unknown[]): void;\n error(message: string, ...args: unknown[]): void;\n}\n\nclass DebugLogger implements Logger {\n private debugLogger: debug.Debugger;\n private infoLogger: debug.Debugger;\n private warnLogger: debug.Debugger;\n private errorLogger: debug.Debugger;\n\n constructor(namespace: string) {\n // Format: @org/package:library:component:level\n this.debugLogger = debug(`${PACKAGE_NAME}:${namespace}:debug`);\n this.infoLogger = debug(`${PACKAGE_NAME}:${namespace}:info`);\n this.warnLogger = debug(`${PACKAGE_NAME}:${namespace}:warn`);\n this.errorLogger = debug(`${PACKAGE_NAME}:${namespace}:error`);\n\n this.debugLogger.color = \"4\";\n this.infoLogger.color = \"2\";\n this.warnLogger.color = \"3\";\n this.errorLogger.color = \"1\";\n }\n\n debug(message: string, ...args: unknown[]): void {\n this.debugLogger(message, ...args);\n }\n\n info(message: string, ...args: unknown[]): void {\n this.infoLogger(message, ...args);\n }\n\n warn(message: string, ...args: unknown[]): void {\n this.warnLogger(message, ...args);\n }\n\n error(message: string, ...args: unknown[]): void {\n this.errorLogger(message, ...args);\n }\n}\n\nexport const createLogger = (namespace: string): Logger =>\n new DebugLogger(namespace);\n\n// Pre-configured loggers for different parts of the package\nexport const loggers = {\n // Next.js specific loggers\n nextjs: {\n routes: createLogger(\"api:routes\"),\n middleware: createLogger(\"api:middleware\"),\n handlers: {\n auth: createLogger(\"api:handlers:auth\"),\n },\n actions: createLogger(\"api:actions\"),\n hooks: createLogger(\"next:hooks\"),\n providers: createLogger(\"next:providers\"),\n },\n // React specific loggers\n react: {\n components: createLogger(\"react:components\"),\n hooks: createLogger(\"react:hooks\"),\n context: createLogger(\"react:context\"),\n },\n // React Router specific loggers\n reactRouter: {\n routes: createLogger(\"react-router:routes\"),\n handlers: {\n auth: createLogger(\"react-router:handlers:auth\"),\n },\n },\n // Shared utilities loggers\n services: {\n validation: createLogger(\"utils:validation\"),\n network: createLogger(\"utils:network\"),\n },\n server: createLogger(\"server\"),\n} as const;\n"]}
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,YAAY,GAAG,aAAa,CAAC;AASnC,MAAM,WAAW;IACP,WAAW,CAAiB;IAC5B,UAAU,CAAiB;IAC3B,UAAU,CAAiB;IAC3B,WAAW,CAAiB;IAEpC,YAAY,SAAiB;QAC3B,+CAA+C;QAC/C,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC,GAAG,YAAY,IAAI,SAAS,QAAQ,CAAC,CAAC;QAC/D,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC,GAAG,YAAY,IAAI,SAAS,OAAO,CAAC,CAAC;QAC7D,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC,GAAG,YAAY,IAAI,SAAS,OAAO,CAAC,CAAC;QAC7D,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC,GAAG,YAAY,IAAI,SAAS,QAAQ,CAAC,CAAC;QAE/D,IAAI,CAAC,WAAW,CAAC,KAAK,GAAG,GAAG,CAAC;QAC7B,IAAI,CAAC,UAAU,CAAC,KAAK,GAAG,GAAG,CAAC;QAC5B,IAAI,CAAC,UAAU,CAAC,KAAK,GAAG,GAAG,CAAC;QAC5B,IAAI,CAAC,WAAW,CAAC,KAAK,GAAG,GAAG,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,GAAG,IAAe;QACvC,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;IACrC,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,GAAG,IAAe;QACtC,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;IACpC,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,GAAG,IAAe;QACtC,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;IACpC,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,GAAG,IAAe;QACvC,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;IACrC,CAAC;CACF;AAED,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,SAAiB,EAAU,EAAE,CACxD,IAAI,WAAW,CAAC,SAAS,CAAC,CAAC;AAE7B,4DAA4D;AAC5D,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,2BAA2B;IAC3B,MAAM,EAAE;QACN,MAAM,EAAE,YAAY,CAAC,YAAY,CAAC;QAClC,UAAU,EAAE,YAAY,CAAC,gBAAgB,CAAC;QAC1C,QAAQ,EAAE;YACR,IAAI,EAAE,YAAY,CAAC,mBAAmB,CAAC;SACxC;QACD,OAAO,EAAE,YAAY,CAAC,aAAa,CAAC;QACpC,KAAK,EAAE,YAAY,CAAC,YAAY,CAAC;QACjC,SAAS,EAAE,YAAY,CAAC,gBAAgB,CAAC;KAC1C;IACD,yBAAyB;IACzB,KAAK,EAAE;QACL,UAAU,EAAE,YAAY,CAAC,kBAAkB,CAAC;QAC5C,KAAK,EAAE,YAAY,CAAC,aAAa,CAAC;QAClC,OAAO,EAAE,YAAY,CAAC,eAAe,CAAC;KACvC;IACD,gCAAgC;IAChC,WAAW,EAAE;QACX,MAAM,EAAE,YAAY,CAAC,qBAAqB,CAAC;QAC3C,QAAQ,EAAE;YACR,IAAI,EAAE,YAAY,CAAC,4BAA4B,CAAC;SACjD;KACF;IACD,2BAA2B;IAC3B,QAAQ,EAAE;QACR,UAAU,EAAE,YAAY,CAAC,kBAAkB,CAAC;QAC5C,OAAO,EAAE,YAAY,CAAC,eAAe,CAAC;QACtC,OAAO,EAAE,YAAY,CAAC,eAAe,CAAC;KACvC;IACD,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC;CACtB,CAAC","sourcesContent":["import debug from \"debug\";\n\nconst PACKAGE_NAME = \"@civic/auth\";\n\nexport interface Logger {\n debug(message: string, ...args: unknown[]): void;\n info(message: string, ...args: unknown[]): void;\n warn(message: string, ...args: unknown[]): void;\n error(message: string, ...args: unknown[]): void;\n}\n\nclass DebugLogger implements Logger {\n private debugLogger: debug.Debugger;\n private infoLogger: debug.Debugger;\n private warnLogger: debug.Debugger;\n private errorLogger: debug.Debugger;\n\n constructor(namespace: string) {\n // Format: @org/package:library:component:level\n this.debugLogger = debug(`${PACKAGE_NAME}:${namespace}:debug`);\n this.infoLogger = debug(`${PACKAGE_NAME}:${namespace}:info`);\n this.warnLogger = debug(`${PACKAGE_NAME}:${namespace}:warn`);\n this.errorLogger = debug(`${PACKAGE_NAME}:${namespace}:error`);\n\n this.debugLogger.color = \"4\";\n this.infoLogger.color = \"2\";\n this.warnLogger.color = \"3\";\n this.errorLogger.color = \"1\";\n }\n\n debug(message: string, ...args: unknown[]): void {\n this.debugLogger(message, ...args);\n }\n\n info(message: string, ...args: unknown[]): void {\n this.infoLogger(message, ...args);\n }\n\n warn(message: string, ...args: unknown[]): void {\n this.warnLogger(message, ...args);\n }\n\n error(message: string, ...args: unknown[]): void {\n this.errorLogger(message, ...args);\n }\n}\n\nexport const createLogger = (namespace: string): Logger =>\n new DebugLogger(namespace);\n\n// Pre-configured loggers for different parts of the package\nexport const loggers = {\n // Next.js specific loggers\n nextjs: {\n routes: createLogger(\"api:routes\"),\n middleware: createLogger(\"api:middleware\"),\n handlers: {\n auth: createLogger(\"api:handlers:auth\"),\n },\n actions: createLogger(\"api:actions\"),\n hooks: createLogger(\"next:hooks\"),\n providers: createLogger(\"next:providers\"),\n },\n // React specific loggers\n react: {\n components: createLogger(\"react:components\"),\n hooks: createLogger(\"react:hooks\"),\n context: createLogger(\"react:context\"),\n },\n // React Router specific loggers\n reactRouter: {\n routes: createLogger(\"react-router:routes\"),\n handlers: {\n auth: createLogger(\"react-router:handlers:auth\"),\n },\n },\n // Shared utilities loggers\n services: {\n validation: createLogger(\"utils:validation\"),\n network: createLogger(\"utils:network\"),\n refresh: createLogger(\"utils:refresh\"),\n },\n server: createLogger(\"server\"),\n} as const;\n"]}
|
|
@@ -57,7 +57,7 @@ const createCivicAuth = (request, config) => {
|
|
|
57
57
|
? resolvedConfig.logoutCallbackUrl
|
|
58
58
|
: CivicAuth.toAbsoluteUrl(urlDetectionRequest, resolvedConfig.logoutCallbackUrl, appUrl);
|
|
59
59
|
const civicAuth = new CivicAuth(cookieStorage, {
|
|
60
|
-
|
|
60
|
+
disableRefresh: resolvedConfig.disableRefresh,
|
|
61
61
|
clientId: resolvedConfig.clientId,
|
|
62
62
|
redirectUrl: absoluteCallbackUrl,
|
|
63
63
|
oauthServer: resolvedConfig.oauthServer,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routeHandler.js","sourceRoot":"","sources":["../../src/nextjs/routeHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import { CivicAuth, type UrlDetectionRequest } from \"@civic/auth/server\";\nimport { LOGOUT_SUCCESS_TEXT } from \"@/constants.js\";\nimport { loggers } from \"@/lib/logger.js\";\nimport { displayModeFromState } from \"@/lib/oauth.js\";\nimport type { AuthConfig } from \"@/nextjs/config.js\";\nimport { resolveAuthConfig } from \"@/nextjs/config.js\";\nimport { clearAuthCookies, NextjsCookieStorage } from \"@/nextjs/cookies.js\";\nimport { CodeVerifier, UserStorage } from \"@/shared/lib/types.js\";\nimport { revalidatePath } from \"next/cache.js\";\nimport type { NextRequest } from \"next/server.js\";\nimport { NextResponse } from \"next/server.js\";\nimport { prependBasePath, redirectWithBasePath } from \"./utils.js\";\n\nconst logger = loggers.nextjs.handlers.auth;\n\nclass AuthError extends Error {\n constructor(\n message: string,\n public readonly status: number = 401,\n ) {\n super(message);\n this.name = \"AuthError\";\n }\n}\n\n/**\n * Helper to convert NextRequest to UrlDetectionRequest for framework-agnostic URL handling\n */\nconst toUrlDetectionRequest = (request: NextRequest): UrlDetectionRequest => ({\n url: request.url,\n headers: Object.fromEntries(request.headers.entries()),\n searchParams: {\n get: (name: string) => request.nextUrl.searchParams.get(name),\n },\n cookies: {\n get: (name: string) => request.cookies.get(name),\n },\n});\n\n/**\n * Helper to create CivicAuth instance for a request\n * Now handles appUrl detection for proxy environments\n */\nconst createCivicAuth = (request: NextRequest, config: AuthConfig) => {\n const resolvedConfig = resolveAuthConfig(config);\n const cookieStorage = new NextjsCookieStorage({\n ...resolvedConfig.cookies?.tokens,\n [UserStorage.USER]: resolvedConfig.cookies?.user,\n });\n\n // Convert to framework-agnostic request format\n const urlDetectionRequest = toUrlDetectionRequest(request);\n\n // Get appUrl from client (for proxy environments)\n const clientAppUrl = CivicAuth.getAppUrl(urlDetectionRequest);\n\n // Use baseUrl from config, then client appUrl, then request origin\n // This matches the main branch priority: config > client > request\n const appUrl =\n resolvedConfig.baseUrl ||\n clientAppUrl ||\n new URL(urlDetectionRequest.url).origin;\n\n // Build absolute URLs using detected appUrl or request origin\n const absoluteCallbackUrl = resolvedConfig.callbackUrl.startsWith(\"http\")\n ? resolvedConfig.callbackUrl\n : CivicAuth.toAbsoluteUrl(\n urlDetectionRequest,\n resolvedConfig.callbackUrl,\n appUrl,\n );\n const absoluteLogoutCallbackUrl = resolvedConfig.logoutCallbackUrl.startsWith(\n \"http\",\n )\n ? resolvedConfig.logoutCallbackUrl\n : CivicAuth.toAbsoluteUrl(\n urlDetectionRequest,\n resolvedConfig.logoutCallbackUrl,\n appUrl,\n );\n\n const civicAuth = new CivicAuth(cookieStorage, {\n ...resolvedConfig,\n clientId: resolvedConfig.clientId,\n redirectUrl: absoluteCallbackUrl,\n oauthServer: resolvedConfig.oauthServer,\n postLogoutRedirectUrl: absoluteLogoutCallbackUrl,\n loginSuccessUrl: request.url,\n });\n\n return {\n civicAuth,\n cookieStorage,\n appUrl, // Return appUrl for use in other functions\n urlDetectionRequest, // Return for use in handlers\n };\n};\n\n/**\n * Login handler - backend OAuth login initiation endpoint\n * Uses CivicAuth.buildLoginUrl()\n */\nasync function handleLogin(\n request: NextRequest,\n config: AuthConfig,\n): Promise<NextResponse> {\n const resolvedConfigs = resolveAuthConfig(config);\n\n try {\n const frontendState = request.nextUrl.searchParams.get(\"state\");\n\n // Store appUrl in cookie if provided as query parameter\n const appUrlFromQuery = request.nextUrl.searchParams.get(\"appUrl\");\n if (appUrlFromQuery) {\n const cookieStorage = new NextjsCookieStorage(\n resolvedConfigs.cookies?.tokens ?? {},\n );\n await cookieStorage.set(CodeVerifier.APP_URL, appUrlFromQuery);\n }\n\n const { civicAuth } = createCivicAuth(request, resolvedConfigs);\n\n const url = await civicAuth.buildLoginUrl({\n state: frontendState || undefined,\n });\n\n logger.info(\"[LOGIN_HANDLER] Redirecting to OAuth login URL\", {\n loginUrl: url.toString(),\n });\n\n return NextResponse.redirect(url.toString());\n } catch (error) {\n logger.error(\"[LOGIN_HANDLER] Backend login error:\", error);\n const urlDetectionRequest = toUrlDetectionRequest(request);\n const appUrl = CivicAuth.getAppUrl(urlDetectionRequest);\n return NextResponse.redirect(\n CivicAuth.toAbsoluteUrl(\n urlDetectionRequest,\n \"/?error=login_failed\",\n appUrl,\n ),\n );\n }\n}\n\nasync function handleRefresh(\n request: NextRequest,\n config: AuthConfig,\n): Promise<NextResponse> {\n const resolvedConfigs = resolveAuthConfig(config);\n\n try {\n const { civicAuth } = createCivicAuth(request, resolvedConfigs);\n\n await civicAuth.refreshTokens();\n\n logger.info(\"[REFRESH_HANDLER] Tokens refreshed successfully\");\n\n return NextResponse.json({\n status: \"success\",\n message: \"Tokens refreshed\",\n });\n } catch (error) {\n logger.error(\"[REFRESH_HANDLER] Token refresh error:\", error);\n return NextResponse.json(\n { error: \"Token refresh failed\" },\n { status: 500 },\n );\n }\n}\n\nasync function handleCallback(\n request: NextRequest,\n config: AuthConfig,\n): Promise<NextResponse> {\n const resolvedConfigs = resolveAuthConfig(config);\n const code = request.nextUrl.searchParams.get(\"code\");\n const state = request.nextUrl.searchParams.get(\"state\");\n const error = request.nextUrl.searchParams.get(\"error\");\n\n if (error) {\n logger.error(\"OAuth error in callback:\", error);\n const urlDetectionRequest = toUrlDetectionRequest(request);\n const appUrl = CivicAuth.getAppUrl(urlDetectionRequest);\n return NextResponse.redirect(\n CivicAuth.toAbsoluteUrl(\n urlDetectionRequest,\n \"/?error=oauth_error\",\n appUrl,\n ),\n );\n }\n\n if (!code || !state) throw new AuthError(\"Bad parameters\", 400);\n\n try {\n const { civicAuth, appUrl, urlDetectionRequest } = createCivicAuth(\n request,\n resolvedConfigs,\n );\n\n // Convert NextRequest to the format expected by handleCallback\n const handleCallbackRequest = {\n headers: Object.fromEntries(request.headers.entries()),\n url: request.url.toString(),\n };\n\n // Get loginSuccessUrl with proper baseUrl handling\n const loginSuccessUrl = CivicAuth.getLoginSuccessUrl(\n urlDetectionRequest,\n appUrl,\n );\n const frontendUrl =\n loginSuccessUrl || resolvedConfigs.loginSuccessUrl || \"/\";\n\n // Use CivicAuth's smart callback handler\n const result = await civicAuth.handleCallback(\n {\n code,\n state,\n req: handleCallbackRequest,\n },\n {\n // Pass the properly resolved frontendUrl\n frontendUrl: prependBasePath(frontendUrl, config.basePath || \"\"),\n },\n );\n if (result.redirectTo) {\n return redirectWithBasePath(\n config,\n CivicAuth.toAbsoluteUrl(urlDetectionRequest, result.redirectTo, appUrl),\n );\n }\n\n if (result.content) {\n // Handle both string content and object content\n if (typeof result.content === \"string\") {\n return new NextResponse(result.content, {\n status: 200,\n headers: {\n \"Content-Type\": \"text/html\",\n },\n });\n } else {\n // Object content (JSON response)\n return NextResponse.json(result.content);\n }\n }\n\n // Fallback redirect\n return NextResponse.redirect(\n CivicAuth.toAbsoluteUrl(urlDetectionRequest, \"/\", appUrl),\n );\n } catch (error) {\n logger.error(\"[CALLBACK_HANDLER] OAuth callback error:\", error);\n const urlDetectionRequest = toUrlDetectionRequest(request);\n const appUrl = CivicAuth.getAppUrl(urlDetectionRequest);\n return NextResponse.redirect(\n CivicAuth.toAbsoluteUrl(\n urlDetectionRequest,\n \"/?error=callback_failed\",\n appUrl,\n ),\n );\n }\n}\n\nconst revalidateUrlPath = async (url: string) => {\n try {\n const path = new URL(url).pathname;\n revalidatePath(path);\n } catch (error) {\n logger.warn(\"Failed to revalidate path after logout:\", error);\n }\n};\n\nexport async function handleLogout(\n request: NextRequest,\n config: AuthConfig,\n): Promise<NextResponse> {\n const resolvedConfigs = resolveAuthConfig(config);\n\n // Get framework-agnostic request for URL utilities\n const urlDetectionRequest = toUrlDetectionRequest(request);\n const appUrl = CivicAuth.getAppUrl(urlDetectionRequest);\n\n // Read the state from the query parameters\n const state = request.nextUrl.searchParams.get(\"state\");\n const clientLogoutRedirectUrl =\n request.nextUrl.searchParams.get(\"logoutRedirectUrl\");\n\n try {\n logger.info(\"[LOGOUT_HANDLER] Backend logout endpoint called\");\n\n // If client provided a logoutRedirectUrl, override the config\n let configToUse = resolvedConfigs;\n if (clientLogoutRedirectUrl) {\n configToUse = {\n ...resolvedConfigs,\n logoutCallbackUrl: clientLogoutRedirectUrl,\n };\n logger.info(\"[LOGOUT_HANDLER] Overriding logout callback URL\", {\n original: resolvedConfigs.logoutCallbackUrl,\n override: clientLogoutRedirectUrl,\n });\n }\n\n const { civicAuth } = createCivicAuth(request, configToUse);\n\n // Always redirect to OAuth logout (like main branch)\n // Don't validate session - even invalid local sessions should hit OAuth logout\n logger.info(\"[LOGOUT_HANDLER] Processing logout request\", {\n state: !!state,\n });\n\n // Always redirect to OAuth logout endpoint (like main branch)\n // Client-side iframe logic will handle completion and redirect appropriately\n const logoutUrl = await civicAuth.buildLogoutRedirectUrl({\n state: state || undefined,\n });\n\n try {\n await clearAuthCookies(resolvedConfigs);\n\n // Revalidate current path to update authentication state in server components\n await revalidateUrlPath(request.url);\n } catch (error) {\n logger.error(\"[LOGOUT_HANDLER] Error clearing tokens:\", error);\n }\n\n // Remove state parameter from logout URL to prevent it from appearing in frontend URL\n const cleanLogoutUrl = new URL(logoutUrl);\n cleanLogoutUrl.searchParams.delete(\"state\");\n\n logger.info(\"[LOGOUT_HANDLER] Redirecting to OAuth logout endpoint\", {\n logoutUrl: cleanLogoutUrl.toString(),\n });\n\n return NextResponse.redirect(cleanLogoutUrl.toString());\n } catch (error) {\n logger.error(\"[LOGOUT_HANDLER] Logout error:\", error);\n // If logout URL generation fails, clear tokens and redirect to home\n await clearAuthCookies(resolvedConfigs);\n\n const fallbackUrl =\n clientLogoutRedirectUrl || resolvedConfigs.logoutCallbackUrl;\n const finalFallbackUrl = CivicAuth.toAbsoluteUrl(\n urlDetectionRequest,\n fallbackUrl,\n appUrl,\n );\n\n return NextResponse.redirect(finalFallbackUrl);\n }\n}\n\nexport async function handleLogoutCallback(\n request: NextRequest,\n config: AuthConfig,\n): Promise<NextResponse> {\n const resolvedConfigs = resolveAuthConfig(config);\n\n try {\n logger.info(\n \"[LOGOUT_CALLBACK_HANDLER] Backend logout callback endpoint called\",\n );\n\n // Clear authentication cookies\n await clearAuthCookies(resolvedConfigs);\n\n // Get framework-agnostic request and create CivicAuth instance\n const urlDetectionRequest = toUrlDetectionRequest(request);\n const { civicAuth } = createCivicAuth(request, resolvedConfigs);\n\n // Get the state parameter for iframe detection\n const state = request.nextUrl.searchParams.get(\"state\");\n\n // If this is an iframe request, return HTML with logout success signal\n if (state && displayModeFromState(state, \"iframe\") === \"iframe\") {\n // For iframe mode, include the post-logout redirect URL in the HTML\n const postLogoutRedirectUrl =\n civicAuth.getPostLogoutRedirectUrl(urlDetectionRequest);\n const response = new NextResponse(\n `<html lang=\"en\"><span style=\"display:none\">${LOGOUT_SUCCESS_TEXT}<a href=\"${postLogoutRedirectUrl}\" rel=\"civic-auth-post-logout-redirect-url\"></a></span></html>`,\n );\n response.headers.set(\"Content-Type\", \"text/html; charset=utf-8\");\n logger.info(\n \"[LOGOUT_CALLBACK_HANDLER] Returning iframe logout success HTML\",\n { postLogoutRedirectUrl },\n );\n return response;\n }\n\n // For non-iframe requests, redirect to the logout callback URL or post-logout URL\n const redirectUrl = civicAuth.getPostLogoutRedirectUrl(urlDetectionRequest);\n logger.info(\n \"[LOGOUT_CALLBACK_HANDLER] Redirecting to logout callback URL\",\n {\n logoutCallbackUrl: resolvedConfigs.logoutCallbackUrl,\n redirectUrl,\n },\n );\n\n // Revalidate the redirect path to update authentication state in server components\n await revalidateUrlPath(redirectUrl);\n return redirectWithBasePath(config, redirectUrl);\n } catch (error) {\n logger.error(\"[LOGOUT_CALLBACK_HANDLER] Logout callback error:\", error);\n const urlDetectionRequest = toUrlDetectionRequest(request);\n const appUrl = CivicAuth.getAppUrl(urlDetectionRequest);\n return redirectWithBasePath(\n config,\n CivicAuth.toAbsoluteUrl(\n urlDetectionRequest,\n resolvedConfigs.logoutCallbackUrl,\n appUrl,\n ),\n );\n }\n}\n\n/**\n * Creates an authentication handler for Next.js API routes\n *\n * Usage:\n * ```ts\n * // app/api/auth/[...civicauth]/route.ts\n * import { handler } from '@civic/auth/nextjs'\n * export const GET = handler({\n * // optional config overrides\n * })\n * export const POST = handler({\n * // optional config overrides\n * })\n * ```\n */\nexport const handler =\n (authConfig = {}) =>\n async (request: NextRequest): Promise<NextResponse> => {\n const config = resolveAuthConfig(authConfig);\n logger.debug(\"routeHandler: Auth route handler called\", config);\n try {\n const pathname = request.nextUrl.pathname;\n const pathSegments = pathname.split(\"/\");\n const lastSegment = pathSegments[pathSegments.length - 1];\n\n switch (lastSegment) {\n case \"challenge\":\n case \"login\":\n return await handleLogin(request, config);\n case \"callback\":\n return await handleCallback(request, config);\n case \"refresh\":\n return await handleRefresh(request, config);\n case \"logout\":\n return await handleLogout(request, config);\n case \"logoutcallback\":\n return await handleLogoutCallback(request, config);\n case \"user\":\n return await handleUser(request, config);\n default:\n throw new AuthError(`Invalid auth route: ${pathname}`, 404);\n }\n } catch (error) {\n logger.error(\"Auth handler error:\", error);\n\n const status = error instanceof AuthError ? error.status : 500;\n const message =\n error instanceof Error ? error.message : \"Authentication failed\";\n\n const response = NextResponse.json({ error: message }, { status });\n\n await clearAuthCookies(config);\n return response;\n }\n };\n\n/**\n * User endpoint - returns current user data as JSON\n * Uses CivicAuth.isLoggedIn() and getUser()\n */\nasync function handleUser(\n request: NextRequest,\n config: AuthConfig,\n): Promise<NextResponse> {\n const resolvedConfigs = resolveAuthConfig(config);\n logger.debug(\n \"routeHandler: [USER_HANDLER] User endpoint called\",\n resolvedConfigs,\n );\n try {\n const { civicAuth } = createCivicAuth(request, resolvedConfigs);\n\n const isLoggedIn = await civicAuth.isLoggedIn();\n\n if (!isLoggedIn) {\n const statusCode = request.nextUrl.searchParams.get(\n \"optimisticRehydration\",\n )\n ? 202\n : 401;\n return NextResponse.json(\n { error: \"Not authenticated\" },\n { status: statusCode },\n );\n }\n\n const user = await civicAuth.getUser();\n\n return NextResponse.json({ user });\n } catch (error) {\n logger.error(\"[USER_HANDLER] User endpoint error:\", error);\n return NextResponse.json(\n { error: \"Internal server error\" },\n { status: 500 },\n );\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"routeHandler.js","sourceRoot":"","sources":["../../src/nextjs/routeHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import { CivicAuth, type UrlDetectionRequest } from \"@civic/auth/server\";\nimport { LOGOUT_SUCCESS_TEXT } from \"@/constants.js\";\nimport { loggers } from \"@/lib/logger.js\";\nimport { displayModeFromState } from \"@/lib/oauth.js\";\nimport type { AuthConfig } from \"@/nextjs/config.js\";\nimport { resolveAuthConfig } from \"@/nextjs/config.js\";\nimport { clearAuthCookies, NextjsCookieStorage } from \"@/nextjs/cookies.js\";\nimport { CodeVerifier, UserStorage } from \"@/shared/lib/types.js\";\nimport { revalidatePath } from \"next/cache.js\";\nimport type { NextRequest } from \"next/server.js\";\nimport { NextResponse } from \"next/server.js\";\nimport { prependBasePath, redirectWithBasePath } from \"./utils.js\";\n\nconst logger = loggers.nextjs.handlers.auth;\n\nclass AuthError extends Error {\n constructor(\n message: string,\n public readonly status: number = 401,\n ) {\n super(message);\n this.name = \"AuthError\";\n }\n}\n\n/**\n * Helper to convert NextRequest to UrlDetectionRequest for framework-agnostic URL handling\n */\nconst toUrlDetectionRequest = (request: NextRequest): UrlDetectionRequest => ({\n url: request.url,\n headers: Object.fromEntries(request.headers.entries()),\n searchParams: {\n get: (name: string) => request.nextUrl.searchParams.get(name),\n },\n cookies: {\n get: (name: string) => request.cookies.get(name),\n },\n});\n\n/**\n * Helper to create CivicAuth instance for a request\n * Now handles appUrl detection for proxy environments\n */\nconst createCivicAuth = (request: NextRequest, config: AuthConfig) => {\n const resolvedConfig = resolveAuthConfig(config);\n const cookieStorage = new NextjsCookieStorage({\n ...resolvedConfig.cookies?.tokens,\n [UserStorage.USER]: resolvedConfig.cookies?.user,\n });\n\n // Convert to framework-agnostic request format\n const urlDetectionRequest = toUrlDetectionRequest(request);\n\n // Get appUrl from client (for proxy environments)\n const clientAppUrl = CivicAuth.getAppUrl(urlDetectionRequest);\n\n // Use baseUrl from config, then client appUrl, then request origin\n // This matches the main branch priority: config > client > request\n const appUrl =\n resolvedConfig.baseUrl ||\n clientAppUrl ||\n new URL(urlDetectionRequest.url).origin;\n\n // Build absolute URLs using detected appUrl or request origin\n const absoluteCallbackUrl = resolvedConfig.callbackUrl.startsWith(\"http\")\n ? resolvedConfig.callbackUrl\n : CivicAuth.toAbsoluteUrl(\n urlDetectionRequest,\n resolvedConfig.callbackUrl,\n appUrl,\n );\n const absoluteLogoutCallbackUrl = resolvedConfig.logoutCallbackUrl.startsWith(\n \"http\",\n )\n ? resolvedConfig.logoutCallbackUrl\n : CivicAuth.toAbsoluteUrl(\n urlDetectionRequest,\n resolvedConfig.logoutCallbackUrl,\n appUrl,\n );\n\n const civicAuth = new CivicAuth(cookieStorage, {\n disableRefresh: resolvedConfig.disableRefresh,\n clientId: resolvedConfig.clientId,\n redirectUrl: absoluteCallbackUrl,\n oauthServer: resolvedConfig.oauthServer,\n postLogoutRedirectUrl: absoluteLogoutCallbackUrl,\n loginSuccessUrl: request.url,\n });\n\n return {\n civicAuth,\n cookieStorage,\n appUrl, // Return appUrl for use in other functions\n urlDetectionRequest, // Return for use in handlers\n };\n};\n\n/**\n * Login handler - backend OAuth login initiation endpoint\n * Uses CivicAuth.buildLoginUrl()\n */\nasync function handleLogin(\n request: NextRequest,\n config: AuthConfig,\n): Promise<NextResponse> {\n const resolvedConfigs = resolveAuthConfig(config);\n\n try {\n const frontendState = request.nextUrl.searchParams.get(\"state\");\n\n // Store appUrl in cookie if provided as query parameter\n const appUrlFromQuery = request.nextUrl.searchParams.get(\"appUrl\");\n if (appUrlFromQuery) {\n const cookieStorage = new NextjsCookieStorage(\n resolvedConfigs.cookies?.tokens ?? {},\n );\n await cookieStorage.set(CodeVerifier.APP_URL, appUrlFromQuery);\n }\n\n const { civicAuth } = createCivicAuth(request, resolvedConfigs);\n\n const url = await civicAuth.buildLoginUrl({\n state: frontendState || undefined,\n });\n\n logger.info(\"[LOGIN_HANDLER] Redirecting to OAuth login URL\", {\n loginUrl: url.toString(),\n });\n\n return NextResponse.redirect(url.toString());\n } catch (error) {\n logger.error(\"[LOGIN_HANDLER] Backend login error:\", error);\n const urlDetectionRequest = toUrlDetectionRequest(request);\n const appUrl = CivicAuth.getAppUrl(urlDetectionRequest);\n return NextResponse.redirect(\n CivicAuth.toAbsoluteUrl(\n urlDetectionRequest,\n \"/?error=login_failed\",\n appUrl,\n ),\n );\n }\n}\n\nasync function handleRefresh(\n request: NextRequest,\n config: AuthConfig,\n): Promise<NextResponse> {\n const resolvedConfigs = resolveAuthConfig(config);\n\n try {\n const { civicAuth } = createCivicAuth(request, resolvedConfigs);\n\n await civicAuth.refreshTokens();\n\n logger.info(\"[REFRESH_HANDLER] Tokens refreshed successfully\");\n\n return NextResponse.json({\n status: \"success\",\n message: \"Tokens refreshed\",\n });\n } catch (error) {\n logger.error(\"[REFRESH_HANDLER] Token refresh error:\", error);\n return NextResponse.json(\n { error: \"Token refresh failed\" },\n { status: 500 },\n );\n }\n}\n\nasync function handleCallback(\n request: NextRequest,\n config: AuthConfig,\n): Promise<NextResponse> {\n const resolvedConfigs = resolveAuthConfig(config);\n const code = request.nextUrl.searchParams.get(\"code\");\n const state = request.nextUrl.searchParams.get(\"state\");\n const error = request.nextUrl.searchParams.get(\"error\");\n\n if (error) {\n logger.error(\"OAuth error in callback:\", error);\n const urlDetectionRequest = toUrlDetectionRequest(request);\n const appUrl = CivicAuth.getAppUrl(urlDetectionRequest);\n return NextResponse.redirect(\n CivicAuth.toAbsoluteUrl(\n urlDetectionRequest,\n \"/?error=oauth_error\",\n appUrl,\n ),\n );\n }\n\n if (!code || !state) throw new AuthError(\"Bad parameters\", 400);\n\n try {\n const { civicAuth, appUrl, urlDetectionRequest } = createCivicAuth(\n request,\n resolvedConfigs,\n );\n\n // Convert NextRequest to the format expected by handleCallback\n const handleCallbackRequest = {\n headers: Object.fromEntries(request.headers.entries()),\n url: request.url.toString(),\n };\n\n // Get loginSuccessUrl with proper baseUrl handling\n const loginSuccessUrl = CivicAuth.getLoginSuccessUrl(\n urlDetectionRequest,\n appUrl,\n );\n const frontendUrl =\n loginSuccessUrl || resolvedConfigs.loginSuccessUrl || \"/\";\n\n // Use CivicAuth's smart callback handler\n const result = await civicAuth.handleCallback(\n {\n code,\n state,\n req: handleCallbackRequest,\n },\n {\n // Pass the properly resolved frontendUrl\n frontendUrl: prependBasePath(frontendUrl, config.basePath || \"\"),\n },\n );\n if (result.redirectTo) {\n return redirectWithBasePath(\n config,\n CivicAuth.toAbsoluteUrl(urlDetectionRequest, result.redirectTo, appUrl),\n );\n }\n\n if (result.content) {\n // Handle both string content and object content\n if (typeof result.content === \"string\") {\n return new NextResponse(result.content, {\n status: 200,\n headers: {\n \"Content-Type\": \"text/html\",\n },\n });\n } else {\n // Object content (JSON response)\n return NextResponse.json(result.content);\n }\n }\n\n // Fallback redirect\n return NextResponse.redirect(\n CivicAuth.toAbsoluteUrl(urlDetectionRequest, \"/\", appUrl),\n );\n } catch (error) {\n logger.error(\"[CALLBACK_HANDLER] OAuth callback error:\", error);\n const urlDetectionRequest = toUrlDetectionRequest(request);\n const appUrl = CivicAuth.getAppUrl(urlDetectionRequest);\n return NextResponse.redirect(\n CivicAuth.toAbsoluteUrl(\n urlDetectionRequest,\n \"/?error=callback_failed\",\n appUrl,\n ),\n );\n }\n}\n\nconst revalidateUrlPath = async (url: string) => {\n try {\n const path = new URL(url).pathname;\n revalidatePath(path);\n } catch (error) {\n logger.warn(\"Failed to revalidate path after logout:\", error);\n }\n};\n\nexport async function handleLogout(\n request: NextRequest,\n config: AuthConfig,\n): Promise<NextResponse> {\n const resolvedConfigs = resolveAuthConfig(config);\n\n // Get framework-agnostic request for URL utilities\n const urlDetectionRequest = toUrlDetectionRequest(request);\n const appUrl = CivicAuth.getAppUrl(urlDetectionRequest);\n\n // Read the state from the query parameters\n const state = request.nextUrl.searchParams.get(\"state\");\n const clientLogoutRedirectUrl =\n request.nextUrl.searchParams.get(\"logoutRedirectUrl\");\n\n try {\n logger.info(\"[LOGOUT_HANDLER] Backend logout endpoint called\");\n\n // If client provided a logoutRedirectUrl, override the config\n let configToUse = resolvedConfigs;\n if (clientLogoutRedirectUrl) {\n configToUse = {\n ...resolvedConfigs,\n logoutCallbackUrl: clientLogoutRedirectUrl,\n };\n logger.info(\"[LOGOUT_HANDLER] Overriding logout callback URL\", {\n original: resolvedConfigs.logoutCallbackUrl,\n override: clientLogoutRedirectUrl,\n });\n }\n\n const { civicAuth } = createCivicAuth(request, configToUse);\n\n // Always redirect to OAuth logout (like main branch)\n // Don't validate session - even invalid local sessions should hit OAuth logout\n logger.info(\"[LOGOUT_HANDLER] Processing logout request\", {\n state: !!state,\n });\n\n // Always redirect to OAuth logout endpoint (like main branch)\n // Client-side iframe logic will handle completion and redirect appropriately\n const logoutUrl = await civicAuth.buildLogoutRedirectUrl({\n state: state || undefined,\n });\n\n try {\n await clearAuthCookies(resolvedConfigs);\n\n // Revalidate current path to update authentication state in server components\n await revalidateUrlPath(request.url);\n } catch (error) {\n logger.error(\"[LOGOUT_HANDLER] Error clearing tokens:\", error);\n }\n\n // Remove state parameter from logout URL to prevent it from appearing in frontend URL\n const cleanLogoutUrl = new URL(logoutUrl);\n cleanLogoutUrl.searchParams.delete(\"state\");\n\n logger.info(\"[LOGOUT_HANDLER] Redirecting to OAuth logout endpoint\", {\n logoutUrl: cleanLogoutUrl.toString(),\n });\n\n return NextResponse.redirect(cleanLogoutUrl.toString());\n } catch (error) {\n logger.error(\"[LOGOUT_HANDLER] Logout error:\", error);\n // If logout URL generation fails, clear tokens and redirect to home\n await clearAuthCookies(resolvedConfigs);\n\n const fallbackUrl =\n clientLogoutRedirectUrl || resolvedConfigs.logoutCallbackUrl;\n const finalFallbackUrl = CivicAuth.toAbsoluteUrl(\n urlDetectionRequest,\n fallbackUrl,\n appUrl,\n );\n\n return NextResponse.redirect(finalFallbackUrl);\n }\n}\n\nexport async function handleLogoutCallback(\n request: NextRequest,\n config: AuthConfig,\n): Promise<NextResponse> {\n const resolvedConfigs = resolveAuthConfig(config);\n\n try {\n logger.info(\n \"[LOGOUT_CALLBACK_HANDLER] Backend logout callback endpoint called\",\n );\n\n // Clear authentication cookies\n await clearAuthCookies(resolvedConfigs);\n\n // Get framework-agnostic request and create CivicAuth instance\n const urlDetectionRequest = toUrlDetectionRequest(request);\n const { civicAuth } = createCivicAuth(request, resolvedConfigs);\n\n // Get the state parameter for iframe detection\n const state = request.nextUrl.searchParams.get(\"state\");\n\n // If this is an iframe request, return HTML with logout success signal\n if (state && displayModeFromState(state, \"iframe\") === \"iframe\") {\n // For iframe mode, include the post-logout redirect URL in the HTML\n const postLogoutRedirectUrl =\n civicAuth.getPostLogoutRedirectUrl(urlDetectionRequest);\n const response = new NextResponse(\n `<html lang=\"en\"><span style=\"display:none\">${LOGOUT_SUCCESS_TEXT}<a href=\"${postLogoutRedirectUrl}\" rel=\"civic-auth-post-logout-redirect-url\"></a></span></html>`,\n );\n response.headers.set(\"Content-Type\", \"text/html; charset=utf-8\");\n logger.info(\n \"[LOGOUT_CALLBACK_HANDLER] Returning iframe logout success HTML\",\n { postLogoutRedirectUrl },\n );\n return response;\n }\n\n // For non-iframe requests, redirect to the logout callback URL or post-logout URL\n const redirectUrl = civicAuth.getPostLogoutRedirectUrl(urlDetectionRequest);\n logger.info(\n \"[LOGOUT_CALLBACK_HANDLER] Redirecting to logout callback URL\",\n {\n logoutCallbackUrl: resolvedConfigs.logoutCallbackUrl,\n redirectUrl,\n },\n );\n\n // Revalidate the redirect path to update authentication state in server components\n await revalidateUrlPath(redirectUrl);\n return redirectWithBasePath(config, redirectUrl);\n } catch (error) {\n logger.error(\"[LOGOUT_CALLBACK_HANDLER] Logout callback error:\", error);\n const urlDetectionRequest = toUrlDetectionRequest(request);\n const appUrl = CivicAuth.getAppUrl(urlDetectionRequest);\n return redirectWithBasePath(\n config,\n CivicAuth.toAbsoluteUrl(\n urlDetectionRequest,\n resolvedConfigs.logoutCallbackUrl,\n appUrl,\n ),\n );\n }\n}\n\n/**\n * Creates an authentication handler for Next.js API routes\n *\n * Usage:\n * ```ts\n * // app/api/auth/[...civicauth]/route.ts\n * import { handler } from '@civic/auth/nextjs'\n * export const GET = handler({\n * // optional config overrides\n * })\n * export const POST = handler({\n * // optional config overrides\n * })\n * ```\n */\nexport const handler =\n (authConfig = {}) =>\n async (request: NextRequest): Promise<NextResponse> => {\n const config = resolveAuthConfig(authConfig);\n logger.debug(\"routeHandler: Auth route handler called\", config);\n try {\n const pathname = request.nextUrl.pathname;\n const pathSegments = pathname.split(\"/\");\n const lastSegment = pathSegments[pathSegments.length - 1];\n\n switch (lastSegment) {\n case \"challenge\":\n case \"login\":\n return await handleLogin(request, config);\n case \"callback\":\n return await handleCallback(request, config);\n case \"refresh\":\n return await handleRefresh(request, config);\n case \"logout\":\n return await handleLogout(request, config);\n case \"logoutcallback\":\n return await handleLogoutCallback(request, config);\n case \"user\":\n return await handleUser(request, config);\n default:\n throw new AuthError(`Invalid auth route: ${pathname}`, 404);\n }\n } catch (error) {\n logger.error(\"Auth handler error:\", error);\n\n const status = error instanceof AuthError ? error.status : 500;\n const message =\n error instanceof Error ? error.message : \"Authentication failed\";\n\n const response = NextResponse.json({ error: message }, { status });\n\n await clearAuthCookies(config);\n return response;\n }\n };\n\n/**\n * User endpoint - returns current user data as JSON\n * Uses CivicAuth.isLoggedIn() and getUser()\n */\nasync function handleUser(\n request: NextRequest,\n config: AuthConfig,\n): Promise<NextResponse> {\n const resolvedConfigs = resolveAuthConfig(config);\n logger.debug(\n \"routeHandler: [USER_HANDLER] User endpoint called\",\n resolvedConfigs,\n );\n try {\n const { civicAuth } = createCivicAuth(request, resolvedConfigs);\n\n const isLoggedIn = await civicAuth.isLoggedIn();\n\n if (!isLoggedIn) {\n const statusCode = request.nextUrl.searchParams.get(\n \"optimisticRehydration\",\n )\n ? 202\n : 401;\n return NextResponse.json(\n { error: \"Not authenticated\" },\n { status: statusCode },\n );\n }\n\n const user = await civicAuth.getUser();\n\n return NextResponse.json({ user });\n } catch (error) {\n logger.error(\"[USER_HANDLER] User endpoint error:\", error);\n return NextResponse.json(\n { error: \"Internal server error\" },\n { status: 500 },\n );\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServerAuthenticationResolver.d.ts","sourceRoot":"","sources":["../../src/server/ServerAuthenticationResolver.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,WAAW,EACX,SAAS,EACT,qBAAqB,EACrB,WAAW,EACZ,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"ServerAuthenticationResolver.d.ts","sourceRoot":"","sources":["../../src/server/ServerAuthenticationResolver.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,WAAW,EACX,SAAS,EACT,qBAAqB,EACrB,WAAW,EACZ,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAQrD,OAAO,KAAK,EAAE,sBAAsB,EAAgB,MAAM,qBAAqB,CAAC;AAMhF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAK7D,qBAAa,4BAA6B,YAAW,sBAAsB;IAMvE,QAAQ,CAAC,UAAU,EAAE,UAAU;IAC/B,QAAQ,CAAC,OAAO,EAAE,WAAW;IAC7B,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC;IAPjD,OAAO,CAAC,YAAY,CAAsB;IAC1C,OAAO,CAAC,YAAY,CAA2B;IAC/C,OAAO,CAAC,SAAS,CAAwB;IAEzC,OAAO;IAeP;;;;OAIG;IACG,gBAAgB,CACpB,WAAW,EAAE,WAAW,GAAG,IAAI,GAC9B,OAAO,CAAC,WAAW,CAAC;IAqDvB;;;OAGG;IACG,uBAAuB,CAC3B,kBAAkB,UAAO,GACxB,OAAO,CAAC,WAAW,CAAC;IA+DvB,IAAI,WAAW,IAAI,MAAM,CAExB;IAEK,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAuBrB,aAAa,CACjB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,qBAAqB,CAAC;IA4C3B,cAAc,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAc7C,qBAAqB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;WAOxC,KAAK,CAChB,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,aAAa,EACtB,iBAAiB,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,GACrC,OAAO,CAAC,sBAAsB,CAAC;CAUnC"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { GenericPublicClientPKCEProducer } from "../services/PKCE.js";
|
|
2
2
|
import { OAuth2Client } from "oslo/oauth2";
|
|
3
|
-
import {
|
|
3
|
+
import { exchangeTokens, getEndpointsWithOverrides, retrieveTokens, storeServerTokens, validateOauth2Tokens, } from "../shared/lib/util.js";
|
|
4
4
|
import { DEFAULT_AUTH_SERVER } from "../constants.js";
|
|
5
5
|
import { CodeVerifier } from "../shared/lib/types.js";
|
|
6
6
|
import { loggers } from "../lib/logger.js";
|
|
7
7
|
import { getUser, getUserFromTokens } from "../shared/lib/session.js";
|
|
8
8
|
import { GenericUserSession } from "../shared/lib/UserSession.js";
|
|
9
|
+
import { AuthenticationRefresherImpl } from "../shared/lib/AuthenticationRefresherImpl.js";
|
|
9
10
|
const logger = loggers.services.validation;
|
|
10
11
|
export class ServerAuthenticationResolver {
|
|
11
12
|
authConfig;
|
|
@@ -35,60 +36,43 @@ export class ServerAuthenticationResolver {
|
|
|
35
36
|
logger.debug("tryRefreshTokens", { sessionData });
|
|
36
37
|
// If there's a refresh token, attempt to refresh tokens
|
|
37
38
|
if (sessionData?.refreshToken) {
|
|
39
|
+
const authRefresher = await AuthenticationRefresherImpl.build({
|
|
40
|
+
...this.authConfig,
|
|
41
|
+
oauthServer: this.authConfig.oauthServer ?? DEFAULT_AUTH_SERVER,
|
|
42
|
+
}, this.storage, async (error) => {
|
|
43
|
+
logger.error("ServerAuthenticationResolver: Error refreshing tokens", { error });
|
|
44
|
+
return Promise.reject(error);
|
|
45
|
+
}, this.endpointOverrides);
|
|
46
|
+
const tokenResponseBody = await authRefresher.refreshAccessToken();
|
|
47
|
+
if (!tokenResponseBody) {
|
|
48
|
+
throw new Error("No tokens returned from refresh");
|
|
49
|
+
}
|
|
50
|
+
// Store user data if a user can be derived from the tokens
|
|
38
51
|
try {
|
|
39
|
-
|
|
40
|
-
if (
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
// Use the oauth2client to refresh the access token
|
|
47
|
-
const refreshOptions = {};
|
|
48
|
-
if (this.authConfig.clientSecret) {
|
|
49
|
-
refreshOptions.credentials = this.authConfig.clientSecret;
|
|
50
|
-
refreshOptions.authenticateWith = "request_body";
|
|
51
|
-
}
|
|
52
|
-
const tokenResponseBody = (await this.oauth2client.refreshAccessToken(sessionData.refreshToken, refreshOptions));
|
|
53
|
-
if (!tokenResponseBody) {
|
|
54
|
-
throw new Error("Failed to get token response from refresh");
|
|
55
|
-
}
|
|
56
|
-
// Validate the refreshed tokens
|
|
57
|
-
await validateOauth2Tokens(tokenResponseBody, this.endpoints.jwks, this.oauth2client, this.oauthServer);
|
|
58
|
-
await storeServerTokens(this.storage, tokenResponseBody);
|
|
59
|
-
// Store user data if a user can be derived from the tokens
|
|
60
|
-
try {
|
|
61
|
-
const user = await getUserFromTokens(tokenResponseBody);
|
|
62
|
-
if (user) {
|
|
63
|
-
const userSession = new GenericUserSession(this.storage);
|
|
64
|
-
await userSession.set(user);
|
|
65
|
-
logger.debug("User cookie stored successfully", {
|
|
66
|
-
hasUser: !!user,
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
else {
|
|
70
|
-
logger.warn("No user found after token exchange");
|
|
71
|
-
}
|
|
52
|
+
const user = await getUserFromTokens(tokenResponseBody);
|
|
53
|
+
if (user) {
|
|
54
|
+
const userSession = new GenericUserSession(this.storage);
|
|
55
|
+
await userSession.set(user);
|
|
56
|
+
logger.debug("User cookie stored successfully", {
|
|
57
|
+
hasUser: !!user,
|
|
58
|
+
});
|
|
72
59
|
}
|
|
73
|
-
|
|
74
|
-
logger.
|
|
60
|
+
else {
|
|
61
|
+
logger.warn("No user found after token exchange");
|
|
75
62
|
}
|
|
76
|
-
// Construct a refreshed session with the new tokens
|
|
77
|
-
return {
|
|
78
|
-
authenticated: true,
|
|
79
|
-
idToken: tokenResponseBody.id_token,
|
|
80
|
-
accessToken: tokenResponseBody.access_token,
|
|
81
|
-
refreshToken: tokenResponseBody.refresh_token,
|
|
82
|
-
oidcSessionExpiresAt: tokenResponseBody.oidc_session_expires_at,
|
|
83
|
-
wasRehydrated: true,
|
|
84
|
-
};
|
|
85
63
|
}
|
|
86
64
|
catch (error) {
|
|
87
|
-
logger.
|
|
88
|
-
await clearTokens(this.storage);
|
|
89
|
-
await clearUser(this.storage);
|
|
90
|
-
return { ...sessionData, authenticated: false };
|
|
65
|
+
logger.error("Failed to store user cookie:", error);
|
|
91
66
|
}
|
|
67
|
+
// Construct a refreshed session with the new tokens
|
|
68
|
+
return {
|
|
69
|
+
authenticated: true,
|
|
70
|
+
idToken: tokenResponseBody.id_token,
|
|
71
|
+
accessToken: tokenResponseBody.access_token,
|
|
72
|
+
refreshToken: tokenResponseBody.refresh_token,
|
|
73
|
+
oidcSessionExpiresAt: tokenResponseBody.oidc_session_expires_at,
|
|
74
|
+
wasRehydrated: true,
|
|
75
|
+
};
|
|
92
76
|
}
|
|
93
77
|
// No refresh token available
|
|
94
78
|
return { ...sessionData, authenticated: false };
|
|
@@ -135,9 +119,17 @@ export class ServerAuthenticationResolver {
|
|
|
135
119
|
logger.warn("Error validating tokens", { error });
|
|
136
120
|
if (attemptRehydration && !this.authConfig.disableRefresh) {
|
|
137
121
|
// If token validation fails, try to refresh tokens
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
122
|
+
try {
|
|
123
|
+
const refreshedSessionData = await this.tryRefreshTokens(sessionData);
|
|
124
|
+
if (refreshedSessionData.authenticated) {
|
|
125
|
+
return refreshedSessionData;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
logger.error("Error refreshing tokens after validation failure", {
|
|
130
|
+
error,
|
|
131
|
+
});
|
|
132
|
+
return { ...sessionData, authenticated: false };
|
|
141
133
|
}
|
|
142
134
|
}
|
|
143
135
|
return { ...sessionData, authenticated: false };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServerAuthenticationResolver.js","sourceRoot":"","sources":["../../src/server/ServerAuthenticationResolver.ts"],"names":[],"mappings":"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","sourcesContent":["import { GenericPublicClientPKCEProducer } from \"@/services/PKCE.js\";\nimport { OAuth2Client } from \"oslo/oauth2\";\nimport type {\n AuthStorage,\n Endpoints,\n OIDCTokenResponseBody,\n SessionData,\n} from \"@/types.js\";\nimport type { AuthConfig } from \"@/server/config.js\";\nimport {\n clearTokens,\n clearUser,\n exchangeTokens,\n getEndpointsWithOverrides,\n retrieveTokens,\n storeServerTokens,\n validateOauth2Tokens,\n} from \"@/shared/lib/util.js\";\nimport type { AuthenticationResolver, PKCEProducer } from \"@/services/types.ts\";\nimport { DEFAULT_AUTH_SERVER } from \"@/constants.js\";\nimport { CodeVerifier } from \"@/shared/lib/types.js\";\nimport { loggers } from \"@/lib/logger.js\";\nimport { getUser, getUserFromTokens } from \"@/shared/lib/session.js\";\nimport { GenericUserSession } from \"@/shared/lib/UserSession.js\";\nimport type { CookieStorage } from \"@/shared/lib/storage.js\";\n\nconst logger = loggers.services.validation;\n\nexport class ServerAuthenticationResolver implements AuthenticationResolver {\n private pkceProducer: PKCEProducer | null;\n private oauth2client: OAuth2Client | undefined;\n private endpoints: Endpoints | undefined;\n\n private constructor(\n readonly authConfig: AuthConfig,\n readonly storage: AuthStorage,\n readonly endpointOverrides?: Partial<Endpoints>,\n ) {\n // Determine if PKCE should be used based on config\n // Default to true\n const usePkce = authConfig.pkce !== false;\n\n // Only create PKCE producer if we're using PKCE\n this.pkceProducer = usePkce\n ? new GenericPublicClientPKCEProducer(storage)\n : null;\n }\n\n /**\n * Attempts to refresh tokens if a refresh token is available\n * @param sessionData Current session data\n * @returns Updated session data\n */\n async tryRefreshTokens(\n sessionData: SessionData | null,\n ): Promise<SessionData> {\n logger.debug(\"tryRefreshTokens\", { sessionData });\n // If there's a refresh token, attempt to refresh tokens\n if (sessionData?.refreshToken) {\n try {\n // Only attempt refresh if we have necessary components\n if (!this.oauth2client || !this.endpoints?.jwks) {\n await this.init();\n }\n\n if (!this.oauth2client || !this.endpoints?.jwks) {\n throw new Error(\n \"Failed to initialize OAuth client for token refresh\",\n );\n }\n\n // Use the oauth2client to refresh the access token\n const refreshOptions: Record<string, string> = {};\n if (this.authConfig.clientSecret) {\n refreshOptions.credentials = this.authConfig.clientSecret;\n refreshOptions.authenticateWith = \"request_body\";\n }\n\n const tokenResponseBody = (await this.oauth2client.refreshAccessToken(\n sessionData.refreshToken,\n refreshOptions,\n )) as OIDCTokenResponseBody;\n\n if (!tokenResponseBody) {\n throw new Error(\"Failed to get token response from refresh\");\n }\n\n // Validate the refreshed tokens\n await validateOauth2Tokens(\n tokenResponseBody,\n this.endpoints.jwks,\n this.oauth2client,\n this.oauthServer,\n );\n\n await storeServerTokens(this.storage, tokenResponseBody);\n\n // Store user data if a user can be derived from the tokens\n try {\n const user = await getUserFromTokens(tokenResponseBody);\n if (user) {\n const userSession = new GenericUserSession(this.storage);\n await userSession.set(user);\n logger.debug(\"User cookie stored successfully\", {\n hasUser: !!user,\n });\n } else {\n logger.warn(\"No user found after token exchange\");\n }\n } catch (error) {\n logger.error(\"Failed to store user cookie:\", error);\n }\n // Construct a refreshed session with the new tokens\n return {\n authenticated: true,\n idToken: tokenResponseBody.id_token,\n accessToken: tokenResponseBody.access_token,\n refreshToken: tokenResponseBody.refresh_token,\n oidcSessionExpiresAt: tokenResponseBody.oidc_session_expires_at,\n wasRehydrated: true,\n };\n } catch (error) {\n logger.warn(\"Failed to refresh tokens\", error);\n await clearTokens(this.storage);\n await clearUser(this.storage);\n return { ...sessionData, authenticated: false };\n }\n }\n\n // No refresh token available\n return { ...sessionData, authenticated: false };\n }\n\n /**\n * returns The session data if the session is valid, otherwise an unauthenticated session\n * @returns {Promise<SessionData>}\n */\n async validateExistingSession(\n attemptRehydration = true,\n ): Promise<SessionData> {\n // TODO: investigate a more peformant way to validate a server session\n // other than using JWKS and JWT verification which is what validateOauth2Tokens uses\n const sessionData = await this.getSessionData();\n\n logger.debug(\"validateExistingSession\", {\n disableRefresh: this.authConfig.disableRefresh,\n });\n // If we don't have an ID token, try to refresh if we have a refresh token\n // Access token is no longer required for authentication\n if (!sessionData?.idToken) {\n if (attemptRehydration && !this.authConfig.disableRefresh) {\n const refreshedSessionData = await this.tryRefreshTokens(sessionData);\n if (refreshedSessionData.authenticated) {\n return refreshedSessionData;\n }\n }\n\n return { ...sessionData, authenticated: false };\n }\n\n // Initialize if needed\n if (!this.endpoints?.jwks || !this.oauth2client) await this.init();\n\n if (!this.endpoints?.jwks) {\n throw new Error(\"JWKS endpoint not found\");\n }\n\n try {\n // Validate existing tokens - access token validation happens only if it exists\n await validateOauth2Tokens(\n {\n access_token: sessionData.accessToken, // May be undefined\n id_token: sessionData.idToken, // Always required\n refresh_token: sessionData.refreshToken,\n oidc_session_expires_at: sessionData.oidcSessionExpiresAt,\n },\n this.endpoints.jwks,\n this.oauth2client!,\n this.oauthServer,\n );\n return sessionData;\n } catch (error) {\n logger.warn(\"Error validating tokens\", { error });\n if (attemptRehydration && !this.authConfig.disableRefresh) {\n // If token validation fails, try to refresh tokens\n const refreshedSessionData = await this.tryRefreshTokens(sessionData);\n if (refreshedSessionData.authenticated) {\n return refreshedSessionData;\n }\n }\n\n return { ...sessionData, authenticated: false };\n }\n }\n\n get oauthServer(): string {\n return this.authConfig.oauthServer || DEFAULT_AUTH_SERVER;\n }\n\n async init(): Promise<this> {\n // Ensure clientId is present for OAuth operations\n if (!this.authConfig.clientId) {\n throw new Error(\"clientId is required for OAuth server operations\");\n }\n\n // resolve oauth config\n this.endpoints = await getEndpointsWithOverrides(\n this.oauthServer,\n this.endpointOverrides,\n );\n this.oauth2client = new OAuth2Client(\n this.authConfig.clientId,\n this.endpoints.auth,\n this.endpoints.token,\n {\n redirectURI: this.authConfig.redirectUrl,\n },\n );\n\n return this;\n }\n\n async tokenExchange(\n code: string,\n state: string,\n ): Promise<OIDCTokenResponseBody> {\n if (!this.oauth2client) await this.init();\n\n // Check if we're using PKCE and validate code verifier if needed\n if (this.pkceProducer) {\n const codeVerifier = await this.pkceProducer.getCodeVerifier();\n if (!codeVerifier) throw new Error(\"Code verifier not found in storage\");\n }\n\n // exchange auth code for tokens\n const tokens = await exchangeTokens(\n code,\n state,\n this.pkceProducer,\n this.oauth2client!, // clean up types here to avoid the ! operator\n this.oauthServer,\n this.endpoints!, // clean up types here to avoid the ! operator\n this.authConfig.clientSecret,\n );\n\n await storeServerTokens(this.storage, tokens);\n\n // Store user data in cookie (like VanillaJS implementation does)\n try {\n const user = await getUser(this.storage);\n if (user) {\n const userSession = new GenericUserSession(this.storage);\n await userSession.set(user);\n logger.debug(\"User cookie stored successfully\", { hasUser: !!user });\n } else {\n logger.warn(\"No user found after token exchange\");\n }\n } catch (error) {\n logger.error(\"Failed to store user cookie:\", error);\n // Don't throw - tokens are already stored, this is just for client-side convenience\n }\n\n // the code verifier should be single-use, so we delete it if using PKCE\n if (this.pkceProducer) {\n await this.storage.delete(CodeVerifier.COOKIE_NAME);\n }\n return tokens;\n }\n\n async getSessionData(): Promise<SessionData | null> {\n const storageData = await retrieveTokens(this.storage);\n\n if (!storageData) return null;\n\n return {\n authenticated: !!storageData.id_token, // User is authenticated if they have an ID token\n idToken: storageData.id_token,\n accessToken: storageData.access_token, // Optional\n refreshToken: storageData.refresh_token,\n oidcSessionExpiresAt: storageData.oidc_session_expires_at,\n };\n }\n\n async getEndSessionEndpoint(): Promise<string | null> {\n if (!this.endpoints) {\n return null;\n }\n return this.endpoints.endsession;\n }\n\n static async build(\n authConfig: AuthConfig,\n storage: CookieStorage,\n endpointOverrides?: Partial<Endpoints>,\n ): Promise<AuthenticationResolver> {\n const resolver = new ServerAuthenticationResolver(\n authConfig,\n storage,\n endpointOverrides,\n );\n await resolver.init();\n\n return resolver;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ServerAuthenticationResolver.js","sourceRoot":"","sources":["../../src/server/ServerAuthenticationResolver.ts"],"names":[],"mappings":"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","sourcesContent":["import { GenericPublicClientPKCEProducer } from \"@/services/PKCE.js\";\nimport { OAuth2Client } from \"oslo/oauth2\";\nimport type {\n AuthStorage,\n Endpoints,\n OIDCTokenResponseBody,\n SessionData,\n} from \"@/types.js\";\nimport type { AuthConfig } from \"@/server/config.js\";\nimport {\n exchangeTokens,\n getEndpointsWithOverrides,\n retrieveTokens,\n storeServerTokens,\n validateOauth2Tokens,\n} from \"@/shared/lib/util.js\";\nimport type { AuthenticationResolver, PKCEProducer } from \"@/services/types.ts\";\nimport { DEFAULT_AUTH_SERVER } from \"@/constants.js\";\nimport { CodeVerifier } from \"@/shared/lib/types.js\";\nimport { loggers } from \"@/lib/logger.js\";\nimport { getUser, getUserFromTokens } from \"@/shared/lib/session.js\";\nimport { GenericUserSession } from \"@/shared/lib/UserSession.js\";\nimport type { CookieStorage } from \"@/shared/lib/storage.js\";\nimport { AuthenticationRefresherImpl } from \"@/shared/lib/AuthenticationRefresherImpl.js\";\n\nconst logger = loggers.services.validation;\n\nexport class ServerAuthenticationResolver implements AuthenticationResolver {\n private pkceProducer: PKCEProducer | null;\n private oauth2client: OAuth2Client | undefined;\n private endpoints: Endpoints | undefined;\n\n private constructor(\n readonly authConfig: AuthConfig,\n readonly storage: AuthStorage,\n readonly endpointOverrides?: Partial<Endpoints>,\n ) {\n // Determine if PKCE should be used based on config\n // Default to true\n const usePkce = authConfig.pkce !== false;\n\n // Only create PKCE producer if we're using PKCE\n this.pkceProducer = usePkce\n ? new GenericPublicClientPKCEProducer(storage)\n : null;\n }\n\n /**\n * Attempts to refresh tokens if a refresh token is available\n * @param sessionData Current session data\n * @returns Updated session data\n */\n async tryRefreshTokens(\n sessionData: SessionData | null,\n ): Promise<SessionData> {\n logger.debug(\"tryRefreshTokens\", { sessionData });\n // If there's a refresh token, attempt to refresh tokens\n if (sessionData?.refreshToken) {\n const authRefresher = await AuthenticationRefresherImpl.build(\n {\n ...this.authConfig,\n oauthServer: this.authConfig.oauthServer ?? DEFAULT_AUTH_SERVER,\n },\n this.storage,\n async (error) => {\n logger.error(\n \"ServerAuthenticationResolver: Error refreshing tokens\",\n { error },\n );\n return Promise.reject(error);\n },\n this.endpointOverrides,\n );\n const tokenResponseBody = await authRefresher.refreshAccessToken();\n if (!tokenResponseBody) {\n throw new Error(\"No tokens returned from refresh\");\n }\n // Store user data if a user can be derived from the tokens\n try {\n const user = await getUserFromTokens(tokenResponseBody);\n if (user) {\n const userSession = new GenericUserSession(this.storage);\n await userSession.set(user);\n logger.debug(\"User cookie stored successfully\", {\n hasUser: !!user,\n });\n } else {\n logger.warn(\"No user found after token exchange\");\n }\n } catch (error) {\n logger.error(\"Failed to store user cookie:\", error);\n }\n // Construct a refreshed session with the new tokens\n return {\n authenticated: true,\n idToken: tokenResponseBody.id_token,\n accessToken: tokenResponseBody.access_token,\n refreshToken: tokenResponseBody.refresh_token,\n oidcSessionExpiresAt: tokenResponseBody.oidc_session_expires_at,\n wasRehydrated: true,\n };\n }\n\n // No refresh token available\n return { ...sessionData, authenticated: false };\n }\n\n /**\n * returns The session data if the session is valid, otherwise an unauthenticated session\n * @returns {Promise<SessionData>}\n */\n async validateExistingSession(\n attemptRehydration = true,\n ): Promise<SessionData> {\n // TODO: investigate a more peformant way to validate a server session\n // other than using JWKS and JWT verification which is what validateOauth2Tokens uses\n const sessionData = await this.getSessionData();\n\n logger.debug(\"validateExistingSession\", {\n disableRefresh: this.authConfig.disableRefresh,\n });\n // If we don't have an ID token, try to refresh if we have a refresh token\n // Access token is no longer required for authentication\n if (!sessionData?.idToken) {\n if (attemptRehydration && !this.authConfig.disableRefresh) {\n const refreshedSessionData = await this.tryRefreshTokens(sessionData);\n if (refreshedSessionData.authenticated) {\n return refreshedSessionData;\n }\n }\n\n return { ...sessionData, authenticated: false };\n }\n\n // Initialize if needed\n if (!this.endpoints?.jwks || !this.oauth2client) await this.init();\n\n if (!this.endpoints?.jwks) {\n throw new Error(\"JWKS endpoint not found\");\n }\n\n try {\n // Validate existing tokens - access token validation happens only if it exists\n await validateOauth2Tokens(\n {\n access_token: sessionData.accessToken, // May be undefined\n id_token: sessionData.idToken, // Always required\n refresh_token: sessionData.refreshToken,\n oidc_session_expires_at: sessionData.oidcSessionExpiresAt,\n },\n this.endpoints.jwks,\n this.oauth2client!,\n this.oauthServer,\n );\n return sessionData;\n } catch (error) {\n logger.warn(\"Error validating tokens\", { error });\n if (attemptRehydration && !this.authConfig.disableRefresh) {\n // If token validation fails, try to refresh tokens\n try {\n const refreshedSessionData = await this.tryRefreshTokens(sessionData);\n if (refreshedSessionData.authenticated) {\n return refreshedSessionData;\n }\n } catch (error) {\n logger.error(\"Error refreshing tokens after validation failure\", {\n error,\n });\n return { ...sessionData, authenticated: false };\n }\n }\n\n return { ...sessionData, authenticated: false };\n }\n }\n\n get oauthServer(): string {\n return this.authConfig.oauthServer || DEFAULT_AUTH_SERVER;\n }\n\n async init(): Promise<this> {\n // Ensure clientId is present for OAuth operations\n if (!this.authConfig.clientId) {\n throw new Error(\"clientId is required for OAuth server operations\");\n }\n\n // resolve oauth config\n this.endpoints = await getEndpointsWithOverrides(\n this.oauthServer,\n this.endpointOverrides,\n );\n this.oauth2client = new OAuth2Client(\n this.authConfig.clientId,\n this.endpoints.auth,\n this.endpoints.token,\n {\n redirectURI: this.authConfig.redirectUrl,\n },\n );\n\n return this;\n }\n\n async tokenExchange(\n code: string,\n state: string,\n ): Promise<OIDCTokenResponseBody> {\n if (!this.oauth2client) await this.init();\n\n // Check if we're using PKCE and validate code verifier if needed\n if (this.pkceProducer) {\n const codeVerifier = await this.pkceProducer.getCodeVerifier();\n if (!codeVerifier) throw new Error(\"Code verifier not found in storage\");\n }\n\n // exchange auth code for tokens\n const tokens = await exchangeTokens(\n code,\n state,\n this.pkceProducer,\n this.oauth2client!, // clean up types here to avoid the ! operator\n this.oauthServer,\n this.endpoints!, // clean up types here to avoid the ! operator\n this.authConfig.clientSecret,\n );\n\n await storeServerTokens(this.storage, tokens);\n\n // Store user data in cookie (like VanillaJS implementation does)\n try {\n const user = await getUser(this.storage);\n if (user) {\n const userSession = new GenericUserSession(this.storage);\n await userSession.set(user);\n logger.debug(\"User cookie stored successfully\", { hasUser: !!user });\n } else {\n logger.warn(\"No user found after token exchange\");\n }\n } catch (error) {\n logger.error(\"Failed to store user cookie:\", error);\n // Don't throw - tokens are already stored, this is just for client-side convenience\n }\n\n // the code verifier should be single-use, so we delete it if using PKCE\n if (this.pkceProducer) {\n await this.storage.delete(CodeVerifier.COOKIE_NAME);\n }\n return tokens;\n }\n\n async getSessionData(): Promise<SessionData | null> {\n const storageData = await retrieveTokens(this.storage);\n\n if (!storageData) return null;\n\n return {\n authenticated: !!storageData.id_token, // User is authenticated if they have an ID token\n idToken: storageData.id_token,\n accessToken: storageData.access_token, // Optional\n refreshToken: storageData.refresh_token,\n oidcSessionExpiresAt: storageData.oidc_session_expires_at,\n };\n }\n\n async getEndSessionEndpoint(): Promise<string | null> {\n if (!this.endpoints) {\n return null;\n }\n return this.endpoints.endsession;\n }\n\n static async build(\n authConfig: AuthConfig,\n storage: CookieStorage,\n endpointOverrides?: Partial<Endpoints>,\n ): Promise<AuthenticationResolver> {\n const resolver = new ServerAuthenticationResolver(\n authConfig,\n storage,\n endpointOverrides,\n );\n await resolver.init();\n\n return resolver;\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthenticationRefresherImpl.d.ts","sourceRoot":"","sources":["../../../src/shared/lib/AuthenticationRefresherImpl.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"AuthenticationRefresherImpl.d.ts","sourceRoot":"","sources":["../../../src/shared/lib/AuthenticationRefresherImpl.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AASrD,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEhF,OAAO,EAAE,8BAA8B,EAAE,MAAM,qCAAqC,CAAC;AAGrF,qBAAa,2BAA4B,SAAQ,8BAA8B;IAO3E,SAAS,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC;IANlD,OAAO,CAAC,SAAS,CAAwB;IACzC,OAAO,CAAC,YAAY,CAA2B;gBAE7C,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,IAAI,CAAC,EAC9B,iBAAiB,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,YAAA;IAQ5C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;WAyBd,KAAK,CAChB,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,IAAI,CAAC,EACxC,iBAAiB,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,GACrC,OAAO,CAAC,2BAA2B,CAAC;IAYjC,WAAW,CACf,iBAAiB,EAAE,qBAAqB,GAAG,IAAI,GAC9C,OAAO,CAAC,IAAI,CAAC;IAcV,kBAAkB,IAAI,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC;CA8ClE"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { clearTokens, clearUser, getEndpointsWithOverrides, storeTokens, validateOauth2Tokens, } from "../../shared/lib/util.js";
|
|
1
|
+
import { clearTokens, clearUser, getEndpointsWithOverrides, storeServerTokens, storeTokens, validateOauth2Tokens, } from "../../shared/lib/util.js";
|
|
2
2
|
import { OAuth2Client } from "oslo/oauth2";
|
|
3
3
|
import { GenericAuthenticationRefresher } from "./GenericAuthenticationRefresher.js";
|
|
4
|
+
import { loggers } from "../../lib/logger.js";
|
|
4
5
|
export class AuthenticationRefresherImpl extends GenericAuthenticationRefresher {
|
|
5
6
|
endpointOverrides;
|
|
6
7
|
endpoints;
|
|
@@ -37,38 +38,44 @@ export class AuthenticationRefresherImpl extends GenericAuthenticationRefresher
|
|
|
37
38
|
// For null tokenResponseBody, we skip storage since tokens might be managed elsewhere (e.g., HTTP-only cookies)
|
|
38
39
|
if (!tokenResponseBody)
|
|
39
40
|
return;
|
|
41
|
+
if (this.storage.storageType === "cookie") {
|
|
42
|
+
loggers.services.refresh.info("Storing tokens in server-side storage");
|
|
43
|
+
await storeServerTokens(this.storage, tokenResponseBody);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
loggers.services.refresh.info("Storing tokens in non-cookie storage");
|
|
40
47
|
await storeTokens(this.storage, tokenResponseBody);
|
|
41
48
|
}
|
|
42
49
|
async refreshAccessToken() {
|
|
43
50
|
if (!this.storage)
|
|
44
51
|
throw new Error("No storage available");
|
|
52
|
+
// this will throw if no refresh token is available
|
|
53
|
+
const refreshToken = await this.getRefreshToken();
|
|
54
|
+
if (!this.oauth2client) {
|
|
55
|
+
await this.init();
|
|
56
|
+
}
|
|
57
|
+
if (!this.endpoints?.jwks) {
|
|
58
|
+
throw new Error("No jwks endpoint");
|
|
59
|
+
}
|
|
45
60
|
try {
|
|
46
|
-
const refreshToken = await this.getRefreshToken();
|
|
47
|
-
if (!this.oauth2client) {
|
|
48
|
-
await this.init();
|
|
49
|
-
}
|
|
50
|
-
if (!this.endpoints?.jwks) {
|
|
51
|
-
throw new Error("No jwks endpoint");
|
|
52
|
-
}
|
|
53
61
|
const oauth2Client = this.oauth2client;
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
await validateOauth2Tokens(tokenResponseBody, this.endpoints.jwks, oauth2Client, this.oauthServer);
|
|
59
|
-
await this.storeTokens(tokenResponseBody);
|
|
60
|
-
return tokenResponseBody;
|
|
61
|
-
}
|
|
62
|
-
catch (tokenRequestError) {
|
|
63
|
-
console.error("Error during refresh token network request:", tokenRequestError);
|
|
64
|
-
throw new Error(`Token refresh failed: ${tokenRequestError.message}`);
|
|
62
|
+
const refreshOptions = {};
|
|
63
|
+
if (this.authConfig?.clientSecret) {
|
|
64
|
+
refreshOptions.credentials = this.authConfig.clientSecret;
|
|
65
|
+
refreshOptions.authenticateWith = "request_body";
|
|
65
66
|
}
|
|
67
|
+
const tokenResponseBody = (await oauth2Client.refreshAccessToken(refreshToken, refreshOptions));
|
|
68
|
+
// Validate the refreshed tokens - ID token is the primary token
|
|
69
|
+
// Access token validation is now optional
|
|
70
|
+
await validateOauth2Tokens(tokenResponseBody, this.endpoints.jwks, oauth2Client, this.oauthServer);
|
|
71
|
+
await this.storeTokens(tokenResponseBody);
|
|
72
|
+
return tokenResponseBody;
|
|
66
73
|
}
|
|
67
74
|
catch (error) {
|
|
68
|
-
console.warn("
|
|
75
|
+
console.warn("OAuth server refresh call failed, clearing tokens and user", error);
|
|
69
76
|
await clearTokens(this.storage);
|
|
70
77
|
await clearUser(this.storage);
|
|
71
|
-
throw error;
|
|
78
|
+
throw new Error(`Token refresh failed: ${error.message}`);
|
|
72
79
|
}
|
|
73
80
|
}
|
|
74
81
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthenticationRefresherImpl.js","sourceRoot":"","sources":["../../../src/shared/lib/AuthenticationRefresherImpl.ts"],"names":[],"mappings":"AACA,OAAO,EACL,WAAW,EACX,SAAS,EACT,yBAAyB,EACzB,WAAW,EACX,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,8BAA8B,EAAE,MAAM,qCAAqC,CAAC;
|
|
1
|
+
{"version":3,"file":"AuthenticationRefresherImpl.js","sourceRoot":"","sources":["../../../src/shared/lib/AuthenticationRefresherImpl.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AuthConfig } from \"@/server/config.js\";\nimport {\n clearTokens,\n clearUser,\n getEndpointsWithOverrides,\n storeServerTokens,\n storeTokens,\n validateOauth2Tokens,\n} from \"@/shared/lib/util.js\";\nimport type { AuthStorage, Endpoints, OIDCTokenResponseBody } from \"@/types.js\";\nimport { OAuth2Client } from \"oslo/oauth2\";\nimport { GenericAuthenticationRefresher } from \"./GenericAuthenticationRefresher.js\";\nimport { loggers } from \"@/lib/logger.js\";\n\nexport class AuthenticationRefresherImpl extends GenericAuthenticationRefresher {\n private endpoints: Endpoints | undefined;\n private oauth2client: OAuth2Client | undefined;\n constructor(\n authConfig: AuthConfig,\n storage: AuthStorage,\n onError: (error: Error) => Promise<void>,\n protected endpointOverrides?: Partial<Endpoints>,\n ) {\n super(onError);\n this.authConfig = authConfig;\n this.storage = storage;\n this.init();\n }\n\n async init(): Promise<this> {\n if (!this.authConfig) throw new Error(\"No auth config available\");\n\n // Ensure clientId is present for OAuth operations\n if (!this.authConfig.clientId) {\n throw new Error(\"clientId is required for OAuth refresh operations\");\n }\n\n // resolve oauth config\n this.endpoints = await getEndpointsWithOverrides(\n this.oauthServer,\n this.endpointOverrides,\n );\n this.oauth2client = new OAuth2Client(\n this.authConfig.clientId,\n this.endpoints.auth,\n this.endpoints.token,\n {\n redirectURI: this.authConfig.redirectUrl,\n },\n );\n\n return this;\n }\n\n static async build(\n authConfig: AuthConfig,\n storage: AuthStorage,\n onError: (error: Error) => Promise<void>,\n endpointOverrides?: Partial<Endpoints>,\n ): Promise<AuthenticationRefresherImpl> {\n const refresher = new AuthenticationRefresherImpl(\n authConfig,\n storage,\n onError,\n endpointOverrides,\n );\n await refresher.init();\n\n return refresher;\n }\n\n async storeTokens(\n tokenResponseBody: OIDCTokenResponseBody | null,\n ): Promise<void> {\n if (!this.storage) throw new Error(\"No storage available\");\n // For null tokenResponseBody, we skip storage since tokens might be managed elsewhere (e.g., HTTP-only cookies)\n if (!tokenResponseBody) return;\n\n if (this.storage.storageType === \"cookie\") {\n loggers.services.refresh.info(\"Storing tokens in server-side storage\");\n await storeServerTokens(this.storage, tokenResponseBody);\n return;\n }\n loggers.services.refresh.info(\"Storing tokens in non-cookie storage\");\n await storeTokens(this.storage, tokenResponseBody);\n }\n\n async refreshAccessToken(): Promise<OIDCTokenResponseBody | null> {\n if (!this.storage) throw new Error(\"No storage available\");\n\n // this will throw if no refresh token is available\n const refreshToken = await this.getRefreshToken();\n if (!this.oauth2client) {\n await this.init();\n }\n if (!this.endpoints?.jwks) {\n throw new Error(\"No jwks endpoint\");\n }\n try {\n const oauth2Client = this.oauth2client!;\n\n const refreshOptions: Record<string, string> = {};\n if (this.authConfig?.clientSecret) {\n refreshOptions.credentials = this.authConfig.clientSecret;\n refreshOptions.authenticateWith = \"request_body\";\n }\n\n const tokenResponseBody = (await oauth2Client.refreshAccessToken(\n refreshToken,\n refreshOptions,\n )) as OIDCTokenResponseBody;\n\n // Validate the refreshed tokens - ID token is the primary token\n // Access token validation is now optional\n await validateOauth2Tokens(\n tokenResponseBody,\n this.endpoints.jwks,\n oauth2Client,\n this.oauthServer,\n );\n\n await this.storeTokens(tokenResponseBody);\n return tokenResponseBody;\n } catch (error) {\n console.warn(\n \"OAuth server refresh call failed, clearing tokens and user\",\n error,\n );\n await clearTokens(this.storage);\n await clearUser(this.storage);\n throw new Error(`Token refresh failed: ${(error as Error).message}`);\n }\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BrowserAuthenticationRefresher.d.ts","sourceRoot":"","sources":["../../../src/shared/lib/BrowserAuthenticationRefresher.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AAC/E,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGrD,MAAM,WAAW,qBAAqB;IACpC,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC/B,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACzC;AAED,qBAAa,8BAA+B,SAAQ,2BAA2B;IAC7E,OAAO,CAAC,qBAAqB,CAAC,CAAwB;WAChC,KAAK,CACzB,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,IAAI,CAAC,EACxC,iBAAiB,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,EACtC,qBAAqB,CAAC,EAAE,qBAAqB,GAC5C,OAAO,CAAC,8BAA8B,CAAC;IAa1C,SAAS,CAAC,WAAW,CAAC,KAAK,EAAE,KAAK;cAMlB,iBAAiB;
|
|
1
|
+
{"version":3,"file":"BrowserAuthenticationRefresher.d.ts","sourceRoot":"","sources":["../../../src/shared/lib/BrowserAuthenticationRefresher.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AAC/E,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGrD,MAAM,WAAW,qBAAqB;IACpC,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC/B,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACzC;AAED,qBAAa,8BAA+B,SAAQ,2BAA2B;IAC7E,OAAO,CAAC,qBAAqB,CAAC,CAAwB;WAChC,KAAK,CACzB,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,IAAI,CAAC,EACxC,iBAAiB,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,EACtC,qBAAqB,CAAC,EAAE,qBAAqB,GAC5C,OAAO,CAAC,8BAA8B,CAAC;IAa1C,SAAS,CAAC,WAAW,CAAC,KAAK,EAAE,KAAK;cAMlB,iBAAiB;IAsD3B,gBAAgB;IAqCtB,gBAAgB;CAWjB"}
|
|
@@ -21,6 +21,12 @@ export class BrowserAuthenticationRefresher extends AuthenticationRefresherImpl
|
|
|
21
21
|
console.warn("Auto-refresh aborted, skipping token refresh attempt");
|
|
22
22
|
return;
|
|
23
23
|
}
|
|
24
|
+
// Check if page is hidden/frozen to prevent cookie-less refresh attempts
|
|
25
|
+
if (typeof document !== "undefined" &&
|
|
26
|
+
(document.hidden || document.visibilityState === "hidden")) {
|
|
27
|
+
console.info("Page is hidden/frozen, skipping auto-refresh to prevent cookie-less requests", new Date());
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
24
30
|
const existingUser = await this.storage?.get(UserStorage.USER);
|
|
25
31
|
if (!existingUser) {
|
|
26
32
|
console.warn("BrowserAuthenticationRefresher: No user found, skipping refresh");
|