@civic/auth 0.9.0 → 0.9.1-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -0
- package/dist/lib/logger.d.ts +6 -0
- package/dist/lib/logger.d.ts.map +1 -1
- package/dist/lib/logger.js +7 -0
- package/dist/lib/logger.js.map +1 -1
- package/dist/nextjs/config.d.ts +2 -4
- package/dist/nextjs/config.d.ts.map +1 -1
- package/dist/nextjs/config.js +4 -57
- package/dist/nextjs/config.js.map +1 -1
- package/dist/react-router-7/components/UserButton.d.ts +13 -0
- package/dist/react-router-7/components/UserButton.d.ts.map +1 -0
- package/dist/react-router-7/components/UserButton.js +108 -0
- package/dist/react-router-7/components/UserButton.js.map +1 -0
- package/dist/react-router-7/components/UserButtonPresentation.d.ts +10 -0
- package/dist/react-router-7/components/UserButtonPresentation.d.ts.map +1 -0
- package/dist/react-router-7/components/UserButtonPresentation.js +19 -0
- package/dist/react-router-7/components/UserButtonPresentation.js.map +1 -0
- package/dist/react-router-7/config.d.ts +69 -0
- package/dist/react-router-7/config.d.ts.map +1 -0
- package/dist/react-router-7/config.js +88 -0
- package/dist/react-router-7/config.js.map +1 -0
- package/dist/react-router-7/cookies.d.ts +40 -0
- package/dist/react-router-7/cookies.d.ts.map +1 -0
- package/dist/react-router-7/cookies.js +125 -0
- package/dist/react-router-7/cookies.js.map +1 -0
- package/dist/react-router-7/index.d.ts +10 -0
- package/dist/react-router-7/index.d.ts.map +1 -0
- package/dist/react-router-7/index.js +12 -0
- package/dist/react-router-7/index.js.map +1 -0
- package/dist/react-router-7/routeHandler.d.ts +51 -0
- package/dist/react-router-7/routeHandler.d.ts.map +1 -0
- package/dist/react-router-7/routeHandler.js +323 -0
- package/dist/react-router-7/routeHandler.js.map +1 -0
- package/dist/react-router-7/useUser.d.ts +43 -0
- package/dist/react-router-7/useUser.d.ts.map +1 -0
- package/dist/react-router-7/useUser.js +92 -0
- package/dist/react-router-7/useUser.js.map +1 -0
- package/dist/reactjs/core/GlobalAuthManager.d.ts +2 -1
- package/dist/reactjs/core/GlobalAuthManager.d.ts.map +1 -1
- package/dist/reactjs/core/GlobalAuthManager.js +16 -2
- package/dist/reactjs/core/GlobalAuthManager.js.map +1 -1
- package/dist/server/ServerAuthenticationResolver.d.ts.map +1 -1
- package/dist/server/ServerAuthenticationResolver.js +4 -0
- package/dist/server/ServerAuthenticationResolver.js.map +1 -1
- package/dist/server/config.d.ts +11 -3
- package/dist/server/config.d.ts.map +1 -1
- package/dist/server/config.js.map +1 -1
- package/dist/server/login.d.ts.map +1 -1
- package/dist/server/login.js +5 -0
- package/dist/server/login.js.map +1 -1
- package/dist/server/logout.d.ts.map +1 -1
- package/dist/server/logout.js +5 -0
- package/dist/server/logout.js.map +1 -1
- package/dist/server/session.d.ts.map +1 -1
- package/dist/server/session.js +5 -0
- package/dist/server/session.js.map +1 -1
- package/dist/services/AuthenticationService.d.ts.map +1 -1
- package/dist/services/AuthenticationService.js +0 -5
- package/dist/services/AuthenticationService.js.map +1 -1
- package/dist/services/PKCE.d.ts.map +1 -1
- package/dist/services/PKCE.js +4 -1
- package/dist/services/PKCE.js.map +1 -1
- package/dist/shared/hooks/useCivicAuthConfig.d.ts +1 -1
- package/dist/shared/hooks/useCivicAuthConfig.d.ts.map +1 -1
- package/dist/shared/lib/AuthenticationRefresherImpl.d.ts.map +1 -1
- package/dist/shared/lib/AuthenticationRefresherImpl.js +4 -0
- package/dist/shared/lib/AuthenticationRefresherImpl.js.map +1 -1
- package/dist/shared/lib/cookieConfig.d.ts +46 -0
- package/dist/shared/lib/cookieConfig.d.ts.map +1 -0
- package/dist/shared/lib/cookieConfig.js +99 -0
- package/dist/shared/lib/cookieConfig.js.map +1 -0
- package/dist/shared/version.d.ts +1 -1
- package/dist/shared/version.d.ts.map +1 -1
- package/dist/shared/version.js +1 -1
- package/dist/shared/version.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/vanillajs/auth/CivicAuth.d.ts +1 -1
- package/dist/vanillajs/auth/CivicAuth.d.ts.map +1 -1
- package/dist/vanillajs/auth/CivicAuth.js +36 -9
- package/dist/vanillajs/auth/CivicAuth.js.map +1 -1
- package/dist/vanillajs/auth/config/ConfigProcessor.js +1 -1
- package/dist/vanillajs/auth/config/ConfigProcessor.js.map +1 -1
- package/dist/vanillajs/auth/handlers/MessageHandler.d.ts.map +1 -1
- package/dist/vanillajs/auth/handlers/MessageHandler.js +3 -0
- package/dist/vanillajs/auth/handlers/MessageHandler.js.map +1 -1
- package/dist/vanillajs/auth/types/AuthTypes.d.ts +31 -12
- package/dist/vanillajs/auth/types/AuthTypes.d.ts.map +1 -1
- package/dist/vanillajs/auth/types/AuthTypes.js.map +1 -1
- package/package.json +13 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routeHandler.js","sourceRoot":"","sources":["../../src/react-router-7/routeHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import { redirect, type LoaderFunctionArgs } from \"react-router\";\nimport { CivicAuth } from \"@civic/auth/server\";\nimport { ReactRouterCookieStorage } from \"./cookies.js\";\nimport { resolveAuthConfig } from \"./config.js\";\nimport type { AuthConfig } from \"./config.js\";\n\n/**\n * Create auth route handlers for React Router - backend endpoints compatible with VanillaJS frontend integration\n * These routes work similar to the Express example, using server-side CivicAuth SDK\n */\nexport function createRouteHandlers(configOverrides: Partial<AuthConfig> = {}) {\n const config = resolveAuthConfig(configOverrides);\n\n const whitelistedFrontEndConfig = [\n \"clientId\",\n \"oauthServer\",\n \"callbackUrl\",\n \"logoutCallbackUrl\",\n \"loginUrl\",\n \"baseUrl\",\n ].reduce(\n (acc, key) => {\n acc[key] = config[key as keyof AuthConfig] as string;\n return acc;\n },\n {} as Record<string, string>,\n );\n\n /**\n * Helper to create CivicAuth instance for a request\n */\n const createCivicAuth = (request: Request) => {\n const cookieStorage = new ReactRouterCookieStorage();\n\n // Set the request context for reading cookies\n cookieStorage.setRequest(request);\n\n const host = config.baseUrl ?? new URL(request.url).origin;\n\n const civicAuth = new CivicAuth(cookieStorage, {\n clientId: config.clientId,\n redirectUrl: config.callbackUrl ?? `${host}/auth/callback`,\n oauthServer: config.oauthServer,\n postLogoutRedirectUrl: config.logoutCallbackUrl ?? `${host}/auth/logout`,\n loginSuccessUrl: `${host}/auth/callback`,\n });\n\n return {\n civicAuth,\n // Use the original cookieStorage instance that we properly configured with setRequest()\n cookieStorage,\n };\n };\n\n /**\n * Helper to create response with cookie headers\n * Following React Router pattern: add serialized cookies as \"Set-Cookie\" headers\n */\n const createResponseWithCookies = (\n body: string,\n init: ResponseInit,\n cookieStorage: ReactRouterCookieStorage,\n ): Response => {\n const headers = new Headers(init.headers);\n\n // Add cookie headers from storage - each one is a complete \"Set-Cookie\" header from cookie.serialize()\n const cookieHeaders = cookieStorage.getCookieHeaders();\n\n cookieHeaders.forEach((cookieHeader) => {\n headers.append(\"Set-Cookie\", cookieHeader);\n });\n\n return new Response(body, {\n ...init,\n headers,\n });\n };\n\n /**\n * Helper to create redirect with cookie headers\n * Following React Router pattern: add serialized cookies as \"Set-Cookie\" headers\n */\n const redirectWithCookies = (\n url: string,\n cookieStorage: ReactRouterCookieStorage,\n init?: ResponseInit,\n ): Response => {\n const headers = new Headers(init?.headers);\n\n // Add cookie headers from storage - each one is a complete \"Set-Cookie\" header from cookie.serialize()\n const cookieHeaders = cookieStorage.getCookieHeaders();\n\n cookieHeaders.forEach((cookieHeader) => {\n headers.append(\"Set-Cookie\", cookieHeader);\n });\n\n // Set Location header for proper redirect\n headers.set(\"Location\", url);\n\n return new Response(null, {\n ...init,\n status: 302,\n headers,\n });\n };\n\n const handlers = {\n /**\n * Login loader - backend OAuth login initiation endpoint\n * Uses CivicAuth.buildLoginUrl() like Express example\n */\n loginLoader: async ({ request }: LoaderFunctionArgs) => {\n const incomingUrl = new URL(request.url);\n const frontendState = incomingUrl.searchParams.get(\"state\");\n // const returnTo = incomingUrl.searchParams.get(\"returnTo\") || \"/\";\n\n try {\n const { civicAuth, cookieStorage } = createCivicAuth(request);\n\n const url = await civicAuth.buildLoginUrl({\n state: frontendState || undefined,\n });\n\n const response = redirectWithCookies(url.toString(), cookieStorage);\n\n return response;\n } catch (error) {\n console.error(\"[LOGIN_HANDLER] Backend login error:\", error);\n return redirect(\"/?error=login_failed\");\n }\n },\n\n /**\n * Callback loader - backend OAuth callback endpoint\n * Uses CivicAuth.handleCallback() like Express example\n */\n callbackLoader: async ({ request }: LoaderFunctionArgs) => {\n try {\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 (error) {\n console.error(\"OAuth error in callback:\", error);\n return redirect(\"/?error=oauth_error\");\n }\n\n if (!code || !state) {\n throw new Error(\"Missing code or state parameter\");\n }\n\n const { civicAuth, cookieStorage } = createCivicAuth(request);\n\n // Convert React Router request to the format expected by handleCallback\n const handleCallbackRequest = {\n headers: Object.fromEntries(request.headers.entries()),\n };\n\n // For non-iframe requests, use the original handleCallback logic\n const result = await civicAuth.handleCallback({\n code,\n state,\n req: handleCallbackRequest,\n });\n\n if (result.redirectTo) {\n return redirectWithCookies(result.redirectTo, cookieStorage);\n }\n\n if (result.content) {\n // Handle both string content and object content\n if (typeof result.content === \"string\") {\n return createResponseWithCookies(\n result.content,\n {\n status: 200,\n headers: {\n \"Content-Type\": \"text/html\",\n },\n },\n cookieStorage,\n );\n } else {\n // Object content (JSON response)\n return createResponseWithCookies(\n JSON.stringify(result.content),\n {\n status: 200,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n },\n cookieStorage,\n );\n }\n }\n\n // Fallback redirect\n return redirectWithCookies(\"/\", cookieStorage);\n } catch (error) {\n console.error(\"[CALLBACK_HANDLER] OAuth callback error:\", error);\n return redirect(\"/?error=callback_failed\");\n }\n },\n\n /**\n * Logout loader - backend logout endpoint\n * Uses CivicAuth.buildLogoutRedirectUrl() and clearTokens() like Express example\n */\n logoutLoader: async ({ request }: LoaderFunctionArgs) => {\n try {\n const { civicAuth, cookieStorage } = createCivicAuth(request);\n\n const logoutUrl = await civicAuth.buildLogoutRedirectUrl();\n await civicAuth.clearTokens();\n\n const url = new URL(logoutUrl.toString());\n // Remove the state parameter to avoid it showing up in the frontend URL\n url.searchParams.delete(\"state\");\n\n return redirectWithCookies(url.toString(), cookieStorage);\n } catch (error) {\n console.error(\"[LOGOUT_HANDLER] Logout error:\", error);\n // If logout URL generation fails, clear tokens and redirect to home (Express pattern)\n try {\n const { civicAuth, cookieStorage } = createCivicAuth(request);\n await civicAuth.clearTokens();\n return redirectWithCookies(\"/\", cookieStorage);\n } catch (clearError) {\n console.error(\"[LOGOUT_HANDLER] Failed to clear tokens:\", clearError);\n return redirect(\"/\");\n }\n }\n },\n\n /**\n * User endpoint - returns current user data as JSON\n * Uses CivicAuth.isLoggedIn() and getUser() like Express example\n */\n userLoader: async ({ request }: LoaderFunctionArgs) => {\n try {\n const { civicAuth, cookieStorage } = createCivicAuth(request);\n\n const isLoggedIn = await civicAuth.isLoggedIn();\n\n if (!isLoggedIn) {\n return createResponseWithCookies(\n JSON.stringify({ error: \"Not authenticated\" }),\n {\n status: 401,\n headers: { \"Content-Type\": \"application/json\" },\n },\n cookieStorage,\n );\n }\n\n const user = await civicAuth.getUser();\n\n return createResponseWithCookies(\n JSON.stringify({ user }),\n {\n status: 200,\n headers: { \"Content-Type\": \"application/json\" },\n },\n cookieStorage,\n );\n } catch (error) {\n console.error(\"[USER_HANDLER] User endpoint error:\", error);\n return new Response(\n JSON.stringify({ error: \"Internal server error\" }),\n {\n status: 500,\n headers: { \"Content-Type\": \"application/json\" },\n },\n );\n }\n },\n\n /**\n * Refresh endpoint - refreshes access tokens\n * Uses CivicAuth.refreshTokens() like Express example\n */\n refreshLoader: async ({ request }: LoaderFunctionArgs) => {\n try {\n const { civicAuth, cookieStorage } = createCivicAuth(request);\n\n const isLoggedIn = await civicAuth.isLoggedIn();\n if (!isLoggedIn) {\n return createResponseWithCookies(\n JSON.stringify({ error: \"Not authenticated\" }),\n {\n status: 401,\n headers: { \"Content-Type\": \"application/json\" },\n },\n cookieStorage,\n );\n }\n\n await civicAuth.refreshTokens();\n\n return createResponseWithCookies(\n JSON.stringify({ success: true, message: \"Tokens refreshed\" }),\n {\n status: 200,\n headers: { \"Content-Type\": \"application/json\" },\n },\n cookieStorage,\n );\n } catch (error) {\n console.error(\"[REFRESH_HANDLER] Token refresh error:\", error);\n return new Response(JSON.stringify({ error: \"Token refresh failed\" }), {\n status: 500,\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n },\n\n /**\n * Get user data from session (for SSR)\n * Uses CivicAuth.isLoggedIn() and getUser() like Express example\n */\n getUser: async (request: Request) => {\n try {\n const { civicAuth } = createCivicAuth(request);\n\n const isLoggedIn = await civicAuth.isLoggedIn();\n if (!isLoggedIn) {\n return null;\n }\n\n return await civicAuth.getUser();\n } catch (error) {\n console.error(\"[GETUSER_HANDLER] getUser error:\", error);\n return null;\n }\n },\n\n /**\n * Get auth data including user and config (for SSR)\n * Returns user data, config, and other auth-related data needed by the app under a civic key\n */\n getAuthData: async (request: Request) => {\n try {\n const { civicAuth } = createCivicAuth(request);\n\n const isLoggedIn = await civicAuth.isLoggedIn();\n const user = isLoggedIn ? await civicAuth.getUser() : null;\n\n return {\n civic: {\n user,\n config: whitelistedFrontEndConfig,\n isLoggedIn,\n },\n };\n } catch (error) {\n console.error(\"[GETAUTHDATA_HANDLER] getAuthData error:\", error);\n return {\n civic: {\n user: null,\n config: whitelistedFrontEndConfig,\n isLoggedIn: false,\n },\n };\n }\n },\n };\n\n /**\n * Creates a loader function that handles all auth routes\n * @example\n * // In your auth.$.tsx route file:\n * export const loader = createAuthLoader();\n */\n const createAuthLoader = () => {\n return async (args: LoaderFunctionArgs) => {\n // Get the auth path from the URL\n const authPath = args.params[\"*\"];\n\n // Route to the appropriate handler\n switch (authPath) {\n case \"login\":\n return handlers.loginLoader(args);\n\n case \"callback\":\n return handlers.callbackLoader(args);\n\n case \"refresh\":\n return handlers.refreshLoader(args);\n\n case \"logout\":\n return handlers.logoutLoader(args);\n\n case \"user\":\n return handlers.userLoader(args);\n\n default:\n // Return 404 for unknown auth paths\n return new Response(\"Not Found\", { status: 404 });\n }\n };\n };\n\n return {\n ...handlers,\n createAuthLoader,\n };\n}\n"]}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type AuthResult, type User } from "@civic/auth/vanillajs";
|
|
2
|
+
import type { AuthConfig } from "./config.js";
|
|
3
|
+
export interface SignInConfig {
|
|
4
|
+
clientId?: string;
|
|
5
|
+
baseUrl?: string;
|
|
6
|
+
displayMode?: "iframe" | "redirect" | "new_tab" | "custom_tab";
|
|
7
|
+
targetContainerElement?: HTMLElement | string;
|
|
8
|
+
}
|
|
9
|
+
export interface CivicAuthData {
|
|
10
|
+
user: User | null;
|
|
11
|
+
isLoggedIn: boolean;
|
|
12
|
+
config: AuthConfig;
|
|
13
|
+
}
|
|
14
|
+
export interface RootLoaderData {
|
|
15
|
+
civic: CivicAuthData;
|
|
16
|
+
}
|
|
17
|
+
export interface AuthData {
|
|
18
|
+
isLoggedIn: boolean;
|
|
19
|
+
user: User | null;
|
|
20
|
+
loginUrl: string;
|
|
21
|
+
logoutUrl: string;
|
|
22
|
+
signIn: (config?: SignInConfig) => Promise<AuthResult>;
|
|
23
|
+
signOut: (baseUrl?: string) => Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Hook to access auth data from the root loader
|
|
27
|
+
* @returns CivicAuthData - The civic auth data from the root loader
|
|
28
|
+
*/
|
|
29
|
+
export declare function useAuthData(): CivicAuthData | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* Hook to access authentication state and user information (SSR pattern)
|
|
32
|
+
* This is the primary hook for React Router 7 applications using server-side rendering
|
|
33
|
+
* Enhanced with GlobalAuthManager for better state management
|
|
34
|
+
* @returns Authentication state and user information from server-side rendering
|
|
35
|
+
*/
|
|
36
|
+
export declare function useUser(): {
|
|
37
|
+
user: import("../types.js").BaseUser | null;
|
|
38
|
+
isLoggedIn: boolean;
|
|
39
|
+
signIn: (config?: SignInConfig) => Promise<AuthResult>;
|
|
40
|
+
signOut: () => Promise<void>;
|
|
41
|
+
config: AuthConfig;
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=useUser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useUser.d.ts","sourceRoot":"","sources":["../../src/react-router-7/useUser.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAMnE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAG9C,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,QAAQ,GAAG,UAAU,GAAG,SAAS,GAAG,YAAY,CAAC;IAC/D,sBAAsB,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC;CAC/C;AAGD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,UAAU,CAAC;CACpB;AAGD,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,aAAa,CAAC;CACtB;AAGD,MAAM,WAAW,QAAQ;IACvB,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,YAAY,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IACvD,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9C;AAED;;;GAGG;AACH,wBAAgB,WAAW,IAAI,aAAa,GAAG,SAAS,CAKvD;AAED;;;;;GAKG;AACH,wBAAgB,OAAO;;;sBAuCU,YAAY;;YA1EnC,UAAU;EAgHnB"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { useMatches, useRevalidator } from "react-router";
|
|
2
|
+
import {} from "@civic/auth/vanillajs";
|
|
3
|
+
import { GlobalAuthManager, } from "../reactjs/core/GlobalAuthManager.js";
|
|
4
|
+
import { useEffect, useMemo, useState } from "react";
|
|
5
|
+
/**
|
|
6
|
+
* Hook to access auth data from the root loader
|
|
7
|
+
* @returns CivicAuthData - The civic auth data from the root loader
|
|
8
|
+
*/
|
|
9
|
+
export function useAuthData() {
|
|
10
|
+
const matches = useMatches();
|
|
11
|
+
const rootMatch = matches.find((match) => match.id === "root");
|
|
12
|
+
const data = rootMatch?.data;
|
|
13
|
+
return data?.civic;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Hook to access authentication state and user information (SSR pattern)
|
|
17
|
+
* This is the primary hook for React Router 7 applications using server-side rendering
|
|
18
|
+
* Enhanced with GlobalAuthManager for better state management
|
|
19
|
+
* @returns Authentication state and user information from server-side rendering
|
|
20
|
+
*/
|
|
21
|
+
export function useUser() {
|
|
22
|
+
const authData = useAuthData();
|
|
23
|
+
const revalidator = useRevalidator();
|
|
24
|
+
const [authManager] = useState(() => GlobalAuthManager.getInstance());
|
|
25
|
+
if (!authData) {
|
|
26
|
+
throw new Error("Auth data not found. Make sure to use createRootAuthLoader in your root route.");
|
|
27
|
+
}
|
|
28
|
+
const initialConfig = useMemo(() => {
|
|
29
|
+
return {
|
|
30
|
+
clientId: authData.config.clientId,
|
|
31
|
+
loginUrl: authData.config.loginUrl,
|
|
32
|
+
displayMode: "iframe",
|
|
33
|
+
framework: "react-router",
|
|
34
|
+
config: {
|
|
35
|
+
oauthServer: authData.config.oauthServer,
|
|
36
|
+
},
|
|
37
|
+
onSignIn: (error) => {
|
|
38
|
+
if (!error) {
|
|
39
|
+
revalidator.revalidate();
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
onSignOut: () => {
|
|
43
|
+
revalidator.revalidate();
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
}, [revalidator, authData]);
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
const initialize = async () => {
|
|
49
|
+
await authManager.initialize(initialConfig);
|
|
50
|
+
};
|
|
51
|
+
initialize();
|
|
52
|
+
}, [authManager, initialConfig]);
|
|
53
|
+
// Create signIn function that leverages GlobalAuthManager
|
|
54
|
+
const signIn = async (config) => {
|
|
55
|
+
try {
|
|
56
|
+
if (config) {
|
|
57
|
+
await authManager.initialize({
|
|
58
|
+
...initialConfig,
|
|
59
|
+
...config,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
const result = await authManager.signIn();
|
|
63
|
+
// Return in AuthResult format for compatibility
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
console.error("Sign-in failed:", error);
|
|
68
|
+
throw error;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
// Create signOut function that leverages GlobalAuthManager
|
|
72
|
+
const signOut = async () => {
|
|
73
|
+
try {
|
|
74
|
+
await authManager.signOut();
|
|
75
|
+
// The onSignOut callback will handle revalidation
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
console.error("Sign-out failed:", error);
|
|
79
|
+
// Still try redirecting to logout URL as fallback
|
|
80
|
+
window.location.href = "/auth/logout";
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
// Ensure we have a valid user object or null
|
|
84
|
+
return {
|
|
85
|
+
...authData,
|
|
86
|
+
user: authData.user || null,
|
|
87
|
+
isLoggedIn: !!authData.user,
|
|
88
|
+
signIn,
|
|
89
|
+
signOut,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=useUser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useUser.js","sourceRoot":"","sources":["../../src/react-router-7/useUser.ts"],"names":[],"mappings":"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","sourcesContent":["import { useMatches, useRevalidator } from \"react-router\";\nimport { type AuthResult, type User } from \"@civic/auth/vanillajs\";\nimport {\n GlobalAuthManager,\n type GlobalAuthConfig,\n} from \"../reactjs/core/GlobalAuthManager.js\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport type { AuthConfig } from \"./config.js\";\n\n// Configuration type for signIn function\nexport interface SignInConfig {\n clientId?: string;\n baseUrl?: string;\n displayMode?: \"iframe\" | \"redirect\" | \"new_tab\" | \"custom_tab\";\n targetContainerElement?: HTMLElement | string;\n}\n\n// Type for the civic auth data structure from the root loader\nexport interface CivicAuthData {\n user: User | null;\n isLoggedIn: boolean;\n config: AuthConfig;\n}\n\n// Type for the complete root loader data structure\nexport interface RootLoaderData {\n civic: CivicAuthData;\n}\n\n// Type for the auth data that will be available in the root loader (SSR pattern)\nexport interface AuthData {\n isLoggedIn: boolean;\n user: User | null;\n loginUrl: string;\n logoutUrl: string;\n signIn: (config?: SignInConfig) => Promise<AuthResult>;\n signOut: (baseUrl?: string) => Promise<void>;\n}\n\n/**\n * Hook to access auth data from the root loader\n * @returns CivicAuthData - The civic auth data from the root loader\n */\nexport function useAuthData(): CivicAuthData | undefined {\n const matches = useMatches();\n const rootMatch = matches.find((match) => match.id === \"root\");\n const data = rootMatch?.data as RootLoaderData | undefined;\n return data?.civic;\n}\n\n/**\n * Hook to access authentication state and user information (SSR pattern)\n * This is the primary hook for React Router 7 applications using server-side rendering\n * Enhanced with GlobalAuthManager for better state management\n * @returns Authentication state and user information from server-side rendering\n */\nexport function useUser() {\n const authData = useAuthData();\n const revalidator = useRevalidator();\n const [authManager] = useState(() => GlobalAuthManager.getInstance());\n\n if (!authData) {\n throw new Error(\n \"Auth data not found. Make sure to use createRootAuthLoader in your root route.\",\n );\n }\n\n const initialConfig: GlobalAuthConfig = useMemo(() => {\n return {\n clientId: authData.config.clientId,\n loginUrl: authData.config.loginUrl,\n displayMode: \"iframe\",\n framework: \"react-router\",\n config: {\n oauthServer: authData.config.oauthServer,\n },\n onSignIn: (error) => {\n if (!error) {\n revalidator.revalidate();\n }\n },\n onSignOut: () => {\n revalidator.revalidate();\n },\n };\n }, [revalidator, authData]);\n\n useEffect(() => {\n const initialize = async () => {\n await authManager.initialize(initialConfig);\n };\n initialize();\n }, [authManager, initialConfig]);\n\n // Create signIn function that leverages GlobalAuthManager\n const signIn = async (config?: SignInConfig) => {\n try {\n if (config) {\n await authManager.initialize({\n ...initialConfig,\n ...config,\n });\n }\n const result = await authManager.signIn();\n\n // Return in AuthResult format for compatibility\n return result as AuthResult;\n } catch (error) {\n console.error(\"Sign-in failed:\", error);\n throw error;\n }\n };\n\n // Create signOut function that leverages GlobalAuthManager\n const signOut = async () => {\n try {\n await authManager.signOut();\n // The onSignOut callback will handle revalidation\n } catch (error) {\n console.error(\"Sign-out failed:\", error);\n // Still try redirecting to logout URL as fallback\n window.location.href = \"/auth/logout\";\n }\n };\n\n // Ensure we have a valid user object or null\n return {\n ...authData,\n user: authData.user || null,\n isLoggedIn: !!authData.user,\n signIn,\n signOut,\n };\n}\n"]}
|
|
@@ -30,8 +30,9 @@ import type { User, Session } from "../../vanillajs/index.js";
|
|
|
30
30
|
import type { DisplayMode, FrameworkType } from "../../types.js";
|
|
31
31
|
import type { LoggingConfig } from "../../vanillajs/auth/types/AuthTypes.js";
|
|
32
32
|
export interface GlobalAuthConfig {
|
|
33
|
-
clientId
|
|
33
|
+
clientId?: string;
|
|
34
34
|
redirectUrl?: string;
|
|
35
|
+
loginUrl?: string;
|
|
35
36
|
config?: {
|
|
36
37
|
oauthServer?: string;
|
|
37
38
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GlobalAuthManager.d.ts","sourceRoot":"","sources":["../../../src/reactjs/core/GlobalAuthManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAOH,OAAO,KAAK,EACV,IAAI,EACJ,OAAO,EAER,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AAQzE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"GlobalAuthManager.d.ts","sourceRoot":"","sources":["../../../src/reactjs/core/GlobalAuthManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -92,8 +92,8 @@ class GlobalAuthManager {
|
|
|
92
92
|
try {
|
|
93
93
|
this.events = new AuthenticationEvents();
|
|
94
94
|
this.setupEventListeners();
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
// Build base config common to both branches
|
|
96
|
+
const baseConfig = {
|
|
97
97
|
oauthServerBaseUrl: config.config?.oauthServer,
|
|
98
98
|
scopes: config.scopes || [
|
|
99
99
|
"openid",
|
|
@@ -114,6 +114,20 @@ class GlobalAuthManager {
|
|
|
114
114
|
},
|
|
115
115
|
framework: config.framework,
|
|
116
116
|
};
|
|
117
|
+
// Build auth config based on discriminated union requirements
|
|
118
|
+
const authConfig = config.loginUrl
|
|
119
|
+
? {
|
|
120
|
+
// Backend integration mode: loginUrl required, clientId optional
|
|
121
|
+
...baseConfig,
|
|
122
|
+
loginUrl: config.loginUrl,
|
|
123
|
+
clientId: config.clientId,
|
|
124
|
+
}
|
|
125
|
+
: {
|
|
126
|
+
// Standard OAuth mode: clientId required, loginUrl optional
|
|
127
|
+
...baseConfig,
|
|
128
|
+
clientId: config.clientId,
|
|
129
|
+
loginUrl: config.loginUrl,
|
|
130
|
+
};
|
|
117
131
|
// Only add redirectUrl if provided
|
|
118
132
|
if (config.redirectUrl) {
|
|
119
133
|
authConfig.redirectUrl = config.redirectUrl;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GlobalAuthManager.js","sourceRoot":"","sources":["../../../src/reactjs/core/GlobalAuthManager.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * GlobalAuthManager - Singleton Authentication State Manager\n *\n * This module provides a global singleton that manages authentication state across a React application\n * without requiring React Context providers or prop drilling. It acts as a centralized authentication\n * manager that wraps the CivicAuth vanilla JavaScript library and provides a React-friendly interface.\n *\n * Key Features:\n * - Singleton pattern ensures single auth instance across the entire app\n * - Eliminates need for React Context providers and reduces bundle size\n * - Manages authentication state (user, session, loading, errors)\n * - Handles sign-in/sign-out flows with event-driven updates\n * - Provides idempotent initialization (safe to call multiple times)\n * - Supports multiple React hooks subscribing to the same auth state\n * - Automatic session refresh and user data synchronization\n *\n * Usage:\n * - Initialize once in your app with authentication configuration\n * - Use React hooks (useCivicAuth, useAuth, etc.) to access auth state\n * - The manager handles all underlying CivicAuth SDK interactions\n * - State updates are automatically propagated to all subscribed components\n *\n * This design pattern is particularly useful for:\n * - Large applications with many components needing auth state\n * - Avoiding provider wrapper hell in React component trees\n * - Ensuring consistent auth state across disconnected component hierarchies\n * - Server-side rendering scenarios where providers might be problematic\n */\n\nimport {\n CivicAuth,\n AuthenticationEvents,\n AuthEvent,\n} from \"../../vanillajs/index.js\";\nimport type {\n User,\n Session,\n CivicAuthClientConfig,\n} from \"../../vanillajs/index.js\";\nimport type { DisplayMode, FrameworkType } from \"../../types.js\";\nimport type { LoggingConfig } from \"@/vanillajs/auth/types/AuthTypes.js\";\nimport { DEFAULT_AUTH_PROCESS_TIMEOUT } from \"../../vanillajs/auth/types/AuthTypes.js\";\n\n// Event payload interfaces\ninterface SignInErrorEvent {\n detail: string;\n}\n\nexport interface GlobalAuthConfig {\n clientId: string;\n redirectUrl?: string;\n config?: {\n oauthServer?: string;\n };\n displayMode?: DisplayMode;\n iframeMode?: \"modal\" | \"embedded\";\n nonce?: string;\n logoutRedirectUrl?: string;\n scopes?: string[];\n authProcessTimeout?: number;\n onSignIn?: (error?: Error) => void;\n onSignOut?: () => void;\n logging?: LoggingConfig;\n preloadIframe?: boolean;\n autoRedirect?: boolean;\n /** Framework being used (for analytics) - internal use only */\n framework?: FrameworkType;\n}\n\nexport type AuthStatus =\n | \"authenticated\"\n | \"unauthenticated\"\n | \"authenticating\"\n | \"error\"\n | \"signing_out\";\n\nexport interface GlobalAuthState {\n user: User | null;\n session: Session | null;\n isLoading: boolean;\n authStatus: AuthStatus;\n error: Error | null;\n displayMode?: DisplayMode;\n isPreloaded?: boolean;\n}\n\ntype StateListener = (state: GlobalAuthState) => void;\n\n/**\n * Global singleton that manages CivicAuth instance for React hooks\n * Eliminates the need for React providers\n */\nclass GlobalAuthManager {\n private static instance: GlobalAuthManager | null = null;\n private auth: CivicAuth | null = null;\n private events: AuthenticationEvents | null = null;\n private config: GlobalAuthConfig | null = null;\n private listeners = new Set<StateListener>();\n private callbacks: {\n onSignIn?: (error?: Error) => void;\n onSignOut?: () => void;\n } = {};\n private initializationPromise: Promise<void> | null = null;\n\n private state: GlobalAuthState = {\n user: null,\n session: null,\n isLoading: false,\n authStatus: \"unauthenticated\",\n error: null,\n displayMode: undefined,\n };\n\n private constructor() {\n // Private constructor for singleton\n }\n\n static getInstance(): GlobalAuthManager {\n if (!GlobalAuthManager.instance) {\n GlobalAuthManager.instance = new GlobalAuthManager();\n }\n return GlobalAuthManager.instance;\n }\n\n /**\n * Initialize auth with config (idempotent)\n * Returns the same promise for concurrent calls with same config\n */\n async initialize(config: GlobalAuthConfig): Promise<void> {\n // If we have a promise and same config, return existing promise\n if (\n this.initializationPromise &&\n this.config &&\n this.isSameConfig(config)\n ) {\n return this.initializationPromise;\n }\n\n // If different config, reset everything\n if (this.config && !this.isSameConfig(config)) {\n this.initializationPromise = null;\n await this.cleanup();\n }\n\n // Create new initialization promise if needed\n if (!this.initializationPromise) {\n this.initializationPromise = this._doInitialize(config);\n }\n\n return this.initializationPromise;\n }\n\n /**\n * Private method that does the actual initialization work\n */\n private async _doInitialize(config: GlobalAuthConfig): Promise<void> {\n this.config = config;\n this.callbacks = {\n onSignIn: config.onSignIn,\n onSignOut: config.onSignOut,\n };\n this.setState({ isLoading: true, error: null });\n\n try {\n this.events = new AuthenticationEvents();\n this.setupEventListeners();\n\n const authConfig: CivicAuthClientConfig = {\n clientId: config.clientId,\n oauthServerBaseUrl: config.config?.oauthServer,\n scopes: config.scopes || [\n \"openid\",\n \"profile\",\n \"email\",\n \"offline_access\",\n ],\n displayMode: config.displayMode || \"iframe\",\n iframeDisplayMode: config.iframeMode || \"modal\",\n nonce: config.nonce,\n authProcessTimeout:\n config.authProcessTimeout || DEFAULT_AUTH_PROCESS_TIMEOUT,\n preloadIframe: config.preloadIframe,\n autoRedirect: config.autoRedirect,\n events: this.events,\n logging: {\n enabled: true,\n level: \"debug\" as const,\n },\n framework: config.framework,\n };\n\n // Only add redirectUrl if provided\n if (config.redirectUrl) {\n authConfig.redirectUrl = config.redirectUrl;\n }\n\n // Only add logoutRedirectUrl if provided\n if (config.logoutRedirectUrl) {\n authConfig.logoutRedirectUrl = config.logoutRedirectUrl;\n }\n\n this.auth = await CivicAuth.create(authConfig);\n\n // Check initial auth state\n const isAuthenticated = await this.auth.isAuthenticated();\n if (isAuthenticated) {\n await this.refreshUserAndSession();\n this.setState({ authStatus: \"authenticated\" });\n } else {\n this.setState({ authStatus: \"unauthenticated\" });\n\n // Note: Preloading is now handled automatically by CivicAuth based on config.preloadIframe\n }\n\n this.setState({\n isLoading: false,\n displayMode: config.displayMode,\n });\n } catch (error) {\n // Reset promise on error so it can be retried\n this.initializationPromise = null;\n\n const authError =\n error instanceof Error\n ? error\n : new Error(\"Auth initialization failed\");\n this.setState({\n error: authError,\n authStatus: \"error\",\n isLoading: false,\n });\n throw authError;\n }\n }\n\n /**\n * Subscribe to state changes\n */\n subscribe(listener: StateListener): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n /**\n * Get current state\n */\n getState(): GlobalAuthState {\n return { ...this.state };\n }\n\n /**\n * Sign in\n */\n async signIn(): Promise<{ user: User }> {\n if (!this.auth) {\n throw new Error(\"Auth not initialized\");\n }\n\n const { user } = await this.auth.startAuthentication();\n await this.refreshUserAndSession();\n\n // Ensure we have a user to return\n if (!user) {\n throw new Error(\"Authentication succeeded but no user was returned\");\n }\n\n // Return the user object\n return { user };\n }\n\n /**\n * Sign out\n */\n async signOut(): Promise<void> {\n if (!this.auth) {\n throw new Error(\"Auth not initialized\");\n }\n\n await this.auth.logout();\n this.setState({\n user: null,\n session: null,\n authStatus: \"unauthenticated\",\n });\n }\n\n /**\n * Check if authentication is preloaded and ready for instant sign-in\n * @returns True if an iframe is preloaded and ready\n */\n isAuthenticationPreloaded(): boolean {\n return this.auth?.isAuthenticationPreloaded() ?? false;\n }\n\n /**\n * Enable or disable iframe preloading\n */\n setPreloadEnabled(enabled: boolean): void {\n if (!this.auth) {\n throw new Error(\"Auth not initialized\");\n }\n this.auth.setPreloadEnabled(enabled);\n }\n\n /**\n * Check if iframe preloading is enabled\n */\n getPreloadEnabled(): boolean {\n return this.auth?.getPreloadEnabled() ?? true;\n }\n\n /**\n * Check if config is the same (for idempotent initialization)\n */\n private isSameConfig(newConfig: GlobalAuthConfig): boolean {\n if (!this.config) return false;\n return (\n this.config.clientId === newConfig.clientId &&\n this.config.config?.oauthServer === newConfig.config?.oauthServer &&\n this.config.displayMode === newConfig.displayMode &&\n this.config.nonce === newConfig.nonce &&\n this.config.preloadIframe === newConfig.preloadIframe &&\n this.config.autoRedirect === newConfig.autoRedirect\n );\n }\n\n /**\n * Setup event listeners for auth state changes\n */\n private setupEventListeners(): void {\n if (!this.events) return;\n\n this.events.on(AuthEvent.SIGN_IN_STARTED, () => {\n this.setState({\n isLoading: true,\n authStatus: \"authenticating\",\n error: null,\n });\n });\n\n this.events.on(AuthEvent.SIGN_IN_COMPLETE, () => {\n this.setState({\n isLoading: false,\n authStatus: \"authenticated\",\n error: null,\n });\n this.refreshUserAndSession();\n this.callbacks.onSignIn?.();\n });\n\n this.events.on(AuthEvent.SIGN_IN_ERROR, (event?: SignInErrorEvent) => {\n const errorDetail = event?.detail || \"Authentication failed\";\n const authError = new Error(errorDetail);\n this.setState({\n isLoading: false,\n authStatus: \"error\",\n error: authError,\n });\n this.callbacks.onSignIn?.(authError);\n });\n\n this.events.on(AuthEvent.SIGN_OUT_STARTED, () => {\n this.setState({\n isLoading: true,\n authStatus: \"signing_out\",\n error: null,\n });\n });\n\n this.events.on(AuthEvent.SIGN_OUT_COMPLETE, () => {\n this.setState({\n isLoading: false,\n authStatus: \"unauthenticated\",\n user: null,\n session: null,\n error: null,\n });\n this.callbacks.onSignOut?.();\n });\n\n this.events.on(AuthEvent.USER_SESSION_CHANGED, () => {\n this.refreshUserAndSession();\n });\n }\n\n /**\n * Refresh user and session data\n */\n private async refreshUserAndSession(): Promise<void> {\n if (!this.auth) return;\n\n try {\n const [session, user] = await Promise.all([\n this.auth.getCurrentSession(),\n this.auth.getCurrentUser(),\n ]);\n\n this.setState({ session, user });\n } catch (error) {\n const sessionError =\n error instanceof Error ? error : new Error(\"Failed to get session\");\n this.setState({ error: sessionError });\n }\n }\n\n /**\n * Update state and notify listeners\n */\n private setState(updates: Partial<GlobalAuthState>): void {\n this.state = { ...this.state, ...updates };\n this.listeners.forEach((listener) => listener(this.state));\n }\n\n /**\n * Cleanup auth instance\n */\n private async cleanup(): Promise<void> {\n if (this.auth) {\n await this.auth.destroy();\n this.auth = null;\n }\n this.events = null;\n this.config = null;\n this.initializationPromise = null; // Reset promise for clean re-initialization\n }\n}\n\nexport { GlobalAuthManager };\n"]}
|
|
1
|
+
{"version":3,"file":"GlobalAuthManager.js","sourceRoot":"","sources":["../../../src/reactjs/core/GlobalAuthManager.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * GlobalAuthManager - Singleton Authentication State Manager\n *\n * This module provides a global singleton that manages authentication state across a React application\n * without requiring React Context providers or prop drilling. It acts as a centralized authentication\n * manager that wraps the CivicAuth vanilla JavaScript library and provides a React-friendly interface.\n *\n * Key Features:\n * - Singleton pattern ensures single auth instance across the entire app\n * - Eliminates need for React Context providers and reduces bundle size\n * - Manages authentication state (user, session, loading, errors)\n * - Handles sign-in/sign-out flows with event-driven updates\n * - Provides idempotent initialization (safe to call multiple times)\n * - Supports multiple React hooks subscribing to the same auth state\n * - Automatic session refresh and user data synchronization\n *\n * Usage:\n * - Initialize once in your app with authentication configuration\n * - Use React hooks (useCivicAuth, useAuth, etc.) to access auth state\n * - The manager handles all underlying CivicAuth SDK interactions\n * - State updates are automatically propagated to all subscribed components\n *\n * This design pattern is particularly useful for:\n * - Large applications with many components needing auth state\n * - Avoiding provider wrapper hell in React component trees\n * - Ensuring consistent auth state across disconnected component hierarchies\n * - Server-side rendering scenarios where providers might be problematic\n */\n\nimport {\n CivicAuth,\n AuthenticationEvents,\n AuthEvent,\n} from \"../../vanillajs/index.js\";\nimport type {\n User,\n Session,\n CivicAuthClientConfig,\n} from \"../../vanillajs/index.js\";\nimport type { DisplayMode, FrameworkType } from \"../../types.js\";\nimport type { LoggingConfig } from \"@/vanillajs/auth/types/AuthTypes.js\";\nimport { DEFAULT_AUTH_PROCESS_TIMEOUT } from \"../../vanillajs/auth/types/AuthTypes.js\";\n\n// Event payload interfaces\ninterface SignInErrorEvent {\n detail: string;\n}\n\nexport interface GlobalAuthConfig {\n clientId?: string;\n redirectUrl?: string;\n loginUrl?: string;\n config?: {\n oauthServer?: string;\n };\n displayMode?: DisplayMode;\n iframeMode?: \"modal\" | \"embedded\";\n nonce?: string;\n logoutRedirectUrl?: string;\n scopes?: string[];\n authProcessTimeout?: number;\n onSignIn?: (error?: Error) => void;\n onSignOut?: () => void;\n logging?: LoggingConfig;\n preloadIframe?: boolean;\n autoRedirect?: boolean;\n /** Framework being used (for analytics) - internal use only */\n framework?: FrameworkType;\n}\n\nexport type AuthStatus =\n | \"authenticated\"\n | \"unauthenticated\"\n | \"authenticating\"\n | \"error\"\n | \"signing_out\";\n\nexport interface GlobalAuthState {\n user: User | null;\n session: Session | null;\n isLoading: boolean;\n authStatus: AuthStatus;\n error: Error | null;\n displayMode?: DisplayMode;\n isPreloaded?: boolean;\n}\n\ntype StateListener = (state: GlobalAuthState) => void;\n\n/**\n * Global singleton that manages CivicAuth instance for React hooks\n * Eliminates the need for React providers\n */\nclass GlobalAuthManager {\n private static instance: GlobalAuthManager | null = null;\n private auth: CivicAuth | null = null;\n private events: AuthenticationEvents | null = null;\n private config: GlobalAuthConfig | null = null;\n private listeners = new Set<StateListener>();\n private callbacks: {\n onSignIn?: (error?: Error) => void;\n onSignOut?: () => void;\n } = {};\n private initializationPromise: Promise<void> | null = null;\n\n private state: GlobalAuthState = {\n user: null,\n session: null,\n isLoading: false,\n authStatus: \"unauthenticated\",\n error: null,\n displayMode: undefined,\n };\n\n private constructor() {\n // Private constructor for singleton\n }\n\n static getInstance(): GlobalAuthManager {\n if (!GlobalAuthManager.instance) {\n GlobalAuthManager.instance = new GlobalAuthManager();\n }\n return GlobalAuthManager.instance;\n }\n\n /**\n * Initialize auth with config (idempotent)\n * Returns the same promise for concurrent calls with same config\n */\n async initialize(config: GlobalAuthConfig): Promise<void> {\n // If we have a promise and same config, return existing promise\n if (\n this.initializationPromise &&\n this.config &&\n this.isSameConfig(config)\n ) {\n return this.initializationPromise;\n }\n\n // If different config, reset everything\n if (this.config && !this.isSameConfig(config)) {\n this.initializationPromise = null;\n await this.cleanup();\n }\n\n // Create new initialization promise if needed\n if (!this.initializationPromise) {\n this.initializationPromise = this._doInitialize(config);\n }\n\n return this.initializationPromise;\n }\n\n /**\n * Private method that does the actual initialization work\n */\n private async _doInitialize(config: GlobalAuthConfig): Promise<void> {\n this.config = config;\n this.callbacks = {\n onSignIn: config.onSignIn,\n onSignOut: config.onSignOut,\n };\n this.setState({ isLoading: true, error: null });\n\n try {\n this.events = new AuthenticationEvents();\n this.setupEventListeners();\n\n // Build base config common to both branches\n const baseConfig = {\n oauthServerBaseUrl: config.config?.oauthServer,\n scopes: config.scopes || [\n \"openid\",\n \"profile\",\n \"email\",\n \"offline_access\",\n ],\n displayMode: config.displayMode || \"iframe\",\n iframeDisplayMode: config.iframeMode || \"modal\",\n nonce: config.nonce,\n authProcessTimeout:\n config.authProcessTimeout || DEFAULT_AUTH_PROCESS_TIMEOUT,\n preloadIframe: config.preloadIframe,\n autoRedirect: config.autoRedirect,\n events: this.events,\n logging: {\n enabled: true,\n level: \"debug\" as const,\n },\n framework: config.framework,\n };\n\n // Build auth config based on discriminated union requirements\n const authConfig: CivicAuthClientConfig = config.loginUrl\n ? {\n // Backend integration mode: loginUrl required, clientId optional\n ...baseConfig,\n loginUrl: config.loginUrl,\n clientId: config.clientId,\n }\n : {\n // Standard OAuth mode: clientId required, loginUrl optional\n ...baseConfig,\n clientId: config.clientId!,\n loginUrl: config.loginUrl,\n };\n\n // Only add redirectUrl if provided\n if (config.redirectUrl) {\n authConfig.redirectUrl = config.redirectUrl;\n }\n\n // Only add logoutRedirectUrl if provided\n if (config.logoutRedirectUrl) {\n authConfig.logoutRedirectUrl = config.logoutRedirectUrl;\n }\n\n this.auth = await CivicAuth.create(authConfig);\n\n // Check initial auth state\n const isAuthenticated = await this.auth.isAuthenticated();\n if (isAuthenticated) {\n await this.refreshUserAndSession();\n this.setState({ authStatus: \"authenticated\" });\n } else {\n this.setState({ authStatus: \"unauthenticated\" });\n\n // Note: Preloading is now handled automatically by CivicAuth based on config.preloadIframe\n }\n\n this.setState({\n isLoading: false,\n displayMode: config.displayMode,\n });\n } catch (error) {\n // Reset promise on error so it can be retried\n this.initializationPromise = null;\n\n const authError =\n error instanceof Error\n ? error\n : new Error(\"Auth initialization failed\");\n this.setState({\n error: authError,\n authStatus: \"error\",\n isLoading: false,\n });\n throw authError;\n }\n }\n\n /**\n * Subscribe to state changes\n */\n subscribe(listener: StateListener): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n /**\n * Get current state\n */\n getState(): GlobalAuthState {\n return { ...this.state };\n }\n\n /**\n * Sign in\n */\n async signIn(): Promise<{ user: User }> {\n if (!this.auth) {\n throw new Error(\"Auth not initialized\");\n }\n\n const { user } = await this.auth.startAuthentication();\n await this.refreshUserAndSession();\n\n // Ensure we have a user to return\n if (!user) {\n throw new Error(\"Authentication succeeded but no user was returned\");\n }\n\n // Return the user object\n return { user };\n }\n\n /**\n * Sign out\n */\n async signOut(): Promise<void> {\n if (!this.auth) {\n throw new Error(\"Auth not initialized\");\n }\n\n await this.auth.logout();\n this.setState({\n user: null,\n session: null,\n authStatus: \"unauthenticated\",\n });\n }\n\n /**\n * Check if authentication is preloaded and ready for instant sign-in\n * @returns True if an iframe is preloaded and ready\n */\n isAuthenticationPreloaded(): boolean {\n return this.auth?.isAuthenticationPreloaded() ?? false;\n }\n\n /**\n * Enable or disable iframe preloading\n */\n setPreloadEnabled(enabled: boolean): void {\n if (!this.auth) {\n throw new Error(\"Auth not initialized\");\n }\n this.auth.setPreloadEnabled(enabled);\n }\n\n /**\n * Check if iframe preloading is enabled\n */\n getPreloadEnabled(): boolean {\n return this.auth?.getPreloadEnabled() ?? true;\n }\n\n /**\n * Check if config is the same (for idempotent initialization)\n */\n private isSameConfig(newConfig: GlobalAuthConfig): boolean {\n if (!this.config) return false;\n return (\n this.config.clientId === newConfig.clientId &&\n this.config.config?.oauthServer === newConfig.config?.oauthServer &&\n this.config.displayMode === newConfig.displayMode &&\n this.config.nonce === newConfig.nonce &&\n this.config.preloadIframe === newConfig.preloadIframe &&\n this.config.autoRedirect === newConfig.autoRedirect\n );\n }\n\n /**\n * Setup event listeners for auth state changes\n */\n private setupEventListeners(): void {\n if (!this.events) return;\n\n this.events.on(AuthEvent.SIGN_IN_STARTED, () => {\n this.setState({\n isLoading: true,\n authStatus: \"authenticating\",\n error: null,\n });\n });\n\n this.events.on(AuthEvent.SIGN_IN_COMPLETE, () => {\n this.setState({\n isLoading: false,\n authStatus: \"authenticated\",\n error: null,\n });\n this.refreshUserAndSession();\n this.callbacks.onSignIn?.();\n });\n\n this.events.on(AuthEvent.SIGN_IN_ERROR, (event?: SignInErrorEvent) => {\n const errorDetail = event?.detail || \"Authentication failed\";\n const authError = new Error(errorDetail);\n this.setState({\n isLoading: false,\n authStatus: \"error\",\n error: authError,\n });\n this.callbacks.onSignIn?.(authError);\n });\n\n this.events.on(AuthEvent.SIGN_OUT_STARTED, () => {\n this.setState({\n isLoading: true,\n authStatus: \"signing_out\",\n error: null,\n });\n });\n\n this.events.on(AuthEvent.SIGN_OUT_COMPLETE, () => {\n this.setState({\n isLoading: false,\n authStatus: \"unauthenticated\",\n user: null,\n session: null,\n error: null,\n });\n this.callbacks.onSignOut?.();\n });\n\n this.events.on(AuthEvent.USER_SESSION_CHANGED, () => {\n this.refreshUserAndSession();\n });\n }\n\n /**\n * Refresh user and session data\n */\n private async refreshUserAndSession(): Promise<void> {\n if (!this.auth) return;\n\n try {\n const [session, user] = await Promise.all([\n this.auth.getCurrentSession(),\n this.auth.getCurrentUser(),\n ]);\n\n this.setState({ session, user });\n } catch (error) {\n const sessionError =\n error instanceof Error ? error : new Error(\"Failed to get session\");\n this.setState({ error: sessionError });\n }\n }\n\n /**\n * Update state and notify listeners\n */\n private setState(updates: Partial<GlobalAuthState>): void {\n this.state = { ...this.state, ...updates };\n this.listeners.forEach((listener) => listener(this.state));\n }\n\n /**\n * Cleanup auth instance\n */\n private async cleanup(): Promise<void> {\n if (this.auth) {\n await this.auth.destroy();\n this.auth = null;\n }\n this.events = null;\n this.config = null;\n this.initializationPromise = null; // Reset promise for clean re-initialization\n }\n}\n\nexport { GlobalAuthManager };\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;AAUrD,OAAO,KAAK,EAAE,sBAAsB,EAAgB,MAAM,qBAAqB,CAAC;AAOhF,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;IA+DvB;;;OAGG;IACG,uBAAuB,CAAC,WAAW,UAAO,GAAG,OAAO,CAAC,WAAW,CAAC;IAmDvE,IAAI,WAAW,IAAI,MAAM,CAExB;IAEK,IAAI,IAAI,OAAO,CAAC,IAAI,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;AAUrD,OAAO,KAAK,EAAE,sBAAsB,EAAgB,MAAM,qBAAqB,CAAC;AAOhF,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;IA+DvB;;;OAGG;IACG,uBAAuB,CAAC,WAAW,UAAO,GAAG,OAAO,CAAC,WAAW,CAAC;IAmDvE,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;IA4B3B,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,WAAW,EACpB,iBAAiB,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,GACrC,OAAO,CAAC,sBAAsB,CAAC;CAUnC"}
|
|
@@ -125,6 +125,10 @@ export class ServerAuthenticationResolver {
|
|
|
125
125
|
return this.authConfig.oauthServer || DEFAULT_AUTH_SERVER;
|
|
126
126
|
}
|
|
127
127
|
async init() {
|
|
128
|
+
// Ensure clientId is present for OAuth operations
|
|
129
|
+
if (!this.authConfig.clientId) {
|
|
130
|
+
throw new Error("clientId is required for OAuth server operations");
|
|
131
|
+
}
|
|
128
132
|
// resolve oauth config
|
|
129
133
|
this.endpoints = await getEndpointsWithOverrides(this.oauthServer, this.endpointOverrides);
|
|
130
134
|
this.oauth2client = new OAuth2Client(this.authConfig.clientId, this.endpoints.auth, this.endpoints.token, {
|
|
@@ -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\";\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 // Store the refreshed tokens\n await storeServerTokens(this.storage, tokenResponseBody);\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 };\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(autoRefresh = true): 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 // 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 (autoRefresh) {\n const refreshedSessionData = await this.tryRefreshTokens(sessionData);\n if (refreshedSessionData.authenticated) {\n return refreshedSessionData;\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, autoRefresh });\n if (autoRefresh) {\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 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 // 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 // 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: AuthStorage,\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 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\";\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 // Store the refreshed tokens\n await storeServerTokens(this.storage, tokenResponseBody);\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 };\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(autoRefresh = true): 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 // 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 (autoRefresh) {\n const refreshedSessionData = await this.tryRefreshTokens(sessionData);\n if (refreshedSessionData.authenticated) {\n return refreshedSessionData;\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, autoRefresh });\n if (autoRefresh) {\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 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 // 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: AuthStorage,\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"]}
|
package/dist/server/config.d.ts
CHANGED
|
@@ -12,7 +12,6 @@ export interface BackendEndpoints {
|
|
|
12
12
|
user?: string;
|
|
13
13
|
}
|
|
14
14
|
export type AuthConfig = {
|
|
15
|
-
clientId: string;
|
|
16
15
|
clientSecret?: string;
|
|
17
16
|
pkce?: boolean;
|
|
18
17
|
redirectUrl: string;
|
|
@@ -21,7 +20,6 @@ export type AuthConfig = {
|
|
|
21
20
|
refreshUrl?: string;
|
|
22
21
|
endpointOverrides?: Partial<Endpoints> | undefined;
|
|
23
22
|
postLogoutRedirectUrl?: string;
|
|
24
|
-
loginUrl?: string;
|
|
25
23
|
/**
|
|
26
24
|
* Custom backend endpoints configuration for backend integration
|
|
27
25
|
* Only used when loginUrl is provided. Allows overriding default endpoints.
|
|
@@ -56,5 +54,15 @@ export type AuthConfig = {
|
|
|
56
54
|
* Useful for testing environments like Cypress where iframe detection may interfere with expected redirects.
|
|
57
55
|
*/
|
|
58
56
|
disableIframeDetection?: boolean;
|
|
59
|
-
}
|
|
57
|
+
} & ({
|
|
58
|
+
/** OAuth client ID - required for standard OAuth flow */
|
|
59
|
+
clientId: string;
|
|
60
|
+
/** Custom login URL for backend integration - optional */
|
|
61
|
+
loginUrl?: string;
|
|
62
|
+
} | {
|
|
63
|
+
/** OAuth client ID - optional when using backend integration */
|
|
64
|
+
clientId?: string;
|
|
65
|
+
/** Custom login URL for backend integration - required when clientId is not provided */
|
|
66
|
+
loginUrl: string;
|
|
67
|
+
});
|
|
60
68
|
//# sourceMappingURL=config.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/server/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,4DAA4D;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oDAAoD;IACpD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/server/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,4DAA4D;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oDAAoD;IACpD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,SAAS,CAAC;IACnD,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;OAEG;IACH,IAAI,CAAC,EAAE;QACL,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC;QACrC,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB,oBAAoB,CAAC,EAAE,MAAM,CAAC;QAC9B,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;QAC1B,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;KAC3B,CAAC;IACF;;OAEG;IACH,MAAM,CAAC,EAAE;QACP,OAAO,CAAC,EAAE,OAAO,CAAC;KACnB,CAAC;IACF;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC,GAAG,CACA;IACE,yDAAyD;IACzD,QAAQ,EAAE,MAAM,CAAC;IACjB,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GACD;IACE,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wFAAwF;IACxF,QAAQ,EAAE,MAAM,CAAC;CAClB,CACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/server/config.ts"],"names":[],"mappings":"","sourcesContent":["import type { Endpoints } from \"@/types.ts\";\n\n/**\n * Configuration for backend authentication endpoints\n * Allows customization of API endpoints when using backend integration (loginUrl)\n */\nexport interface BackendEndpoints {\n /** Endpoint for token refresh (default: \"/auth/refresh\") */\n refresh?: string;\n /** Endpoint for logout (default: \"/auth/logout\") */\n logout?: string;\n /** Endpoint for user info and session validation (default: \"/auth/user\") */\n user?: string;\n}\n\nexport type AuthConfig = {\n
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/server/config.ts"],"names":[],"mappings":"","sourcesContent":["import type { Endpoints } from \"@/types.ts\";\n\n/**\n * Configuration for backend authentication endpoints\n * Allows customization of API endpoints when using backend integration (loginUrl)\n */\nexport interface BackendEndpoints {\n /** Endpoint for token refresh (default: \"/auth/refresh\") */\n refresh?: string;\n /** Endpoint for logout (default: \"/auth/logout\") */\n logout?: string;\n /** Endpoint for user info and session validation (default: \"/auth/user\") */\n user?: string;\n}\n\nexport type AuthConfig = {\n clientSecret?: string; // Optional client secret for confidential clients\n pkce?: boolean; // Optional PKCE flag, defaults to true if not specified\n redirectUrl: string;\n oauthServer?: string;\n challengeUrl?: string;\n refreshUrl?: string;\n endpointOverrides?: Partial<Endpoints> | undefined;\n postLogoutRedirectUrl?: string;\n /**\n * Custom backend endpoints configuration for backend integration\n * Only used when loginUrl is provided. Allows overriding default endpoints.\n */\n backendEndpoints?: BackendEndpoints;\n /**\n * Optional URL to redirect frontend clients back to after successful authentication.\n * When provided, the backend will automatically redirect SPA clients to this URL\n * instead of traditional server-side redirects. Useful for backend + frontend integration.\n * Example: \"http://localhost:5173\" or \"https://your-spa.com\"\n */\n loginSuccessUrl?: string;\n /**\n * Optional CORS configuration for authentication endpoints\n */\n cors?: {\n origin?: string | string[] | boolean;\n credentials?: boolean;\n optionsSuccessStatus?: number;\n allowedHeaders?: string[];\n exposedHeaders?: string[];\n };\n /**\n * Optional logger configuration for authentication middleware\n */\n logger?: {\n enabled?: boolean; // Defaults to true if not specified\n };\n /**\n * Optional flag to disable iframe detection in handleCallback.\n * When true, callbacks will always attempt to redirect instead of returning HTML content for iframes.\n * Useful for testing environments like Cypress where iframe detection may interfere with expected redirects.\n */\n disableIframeDetection?: boolean;\n} & (\n | {\n /** OAuth client ID - required for standard OAuth flow */\n clientId: string;\n /** Custom login URL for backend integration - optional */\n loginUrl?: string;\n }\n | {\n /** OAuth client ID - optional when using backend integration */\n clientId?: string;\n /** Custom login URL for backend integration - required when clientId is not provided */\n loginUrl: string;\n }\n);\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/server/login.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,qBAAqB,EACrB,aAAa,EACd,MAAM,YAAY,CAAC;AAKpB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGrD;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;GAMG;AACH,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,qBAAqB,CAAC,CAWhC;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAEvE;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,aAAa,CAAC,GAClD,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,GAAG,MAAM,GAAG,cAAc,CAAC,CAAC,GAAG;IACnE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,EACH,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/server/login.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,qBAAqB,EACrB,aAAa,EACd,MAAM,YAAY,CAAC;AAKpB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGrD;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;GAMG;AACH,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,qBAAqB,CAAC,CAWhC;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAEvE;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,aAAa,CAAC,GAClD,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,GAAG,MAAM,GAAG,cAAc,CAAC,CAAC,GAAG;IACnE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,EACH,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,GAAG,CAAC,CA4Cd"}
|
package/dist/server/login.js
CHANGED
|
@@ -44,8 +44,13 @@ export async function buildLoginUrl(config, storage) {
|
|
|
44
44
|
const usePkce = config.pkce !== false;
|
|
45
45
|
// Only create PKCE producer if we're using PKCE and have storage
|
|
46
46
|
const pkceProducer = usePkce && storage ? new GenericPublicClientPKCEProducer(storage) : null;
|
|
47
|
+
// Ensure clientId is present for OAuth operations
|
|
48
|
+
if (!config.clientId) {
|
|
49
|
+
throw new Error("clientId is required for OAuth login operations");
|
|
50
|
+
}
|
|
47
51
|
const authInitiator = new GenericAuthenticationInitiator({
|
|
48
52
|
...config,
|
|
53
|
+
clientId: config.clientId,
|
|
49
54
|
state,
|
|
50
55
|
scopes,
|
|
51
56
|
oauthServer: config.oauthServer ?? DEFAULT_AUTH_SERVER,
|
package/dist/server/login.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/server/login.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,EAAE,8BAA8B,EAAE,MAAM,qCAAqC,CAAC;AACrF,OAAO,EAAE,+BAA+B,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,EAAE,4BAA4B,EAAE,MAAM,0CAA0C,CAAC;AAExF,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAY/C;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,IAAY,EACZ,KAAa,EACb,OAAoB,EACpB,MAAkB;IAElB,MAAM,kBAAkB,GAAG,MAAM,4BAA4B,CAAC,KAAK,CACjE;QACE,GAAG,MAAM;QACT,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,mBAAmB;KACvD,EACD,OAAO,EACP,MAAM,CAAC,iBAAiB,CACzB,CAAC;IAEF,OAAO,kBAAkB,CAAC,aAAa,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAAoB;IACnD,OAAO,CAAC,CAAC,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAOG,EACH,OAAqB;IAErB,oFAAoF;IACpF,IAAI,KAAa,CAAC;IAClB,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,sEAAsE;QACtE,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;IACvB,CAAC;SAAM,IAAI,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACjD,wDAAwD;QACxD,KAAK,GAAG,aAAa,CAAC;YACpB,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,UAAU,EAAE,MAAM,CAAC,UAAU;SAC9B,CAAC,CAAC;IACL,CAAC;SAAM,CAAC;QACN,oCAAoC;QACpC,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAClD,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,cAAc,CAAC;IAE/C,mDAAmD;IACnD,8DAA8D;IAC9D,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,KAAK,KAAK,CAAC;IAEtC,iEAAiE;IACjE,MAAM,YAAY,GAChB,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,IAAI,+BAA+B,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAE3E,MAAM,aAAa,GAAG,IAAI,8BAA8B,CAAC;QACvD,GAAG,MAAM;QACT,KAAK;QACL,MAAM;QACN,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,mBAAmB;QACtD,mGAAmG;QACnG,kEAAkE;QAClE,YAAY,EAAE,YAAY,IAAI,SAAS;KACxC,CAAC,CAAC;IAEH,OAAO,aAAa,CAAC,MAAM,EAAE,CAAC;AAChC,CAAC","sourcesContent":["import type {\n AuthStorage,\n OIDCTokenResponseBody,\n FrameworkType,\n} from \"@/types.js\";\nimport { DEFAULT_AUTH_SERVER, DEFAULT_SCOPES } from \"@/constants.js\";\nimport { GenericAuthenticationInitiator } from \"@/services/AuthenticationService.js\";\nimport { GenericPublicClientPKCEProducer } from \"@/services/PKCE.js\";\nimport { ServerAuthenticationResolver } from \"@/server/ServerAuthenticationResolver.js\";\nimport type { AuthConfig } from \"@/server/config.ts\";\nimport { generateState } from \"@/lib/oauth.js\";\n\n/**\n * Context interface for detecting frontend vs backend requests\n */\nexport interface RequestContext {\n referer?: string;\n origin?: string;\n userAgent?: string;\n acceptsJson?: boolean;\n}\n\n/**\n * Resolve an OAuth access code to a set of OIDC tokens\n * @param code The access code, typically from a query parameter in the redirect url\n * @param state The oauth random state string, used to distinguish between requests. Typically also passed in the redirect url\n * @param storage The place that this server uses to store session data (e.g. a cookie store)\n * @param config Oauth Server configuration\n */\nexport async function resolveOAuthAccessCode(\n code: string,\n state: string,\n storage: AuthStorage,\n config: AuthConfig,\n): Promise<OIDCTokenResponseBody> {\n const authSessionService = await ServerAuthenticationResolver.build(\n {\n ...config,\n oauthServer: config.oauthServer ?? DEFAULT_AUTH_SERVER,\n },\n storage,\n config.endpointOverrides,\n );\n\n return authSessionService.tokenExchange(code, state);\n}\n\nexport async function isLoggedIn(storage: AuthStorage): Promise<boolean> {\n return !!(await storage.get(\"id_token\"));\n}\n\nexport async function buildLoginUrl(\n config: Pick<AuthConfig, \"clientId\" | \"redirectUrl\"> &\n Partial<Pick<AuthConfig, \"oauthServer\" | \"pkce\" | \"clientSecret\">> & {\n scopes?: string[];\n state?: string;\n nonce?: string;\n framework?: FrameworkType;\n sdkVersion?: string;\n },\n storage?: AuthStorage,\n): Promise<URL> {\n // Generate state: prioritize provided state (which preserves frontend display mode)\n let state: string;\n if (config.state) {\n // Use the provided state (e.g., from frontend with display mode info)\n state = config.state;\n } else if (config.sdkVersion || config.framework) {\n // Generate new structured state with framework/SDK info\n state = generateState({\n framework: config.framework,\n sdkVersion: config.sdkVersion,\n });\n } else {\n // Generate random state as fallback\n state = Math.random().toString(36).substring(2);\n }\n\n const scopes = config.scopes ?? DEFAULT_SCOPES;\n\n // Determine if PKCE should be used based on config\n // Default to true for backward compatibility if not specified\n const usePkce = config.pkce !== false;\n\n // Only create PKCE producer if we're using PKCE and have storage\n const pkceProducer =\n usePkce && storage ? new GenericPublicClientPKCEProducer(storage) : null;\n\n const authInitiator = new GenericAuthenticationInitiator({\n ...config,\n state,\n scopes,\n oauthServer: config.oauthServer ?? DEFAULT_AUTH_SERVER,\n // When retrieving the PKCE challenge on the server-side, we produce it and store it in the session\n // For confidential clients not using PKCE, this will be undefined\n pkceConsumer: pkceProducer ?? undefined,\n });\n\n return authInitiator.signIn();\n}\n"]}
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/server/login.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,EAAE,8BAA8B,EAAE,MAAM,qCAAqC,CAAC;AACrF,OAAO,EAAE,+BAA+B,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,EAAE,4BAA4B,EAAE,MAAM,0CAA0C,CAAC;AAExF,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAY/C;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,IAAY,EACZ,KAAa,EACb,OAAoB,EACpB,MAAkB;IAElB,MAAM,kBAAkB,GAAG,MAAM,4BAA4B,CAAC,KAAK,CACjE;QACE,GAAG,MAAM;QACT,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,mBAAmB;KACvD,EACD,OAAO,EACP,MAAM,CAAC,iBAAiB,CACzB,CAAC;IAEF,OAAO,kBAAkB,CAAC,aAAa,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAAoB;IACnD,OAAO,CAAC,CAAC,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAOG,EACH,OAAqB;IAErB,oFAAoF;IACpF,IAAI,KAAa,CAAC;IAClB,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,sEAAsE;QACtE,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;IACvB,CAAC;SAAM,IAAI,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACjD,wDAAwD;QACxD,KAAK,GAAG,aAAa,CAAC;YACpB,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,UAAU,EAAE,MAAM,CAAC,UAAU;SAC9B,CAAC,CAAC;IACL,CAAC;SAAM,CAAC;QACN,oCAAoC;QACpC,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAClD,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,cAAc,CAAC;IAE/C,mDAAmD;IACnD,8DAA8D;IAC9D,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,KAAK,KAAK,CAAC;IAEtC,iEAAiE;IACjE,MAAM,YAAY,GAChB,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,IAAI,+BAA+B,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAE3E,kDAAkD;IAClD,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACrE,CAAC;IAED,MAAM,aAAa,GAAG,IAAI,8BAA8B,CAAC;QACvD,GAAG,MAAM;QACT,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,KAAK;QACL,MAAM;QACN,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,mBAAmB;QACtD,mGAAmG;QACnG,kEAAkE;QAClE,YAAY,EAAE,YAAY,IAAI,SAAS;KACxC,CAAC,CAAC;IAEH,OAAO,aAAa,CAAC,MAAM,EAAE,CAAC;AAChC,CAAC","sourcesContent":["import type {\n AuthStorage,\n OIDCTokenResponseBody,\n FrameworkType,\n} from \"@/types.js\";\nimport { DEFAULT_AUTH_SERVER, DEFAULT_SCOPES } from \"@/constants.js\";\nimport { GenericAuthenticationInitiator } from \"@/services/AuthenticationService.js\";\nimport { GenericPublicClientPKCEProducer } from \"@/services/PKCE.js\";\nimport { ServerAuthenticationResolver } from \"@/server/ServerAuthenticationResolver.js\";\nimport type { AuthConfig } from \"@/server/config.ts\";\nimport { generateState } from \"@/lib/oauth.js\";\n\n/**\n * Context interface for detecting frontend vs backend requests\n */\nexport interface RequestContext {\n referer?: string;\n origin?: string;\n userAgent?: string;\n acceptsJson?: boolean;\n}\n\n/**\n * Resolve an OAuth access code to a set of OIDC tokens\n * @param code The access code, typically from a query parameter in the redirect url\n * @param state The oauth random state string, used to distinguish between requests. Typically also passed in the redirect url\n * @param storage The place that this server uses to store session data (e.g. a cookie store)\n * @param config Oauth Server configuration\n */\nexport async function resolveOAuthAccessCode(\n code: string,\n state: string,\n storage: AuthStorage,\n config: AuthConfig,\n): Promise<OIDCTokenResponseBody> {\n const authSessionService = await ServerAuthenticationResolver.build(\n {\n ...config,\n oauthServer: config.oauthServer ?? DEFAULT_AUTH_SERVER,\n },\n storage,\n config.endpointOverrides,\n );\n\n return authSessionService.tokenExchange(code, state);\n}\n\nexport async function isLoggedIn(storage: AuthStorage): Promise<boolean> {\n return !!(await storage.get(\"id_token\"));\n}\n\nexport async function buildLoginUrl(\n config: Pick<AuthConfig, \"clientId\" | \"redirectUrl\"> &\n Partial<Pick<AuthConfig, \"oauthServer\" | \"pkce\" | \"clientSecret\">> & {\n scopes?: string[];\n state?: string;\n nonce?: string;\n framework?: FrameworkType;\n sdkVersion?: string;\n },\n storage?: AuthStorage,\n): Promise<URL> {\n // Generate state: prioritize provided state (which preserves frontend display mode)\n let state: string;\n if (config.state) {\n // Use the provided state (e.g., from frontend with display mode info)\n state = config.state;\n } else if (config.sdkVersion || config.framework) {\n // Generate new structured state with framework/SDK info\n state = generateState({\n framework: config.framework,\n sdkVersion: config.sdkVersion,\n });\n } else {\n // Generate random state as fallback\n state = Math.random().toString(36).substring(2);\n }\n\n const scopes = config.scopes ?? DEFAULT_SCOPES;\n\n // Determine if PKCE should be used based on config\n // Default to true for backward compatibility if not specified\n const usePkce = config.pkce !== false;\n\n // Only create PKCE producer if we're using PKCE and have storage\n const pkceProducer =\n usePkce && storage ? new GenericPublicClientPKCEProducer(storage) : null;\n\n // Ensure clientId is present for OAuth operations\n if (!config.clientId) {\n throw new Error(\"clientId is required for OAuth login operations\");\n }\n\n const authInitiator = new GenericAuthenticationInitiator({\n ...config,\n clientId: config.clientId,\n state,\n scopes,\n oauthServer: config.oauthServer ?? DEFAULT_AUTH_SERVER,\n // When retrieving the PKCE challenge on the server-side, we produce it and store it in the session\n // For confidential clients not using PKCE, this will be undefined\n pkceConsumer: pkceProducer ?? undefined,\n });\n\n return authInitiator.signIn();\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../src/server/logout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAM9C,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,uBAAuB,CAAC,GAC5D,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC,GAAG;IACzC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,EACH,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../src/server/logout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAM9C,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,uBAAuB,CAAC,GAC5D,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC,GAAG;IACzC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,EACH,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,GAAG,CAAC,CAwBd"}
|
package/dist/server/logout.js
CHANGED
|
@@ -3,12 +3,17 @@ import { GenericPublicClientPKCEProducer } from "../services/PKCE.js";
|
|
|
3
3
|
import { GenericAuthenticationInitiator } from "../services/AuthenticationService.js";
|
|
4
4
|
import { OAuthTokenTypes } from "../shared/lib/types.js";
|
|
5
5
|
export async function buildLogoutRedirectUrl(config, storage) {
|
|
6
|
+
// Ensure clientId is present for OAuth operations
|
|
7
|
+
if (!config.clientId) {
|
|
8
|
+
throw new Error("clientId is required for OAuth logout operations");
|
|
9
|
+
}
|
|
6
10
|
// generate a random state if not provided
|
|
7
11
|
const state = config.state ?? Math.random().toString(36).substring(2);
|
|
8
12
|
const scopes = config.scopes ?? DEFAULT_SCOPES;
|
|
9
13
|
const pkceProducer = new GenericPublicClientPKCEProducer(storage);
|
|
10
14
|
const authInitiator = new GenericAuthenticationInitiator({
|
|
11
15
|
...config,
|
|
16
|
+
clientId: config.clientId,
|
|
12
17
|
state,
|
|
13
18
|
scopes,
|
|
14
19
|
oauthServer: config.oauthServer ?? DEFAULT_AUTH_SERVER,
|