@civic/auth 0.6.0 → 0.6.1-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/dist/shared/components/CivicAuthIframeContainer.js +1 -1
  2. package/dist/shared/components/CivicAuthIframeContainer.js.map +1 -1
  3. package/dist/shared/lib/BrowserAuthenticationRefresher.d.ts +7 -1
  4. package/dist/shared/lib/BrowserAuthenticationRefresher.d.ts.map +1 -1
  5. package/dist/shared/lib/BrowserAuthenticationRefresher.js +15 -2
  6. package/dist/shared/lib/BrowserAuthenticationRefresher.js.map +1 -1
  7. package/dist/shared/lib/util.d.ts +1 -1
  8. package/dist/shared/lib/util.d.ts.map +1 -1
  9. package/dist/shared/lib/util.js +6 -1
  10. package/dist/shared/lib/util.js.map +1 -1
  11. package/dist/shared/version.d.ts +1 -1
  12. package/dist/shared/version.d.ts.map +1 -1
  13. package/dist/shared/version.js +1 -1
  14. package/dist/shared/version.js.map +1 -1
  15. package/dist/vanillajs/auth/CivicAuth.d.ts +63 -5
  16. package/dist/vanillajs/auth/CivicAuth.d.ts.map +1 -1
  17. package/dist/vanillajs/auth/CivicAuth.js +202 -26
  18. package/dist/vanillajs/auth/CivicAuth.js.map +1 -1
  19. package/dist/vanillajs/auth/OAuthCallbackHandler.d.ts +90 -0
  20. package/dist/vanillajs/auth/OAuthCallbackHandler.d.ts.map +1 -0
  21. package/dist/vanillajs/auth/OAuthCallbackHandler.js +143 -0
  22. package/dist/vanillajs/auth/OAuthCallbackHandler.js.map +1 -0
  23. package/dist/vanillajs/auth/SessionManager.d.ts +40 -9
  24. package/dist/vanillajs/auth/SessionManager.d.ts.map +1 -1
  25. package/dist/vanillajs/auth/SessionManager.js +96 -61
  26. package/dist/vanillajs/auth/SessionManager.js.map +1 -1
  27. package/dist/vanillajs/auth/TokenRefresher.d.ts +54 -0
  28. package/dist/vanillajs/auth/TokenRefresher.d.ts.map +1 -0
  29. package/dist/vanillajs/auth/TokenRefresher.js +166 -0
  30. package/dist/vanillajs/auth/TokenRefresher.js.map +1 -0
  31. package/dist/vanillajs/iframe/IframeManager.d.ts +82 -0
  32. package/dist/vanillajs/iframe/IframeManager.d.ts.map +1 -0
  33. package/dist/vanillajs/iframe/IframeManager.js +487 -0
  34. package/dist/vanillajs/iframe/IframeManager.js.map +1 -0
  35. package/dist/vanillajs/iframe/IframeResizer.d.ts +15 -0
  36. package/dist/vanillajs/iframe/IframeResizer.d.ts.map +1 -0
  37. package/dist/vanillajs/iframe/IframeResizer.js +127 -0
  38. package/dist/vanillajs/iframe/IframeResizer.js.map +1 -0
  39. package/dist/vanillajs/index.d.ts +8 -7
  40. package/dist/vanillajs/index.d.ts.map +1 -1
  41. package/dist/vanillajs/index.js +10 -7
  42. package/dist/vanillajs/index.js.map +1 -1
  43. package/dist/vanillajs/types/index.d.ts +2 -2
  44. package/dist/vanillajs/types/index.d.ts.map +1 -1
  45. package/dist/vanillajs/types/index.js.map +1 -1
  46. package/dist/vanillajs/ui/LoadingComponents.d.ts +51 -0
  47. package/dist/vanillajs/ui/LoadingComponents.d.ts.map +1 -0
  48. package/dist/vanillajs/ui/LoadingComponents.js +363 -0
  49. package/dist/vanillajs/ui/LoadingComponents.js.map +1 -0
  50. package/package.json +1 -1
  51. package/dist/vanillajs/iframe/domUtils.d.ts +0 -4
  52. package/dist/vanillajs/iframe/domUtils.d.ts.map +0 -1
  53. package/dist/vanillajs/iframe/domUtils.js +0 -25
  54. package/dist/vanillajs/iframe/domUtils.js.map +0 -1
  55. package/dist/vanillajs/storage/BrowserCookieStorageAdapter.d.ts +0 -19
  56. package/dist/vanillajs/storage/BrowserCookieStorageAdapter.d.ts.map +0 -1
  57. package/dist/vanillajs/storage/BrowserCookieStorageAdapter.js +0 -101
  58. package/dist/vanillajs/storage/BrowserCookieStorageAdapter.js.map +0 -1
  59. package/dist/vanillajs/storage/BrowserLocalStorageAdapter.d.ts +0 -9
  60. package/dist/vanillajs/storage/BrowserLocalStorageAdapter.d.ts.map +0 -1
  61. package/dist/vanillajs/storage/BrowserLocalStorageAdapter.js +0 -36
  62. package/dist/vanillajs/storage/BrowserLocalStorageAdapter.js.map +0 -1
  63. package/dist/vanillajs/storage/InMemoryStorageAdapter.d.ts +0 -9
  64. package/dist/vanillajs/storage/InMemoryStorageAdapter.d.ts.map +0 -1
  65. package/dist/vanillajs/storage/InMemoryStorageAdapter.js +0 -16
  66. package/dist/vanillajs/storage/InMemoryStorageAdapter.js.map +0 -1
  67. package/dist/vanillajs/storage/StorageAdapter.d.ts +0 -15
  68. package/dist/vanillajs/storage/StorageAdapter.d.ts.map +0 -1
  69. package/dist/vanillajs/storage/StorageAdapter.js +0 -16
  70. package/dist/vanillajs/storage/StorageAdapter.js.map +0 -1
  71. package/dist/vanillajs/utils/page-handlers.d.ts +0 -29
  72. package/dist/vanillajs/utils/page-handlers.d.ts.map +0 -1
  73. package/dist/vanillajs/utils/page-handlers.js +0 -165
  74. package/dist/vanillajs/utils/page-handlers.js.map +0 -1
@@ -0,0 +1,143 @@
1
+ /**
2
+ * OAuth Callback Handler for Vanilla JavaScript Applications
3
+ *
4
+ * This module provides functionality for handling OAuth redirect/callback pages in vanilla JavaScript
5
+ * applications using the Civic Auth system. It processes the OAuth authorization code flow completion
6
+ * by exchanging authorization codes for access tokens and managing the authentication state.
7
+ *
8
+ * Key responsibilities:
9
+ * - Process OAuth callback URL parameters (code, state)
10
+ * - Exchange authorization codes for access tokens using PKCE
11
+ * - Store tokens and user session data using shared utilities
12
+ * - Create DOM signals for iframe-based authentication flows
13
+ * - Handle error states and cleanup during the OAuth flow
14
+ *
15
+ * This module works in conjunction with:
16
+ * - CivicAuth class for initiating OAuth flows
17
+ * - SignalObserver for detecting authentication completion in iframes
18
+ * - Shared token storage utilities for consistent state management
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * // In an OAuth callback page
23
+ * import { handleOAuthRedirectPage, LocalStorageAdapter } from '@civic/auth/vanillajs';
24
+ *
25
+ * const handled = await handleOAuthRedirectPage({
26
+ * clientId: 'your-client-id',
27
+ * redirectUrl: 'https://your-app.com/callback',
28
+ * oauthServer: 'https://auth.civic.com/oauth/',
29
+ * textSignals: {
30
+ * success: 'Authentication successful!',
31
+ * error: 'Authentication failed!'
32
+ * },
33
+ * storageAdapter: new LocalStorageAdapter()
34
+ * });
35
+ * ```
36
+ */
37
+ import { exchangeTokens, buildOauth2Client, getEndpointsWithOverrides, storeTokens as sharedStoreTokens, } from "../../shared/lib/util.js";
38
+ import { getUser } from "../../shared/lib/session.js";
39
+ import { GenericUserSession } from "../../shared/lib/UserSession.js";
40
+ import { CodeVerifier } from "../../shared/lib/types.js";
41
+ import { getCurrentLogger } from "../utils/logger.js";
42
+ import { GenericPublicClientPKCEProducer } from "../../services/PKCE.js";
43
+ /**
44
+ * Store tokens using the shared utilities from /shared/lib
45
+ * This ensures consistency with the React implementation and also handles user session storage
46
+ */
47
+ export async function storeTokens(tokens, storageAdapter, loggerInstance = getCurrentLogger()) {
48
+ try {
49
+ // Use shared storeTokens utility for consistent token storage
50
+ await sharedStoreTokens(storageAdapter, tokens);
51
+ // Get user info using shared utilities
52
+ const user = await getUser(storageAdapter);
53
+ if (user) {
54
+ // Store user session using shared utilities
55
+ const userSession = new GenericUserSession(storageAdapter);
56
+ await userSession.set(user);
57
+ loggerInstance.info("CivicAuth: Tokens and user info stored successfully using shared utilities.");
58
+ return user;
59
+ }
60
+ else {
61
+ loggerInstance.warn("CivicAuth: Failed to extract user info from tokens.");
62
+ return null;
63
+ }
64
+ }
65
+ catch (error) {
66
+ loggerInstance.error("CivicAuth: Error storing tokens:", error);
67
+ throw error;
68
+ }
69
+ }
70
+ /**
71
+ * Handle OAuth redirect page processing for vanilla JavaScript applications.
72
+ * This function processes the OAuth callback URL parameters and exchanges the authorization code for tokens.
73
+ *
74
+ * @param config - Configuration object for handling the OAuth redirect
75
+ * @param config.clientId - OAuth client ID
76
+ * @param config.redirectUrl - URL to redirect to after authentication
77
+ * @param config.oauthServer - OAuth server base URL
78
+ * @param config.textSignals - Text signals for success and error states
79
+ * @param config.storageAdapter - Storage adapter for persisting auth state (required)
80
+ * @param config.logger - Optional logger instance
81
+ * @returns Promise<boolean> - Returns true if callback was handled, false otherwise
82
+ *
83
+ * @example
84
+ * ```typescript
85
+ * import { handleOAuthRedirectPage, LocalStorageAdapter } from '@civic/auth/vanillajs';
86
+ *
87
+ * const handled = await handleOAuthRedirectPage({
88
+ * clientId: 'your-client-id',
89
+ * redirectUrl: 'https://your-app.com/callback',
90
+ * oauthServer: 'https://auth.civic.com/oauth/',
91
+ * textSignals: {
92
+ * success: 'Authentication successful!',
93
+ * error: 'Authentication failed!'
94
+ * },
95
+ * storageAdapter: new LocalStorageAdapter()
96
+ * });
97
+ * ```
98
+ */
99
+ export async function handleOAuthRedirectPage(config) {
100
+ const loggerInstance = config.logger || getCurrentLogger();
101
+ const urlParams = new URLSearchParams(window.location.search);
102
+ const code = urlParams.get("code");
103
+ const state = urlParams.get("state");
104
+ if (code && state) {
105
+ loggerInstance.info("CivicAuth: OAuth callback detected with code:", code);
106
+ // Use the provided storage adapter from config
107
+ const storage = config.storageAdapter;
108
+ const pkceProducer = new GenericPublicClientPKCEProducer(storage);
109
+ try {
110
+ const endpoints = await getEndpointsWithOverrides(config.oauthServer);
111
+ const oauth2Client = buildOauth2Client(config.clientId, config.redirectUrl, endpoints);
112
+ const tokenResponse = await exchangeTokens(code, state, pkceProducer, oauth2Client, config.oauthServer, endpoints);
113
+ // Get userInfo from storeTokens using shared utilities
114
+ const userInfo = await storeTokens(tokenResponse, storage, loggerInstance);
115
+ loggerInstance.info("CivicAuth: Tokens stored successfully using shared utilities.");
116
+ const signalElement = document.createElement("div");
117
+ signalElement.id = "civic-auth-success-signal";
118
+ signalElement.textContent = config.textSignals.success;
119
+ if (userInfo) {
120
+ // Embed userInfo if available
121
+ signalElement.setAttribute("data-user-info", JSON.stringify(userInfo));
122
+ }
123
+ signalElement.style.display = "none";
124
+ document.body.appendChild(signalElement);
125
+ loggerInstance.info("CivicAuth: Appended success signal to body.");
126
+ // Clean up the code verifier using shared utilities
127
+ await storage.delete(CodeVerifier.COOKIE_NAME);
128
+ }
129
+ catch (error) {
130
+ loggerInstance.error("CivicAuth: Token exchange error:", error);
131
+ const errorSignalElement = document.createElement("div");
132
+ errorSignalElement.id = "civic-auth-error-signal";
133
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
134
+ errorSignalElement.textContent = `${config.textSignals.error} (Error: ${errorMessage})`;
135
+ errorSignalElement.style.display = "none";
136
+ document.body.appendChild(errorSignalElement);
137
+ return true;
138
+ }
139
+ return true;
140
+ }
141
+ return false;
142
+ }
143
+ //# sourceMappingURL=OAuthCallbackHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OAuthCallbackHandler.js","sourceRoot":"","sources":["../../../src/vanillajs/auth/OAuthCallbackHandler.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * OAuth Callback Handler for Vanilla JavaScript Applications\n *\n * This module provides functionality for handling OAuth redirect/callback pages in vanilla JavaScript\n * applications using the Civic Auth system. It processes the OAuth authorization code flow completion\n * by exchanging authorization codes for access tokens and managing the authentication state.\n *\n * Key responsibilities:\n * - Process OAuth callback URL parameters (code, state)\n * - Exchange authorization codes for access tokens using PKCE\n * - Store tokens and user session data using shared utilities\n * - Create DOM signals for iframe-based authentication flows\n * - Handle error states and cleanup during the OAuth flow\n *\n * This module works in conjunction with:\n * - CivicAuth class for initiating OAuth flows\n * - SignalObserver for detecting authentication completion in iframes\n * - Shared token storage utilities for consistent state management\n *\n * @example\n * ```typescript\n * // In an OAuth callback page\n * import { handleOAuthRedirectPage, LocalStorageAdapter } from '@civic/auth/vanillajs';\n *\n * const handled = await handleOAuthRedirectPage({\n * clientId: 'your-client-id',\n * redirectUrl: 'https://your-app.com/callback',\n * oauthServer: 'https://auth.civic.com/oauth/',\n * textSignals: {\n * success: 'Authentication successful!',\n * error: 'Authentication failed!'\n * },\n * storageAdapter: new LocalStorageAdapter()\n * });\n * ```\n */\n\nimport {\n exchangeTokens,\n buildOauth2Client,\n getEndpointsWithOverrides,\n storeTokens as sharedStoreTokens,\n} from \"../../shared/lib/util.js\";\nimport { getUser } from \"../../shared/lib/session.js\";\nimport { GenericUserSession } from \"../../shared/lib/UserSession.js\";\nimport { CodeVerifier } from \"../../shared/lib/types.js\";\nimport { getCurrentLogger } from \"../utils/logger.js\";\nimport { GenericPublicClientPKCEProducer } from \"../../services/PKCE.js\";\nimport type { AuthStorage, OIDCTokenResponseBody } from \"../../types.js\";\n\n/**\n * Store tokens using the shared utilities from /shared/lib\n * This ensures consistency with the React implementation and also handles user session storage\n */\nexport async function storeTokens(\n tokens: OIDCTokenResponseBody,\n storageAdapter: AuthStorage,\n loggerInstance = getCurrentLogger(),\n): Promise<object | null> {\n try {\n // Use shared storeTokens utility for consistent token storage\n await sharedStoreTokens(storageAdapter, tokens);\n\n // Get user info using shared utilities\n const user = await getUser(storageAdapter);\n if (user) {\n // Store user session using shared utilities\n const userSession = new GenericUserSession(storageAdapter);\n await userSession.set(user);\n loggerInstance.info(\n \"CivicAuth: Tokens and user info stored successfully using shared utilities.\",\n );\n return user;\n } else {\n loggerInstance.warn(\n \"CivicAuth: Failed to extract user info from tokens.\",\n );\n return null;\n }\n } catch (error) {\n loggerInstance.error(\"CivicAuth: Error storing tokens:\", error);\n throw error;\n }\n}\n\nexport interface HandleOAuthRedirectConfig {\n clientId: string;\n redirectUrl: string;\n oauthServer: string;\n textSignals: {\n success: string;\n error: string;\n };\n storageAdapter: AuthStorage;\n logger?: ReturnType<typeof getCurrentLogger>;\n}\n\n/**\n * Handle OAuth redirect page processing for vanilla JavaScript applications.\n * This function processes the OAuth callback URL parameters and exchanges the authorization code for tokens.\n *\n * @param config - Configuration object for handling the OAuth redirect\n * @param config.clientId - OAuth client ID\n * @param config.redirectUrl - URL to redirect to after authentication\n * @param config.oauthServer - OAuth server base URL\n * @param config.textSignals - Text signals for success and error states\n * @param config.storageAdapter - Storage adapter for persisting auth state (required)\n * @param config.logger - Optional logger instance\n * @returns Promise<boolean> - Returns true if callback was handled, false otherwise\n *\n * @example\n * ```typescript\n * import { handleOAuthRedirectPage, LocalStorageAdapter } from '@civic/auth/vanillajs';\n *\n * const handled = await handleOAuthRedirectPage({\n * clientId: 'your-client-id',\n * redirectUrl: 'https://your-app.com/callback',\n * oauthServer: 'https://auth.civic.com/oauth/',\n * textSignals: {\n * success: 'Authentication successful!',\n * error: 'Authentication failed!'\n * },\n * storageAdapter: new LocalStorageAdapter()\n * });\n * ```\n */\nexport async function handleOAuthRedirectPage(\n config: HandleOAuthRedirectConfig,\n): Promise<boolean> {\n const loggerInstance = config.logger || getCurrentLogger();\n const urlParams = new URLSearchParams(window.location.search);\n const code = urlParams.get(\"code\");\n const state = urlParams.get(\"state\");\n\n if (code && state) {\n loggerInstance.info(\"CivicAuth: OAuth callback detected with code:\", code);\n\n // Use the provided storage adapter from config\n const storage = config.storageAdapter;\n const pkceProducer = new GenericPublicClientPKCEProducer(storage);\n\n try {\n const endpoints = await getEndpointsWithOverrides(config.oauthServer);\n const oauth2Client = buildOauth2Client(\n config.clientId,\n config.redirectUrl,\n endpoints,\n );\n\n const tokenResponse = await exchangeTokens(\n code,\n state,\n pkceProducer,\n oauth2Client,\n config.oauthServer,\n endpoints,\n );\n\n // Get userInfo from storeTokens using shared utilities\n const userInfo = await storeTokens(\n tokenResponse,\n storage,\n loggerInstance,\n );\n loggerInstance.info(\n \"CivicAuth: Tokens stored successfully using shared utilities.\",\n );\n\n const signalElement = document.createElement(\"div\");\n signalElement.id = \"civic-auth-success-signal\";\n signalElement.textContent = config.textSignals.success;\n if (userInfo) {\n // Embed userInfo if available\n signalElement.setAttribute(\"data-user-info\", JSON.stringify(userInfo));\n }\n signalElement.style.display = \"none\";\n document.body.appendChild(signalElement);\n loggerInstance.info(\"CivicAuth: Appended success signal to body.\");\n\n // Clean up the code verifier using shared utilities\n await storage.delete(CodeVerifier.COOKIE_NAME);\n } catch (error) {\n loggerInstance.error(\"CivicAuth: Token exchange error:\", error);\n const errorSignalElement = document.createElement(\"div\");\n errorSignalElement.id = \"civic-auth-error-signal\";\n const errorMessage =\n error instanceof Error ? error.message : \"Unknown error\";\n errorSignalElement.textContent = `${config.textSignals.error} (Error: ${errorMessage})`;\n errorSignalElement.style.display = \"none\";\n document.body.appendChild(errorSignalElement);\n return true;\n }\n return true;\n }\n return false;\n}\n"]}
@@ -1,17 +1,48 @@
1
- import type { StorageAdapter } from "../storage/StorageAdapter.js";
1
+ import type { AuthStorage } from "../../types.js";
2
2
  import type { AuthenticationEvents } from "./AuthenticationEvents.js";
3
3
  import type { User, Session } from "../types/index.js";
4
+ import type { AuthConfig } from "../../server/config.js";
4
5
  export declare class SessionManager {
5
6
  private storage;
6
7
  private events;
7
- private currentSession;
8
- constructor(storageAdapter: StorageAdapter, events: AuthenticationEvents);
9
- loadSession(): Promise<void>;
10
- setSession(session: Session): Promise<void>;
11
- clearSession(): Promise<void>;
12
- getUser(): Promise<User | null>;
13
- getSession(): Promise<Session | null>;
8
+ private tokenRefresher?;
9
+ private logger;
10
+ constructor(storageAdapter: AuthStorage, events: AuthenticationEvents);
11
+ /**
12
+ * Initialize the session manager with auth configuration to enable token refresh
13
+ */
14
+ initializeWithAuthConfig(authConfig: AuthConfig): Promise<void>;
15
+ /**
16
+ * Build current session from shared lib storage
17
+ */
18
+ getCurrentSession(): Promise<Session | null>;
19
+ /**
20
+ * Check if user is authenticated using shared lib utilities
21
+ */
14
22
  isAuthenticated(): Promise<boolean>;
15
- refreshToken(): Promise<Session | null>;
23
+ /**
24
+ * Get current user from shared lib storage
25
+ */
26
+ getCurrentUser(): Promise<User | null>;
27
+ /**
28
+ * Clear all authentication data using shared lib utilities
29
+ */
30
+ clearSession(): Promise<void>;
31
+ /**
32
+ * Manually trigger token refresh
33
+ */
34
+ refreshTokens(): Promise<void>;
35
+ /**
36
+ * Get token refresher state for debugging
37
+ */
38
+ getTokenRefresherState(): {
39
+ isInitialized: boolean;
40
+ isAuthenticated: boolean;
41
+ isAutoRefreshActive: boolean;
42
+ } | null;
43
+ /**
44
+ * Clean up resources when session manager is destroyed
45
+ */
46
+ destroy(): Promise<void>;
16
47
  }
17
48
  //# sourceMappingURL=SessionManager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SessionManager.d.ts","sourceRoot":"","sources":["../../../src/vanillajs/auth/SessionManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAMvD,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,cAAc,CAAwB;gBAElC,cAAc,EAAE,cAAc,EAAE,MAAM,EAAE,oBAAoB;IAMlE,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAsB5B,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAS3C,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ7B,OAAO,IAAI,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAK/B,UAAU,IAAI,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAIrC,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC;IAanC,YAAY,IAAI,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;CAqB9C"}
1
+ {"version":3,"file":"SessionManager.d.ts","sourceRoot":"","sources":["../../../src/vanillajs/auth/SessionManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAIvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAKzD,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,cAAc,CAAC,CAAiB;IACxC,OAAO,CAAC,MAAM,CAAsB;gBAExB,cAAc,EAAE,WAAW,EAAE,MAAM,EAAE,oBAAoB;IAQrE;;OAEG;IACG,wBAAwB,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BrE;;OAEG;IACG,iBAAiB,IAAI,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAyBlD;;OAEG;IACG,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC;IAKzC;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAS5C;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAmBnC;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAUpC;;OAEG;IACH,sBAAsB,IAAI;QACxB,aAAa,EAAE,OAAO,CAAC;QACvB,eAAe,EAAE,OAAO,CAAC;QACzB,mBAAmB,EAAE,OAAO,CAAC;KAC9B,GAAG,IAAI;IAIR;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAK/B"}
@@ -1,86 +1,121 @@
1
1
  import { AuthEvent } from "../types/index.js";
2
- import { loggers } from "../utils/logger.js";
3
- const SESSION_STORAGE_KEY = "civic_auth_session";
2
+ import { getCurrentLogger } from "../utils/logger.js";
3
+ import { TokenRefresher } from "./TokenRefresher.js";
4
+ import { retrieveTokens, clearTokens } from "../../shared/lib/util.js";
5
+ import { getUser } from "../../shared/lib/session.js";
6
+ import { GenericUserSession } from "../../shared/lib/UserSession.js";
4
7
  export class SessionManager {
5
8
  storage;
6
9
  events;
7
- currentSession = null;
10
+ tokenRefresher;
11
+ logger = getCurrentLogger();
8
12
  constructor(storageAdapter, events) {
9
13
  this.storage = storageAdapter;
10
14
  this.events = events;
11
- this.loadSession(); // Initial load
15
+ this.logger.info("SessionManager initialized with shared lib token storage");
12
16
  }
13
- async loadSession() {
17
+ /**
18
+ * Initialize the session manager with auth configuration to enable token refresh
19
+ */
20
+ async initializeWithAuthConfig(authConfig) {
14
21
  try {
15
- const storedSession = await this.storage.getItem(SESSION_STORAGE_KEY);
16
- if (storedSession) {
17
- this.currentSession = JSON.parse(storedSession);
18
- // TODO: Add validation, token expiry checks here
19
- if (this.currentSession?.user) {
20
- this.events.emit(AuthEvent.USER_SESSION_CHANGED, this.currentSession.user);
21
- }
22
- }
22
+ // Initialize token refresher
23
+ this.tokenRefresher = new TokenRefresher(this.storage, this.events, authConfig);
24
+ await this.tokenRefresher.initialize(authConfig);
25
+ // Set current authentication state
26
+ const isAuthenticated = await this.isAuthenticated();
27
+ this.tokenRefresher.setAuthenticationState(isAuthenticated);
28
+ this.logger.info("SessionManager initialized with token refresh capability");
23
29
  }
24
30
  catch (error) {
25
- loggers.session("SessionManager: Error loading session from storage", error);
26
- this.currentSession = null;
31
+ this.logger.error("Failed to initialize SessionManager with auth config:", error);
32
+ this.events.emit(AuthEvent.TOKEN_REFRESH_ERROR, error);
27
33
  }
28
34
  }
29
- async setSession(session) {
30
- this.currentSession = session;
31
- await this.storage.setItem(SESSION_STORAGE_KEY, JSON.stringify(session));
32
- if (session.user) {
33
- this.events.emit(AuthEvent.USER_SESSION_CHANGED, session.user);
35
+ /**
36
+ * Build current session from shared lib storage
37
+ */
38
+ async getCurrentSession() {
39
+ try {
40
+ const tokens = await retrieveTokens(this.storage);
41
+ const user = await this.getCurrentUser();
42
+ if (!tokens?.id_token || !user) {
43
+ this.logger.warn("No id_token or user available, cannot create session");
44
+ return null;
45
+ }
46
+ return {
47
+ user,
48
+ accessToken: tokens.access_token,
49
+ idToken: tokens.id_token,
50
+ refreshToken: tokens.refresh_token ?? undefined,
51
+ expiresAt: tokens.access_token_expires_at ?? undefined,
52
+ };
53
+ }
54
+ catch (error) {
55
+ this.logger.error("Failed to load session from shared storage:", error);
56
+ return null;
34
57
  }
35
- // TODO: schedule token refresh if applicable based on session.expiresAt
36
- }
37
- async clearSession() {
38
- this.currentSession = null;
39
- await this.storage.removeItem(SESSION_STORAGE_KEY);
40
- this.events.emit(AuthEvent.USER_SESSION_CHANGED, null);
41
- // TODO: cancel any scheduled token refresh
42
- loggers.session("SessionManager: Session cleared.");
43
- }
44
- async getUser() {
45
- // Potentially refresh or validate session before returning user
46
- return this.currentSession?.user || null;
47
- }
48
- async getSession() {
49
- return this.currentSession;
50
58
  }
59
+ /**
60
+ * Check if user is authenticated using shared lib utilities
61
+ */
51
62
  async isAuthenticated() {
52
- // Add more sophisticated checks, e.g., token validation, expiry
53
- // For now, just checks if a user object exists in the session
54
- if (!this.currentSession || !this.currentSession.idToken) {
55
- return false;
56
- }
57
- // Placeholder: In a real scenario, validate token (e.g. using TokenService)
58
- // const tokenService = new TokenService(); // Or get as dependency
59
- // return tokenService.isValid(this.currentSession.accessToken);
60
- return !!this.currentSession.user;
63
+ const tokens = await retrieveTokens(this.storage);
64
+ return !!tokens?.id_token;
61
65
  }
62
- // Placeholder for token refresh logic
63
- async refreshToken() {
64
- this.events.emit(AuthEvent.TOKEN_REFRESH_STARTED);
66
+ /**
67
+ * Get current user from shared lib storage
68
+ */
69
+ async getCurrentUser() {
65
70
  try {
66
- // Actual refresh logic would go here (e.g., call an API with refresh token)
67
- // For now, just a placeholder that does nothing or simulates a failure/success
68
- loggers.session("SessionManager: refreshToken() not implemented.");
69
- // const newSession = await ApiService.refreshToken(this.currentSession.refreshToken);
70
- // if (newSession) {
71
- // await this.setSession(newSession);
72
- // this.events.emit(AuthEvent.TOKEN_REFRESH_COMPLETE, newSession.user);
73
- // return newSession;
74
- // }
75
- throw new Error("Refresh token flow not implemented.");
71
+ return await getUser(this.storage);
76
72
  }
77
73
  catch (error) {
78
- loggers.session("SessionManager: Token refresh failed", error);
79
- this.events.emit(AuthEvent.TOKEN_REFRESH_ERROR, error);
80
- // Potentially clear session if refresh fails critically
81
- // await this.clearSession();
74
+ this.logger.error("Failed to get user from shared storage:", error);
82
75
  return null;
83
76
  }
84
77
  }
78
+ /**
79
+ * Clear all authentication data using shared lib utilities
80
+ */
81
+ async clearSession() {
82
+ try {
83
+ await clearTokens(this.storage);
84
+ // Clear user session using shared utilities
85
+ const userSession = new GenericUserSession(this.storage);
86
+ await userSession.clear();
87
+ // Stop token refresher when session is cleared
88
+ this.tokenRefresher?.setAuthenticationState(false);
89
+ this.events.emit(AuthEvent.USER_SESSION_CHANGED, null);
90
+ this.logger.info("Session cleared using shared lib utilities");
91
+ }
92
+ catch (error) {
93
+ this.logger.error("Failed to clear session:", error);
94
+ throw error;
95
+ }
96
+ }
97
+ /**
98
+ * Manually trigger token refresh
99
+ */
100
+ async refreshTokens() {
101
+ if (!this.tokenRefresher) {
102
+ throw new Error("Token refresher not initialized. Call initializeWithAuthConfig first.");
103
+ }
104
+ return this.tokenRefresher.refreshTokens();
105
+ }
106
+ /**
107
+ * Get token refresher state for debugging
108
+ */
109
+ getTokenRefresherState() {
110
+ return this.tokenRefresher?.getState() || null;
111
+ }
112
+ /**
113
+ * Clean up resources when session manager is destroyed
114
+ */
115
+ async destroy() {
116
+ await this.tokenRefresher?.destroy();
117
+ this.tokenRefresher = undefined;
118
+ this.logger.info("SessionManager destroyed");
119
+ }
85
120
  }
86
121
  //# sourceMappingURL=SessionManager.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SessionManager.js","sourceRoot":"","sources":["../../../src/vanillajs/auth/SessionManager.ts"],"names":[],"mappings":"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","sourcesContent":["import type { StorageAdapter } from \"../storage/StorageAdapter.js\";\nimport type { AuthenticationEvents } from \"./AuthenticationEvents.js\";\nimport type { User, Session } from \"../types/index.js\"; // Assuming Session might be used internally\nimport { AuthEvent } from \"../types/index.js\";\nimport { loggers } from \"../utils/logger.js\";\n\nconst SESSION_STORAGE_KEY = \"civic_auth_session\";\n\nexport class SessionManager {\n private storage: StorageAdapter;\n private events: AuthenticationEvents;\n private currentSession: Session | null = null;\n\n constructor(storageAdapter: StorageAdapter, events: AuthenticationEvents) {\n this.storage = storageAdapter;\n this.events = events;\n this.loadSession(); // Initial load\n }\n\n async loadSession(): Promise<void> {\n try {\n const storedSession = await this.storage.getItem(SESSION_STORAGE_KEY);\n if (storedSession) {\n this.currentSession = JSON.parse(storedSession);\n // TODO: Add validation, token expiry checks here\n if (this.currentSession?.user) {\n this.events.emit(\n AuthEvent.USER_SESSION_CHANGED,\n this.currentSession.user,\n );\n }\n }\n } catch (error) {\n loggers.session(\n \"SessionManager: Error loading session from storage\",\n error,\n );\n this.currentSession = null;\n }\n }\n\n async setSession(session: Session): Promise<void> {\n this.currentSession = session;\n await this.storage.setItem(SESSION_STORAGE_KEY, JSON.stringify(session));\n if (session.user) {\n this.events.emit(AuthEvent.USER_SESSION_CHANGED, session.user);\n }\n // TODO: schedule token refresh if applicable based on session.expiresAt\n }\n\n async clearSession(): Promise<void> {\n this.currentSession = null;\n await this.storage.removeItem(SESSION_STORAGE_KEY);\n this.events.emit(AuthEvent.USER_SESSION_CHANGED, null);\n // TODO: cancel any scheduled token refresh\n loggers.session(\"SessionManager: Session cleared.\");\n }\n\n async getUser(): Promise<User | null> {\n // Potentially refresh or validate session before returning user\n return this.currentSession?.user || null;\n }\n\n async getSession(): Promise<Session | null> {\n return this.currentSession;\n }\n\n async isAuthenticated(): Promise<boolean> {\n // Add more sophisticated checks, e.g., token validation, expiry\n // For now, just checks if a user object exists in the session\n if (!this.currentSession || !this.currentSession.idToken) {\n return false;\n }\n // Placeholder: In a real scenario, validate token (e.g. using TokenService)\n // const tokenService = new TokenService(); // Or get as dependency\n // return tokenService.isValid(this.currentSession.accessToken);\n return !!this.currentSession.user;\n }\n\n // Placeholder for token refresh logic\n async refreshToken(): Promise<Session | null> {\n this.events.emit(AuthEvent.TOKEN_REFRESH_STARTED);\n try {\n // Actual refresh logic would go here (e.g., call an API with refresh token)\n // For now, just a placeholder that does nothing or simulates a failure/success\n loggers.session(\"SessionManager: refreshToken() not implemented.\");\n // const newSession = await ApiService.refreshToken(this.currentSession.refreshToken);\n // if (newSession) {\n // await this.setSession(newSession);\n // this.events.emit(AuthEvent.TOKEN_REFRESH_COMPLETE, newSession.user);\n // return newSession;\n // }\n throw new Error(\"Refresh token flow not implemented.\");\n } catch (error) {\n loggers.session(\"SessionManager: Token refresh failed\", error);\n this.events.emit(AuthEvent.TOKEN_REFRESH_ERROR, error);\n // Potentially clear session if refresh fails critically\n // await this.clearSession();\n return null;\n }\n }\n}\n"]}
1
+ {"version":3,"file":"SessionManager.js","sourceRoot":"","sources":["../../../src/vanillajs/auth/SessionManager.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AuthStorage } from \"../../types.js\";\nimport type { AuthenticationEvents } from \"./AuthenticationEvents.js\";\nimport type { User, Session } from \"../types/index.js\"; // Assuming Session might be used internally\nimport { AuthEvent } from \"../types/index.js\";\nimport { getCurrentLogger } from \"../utils/logger.js\";\nimport { TokenRefresher } from \"./TokenRefresher.js\";\nimport type { AuthConfig } from \"../../server/config.js\";\nimport { retrieveTokens, clearTokens } from \"../../shared/lib/util.js\";\nimport { getUser } from \"../../shared/lib/session.js\";\nimport { GenericUserSession } from \"../../shared/lib/UserSession.js\";\n\nexport class SessionManager {\n private storage: AuthStorage;\n private events: AuthenticationEvents;\n private tokenRefresher?: TokenRefresher;\n private logger = getCurrentLogger();\n\n constructor(storageAdapter: AuthStorage, events: AuthenticationEvents) {\n this.storage = storageAdapter;\n this.events = events;\n this.logger.info(\n \"SessionManager initialized with shared lib token storage\",\n );\n }\n\n /**\n * Initialize the session manager with auth configuration to enable token refresh\n */\n async initializeWithAuthConfig(authConfig: AuthConfig): Promise<void> {\n try {\n // Initialize token refresher\n this.tokenRefresher = new TokenRefresher(\n this.storage,\n this.events,\n authConfig,\n );\n await this.tokenRefresher.initialize(authConfig);\n\n // Set current authentication state\n const isAuthenticated = await this.isAuthenticated();\n this.tokenRefresher.setAuthenticationState(isAuthenticated);\n\n this.logger.info(\n \"SessionManager initialized with token refresh capability\",\n );\n } catch (error) {\n this.logger.error(\n \"Failed to initialize SessionManager with auth config:\",\n error,\n );\n this.events.emit(AuthEvent.TOKEN_REFRESH_ERROR, error);\n }\n }\n\n /**\n * Build current session from shared lib storage\n */\n async getCurrentSession(): Promise<Session | null> {\n try {\n const tokens = await retrieveTokens(this.storage);\n const user = await this.getCurrentUser();\n\n if (!tokens?.id_token || !user) {\n this.logger.warn(\n \"No id_token or user available, cannot create session\",\n );\n return null;\n }\n\n return {\n user,\n accessToken: tokens.access_token,\n idToken: tokens.id_token,\n refreshToken: tokens.refresh_token ?? undefined,\n expiresAt: tokens.access_token_expires_at ?? undefined,\n };\n } catch (error) {\n this.logger.error(\"Failed to load session from shared storage:\", error);\n return null;\n }\n }\n\n /**\n * Check if user is authenticated using shared lib utilities\n */\n async isAuthenticated(): Promise<boolean> {\n const tokens = await retrieveTokens(this.storage);\n return !!tokens?.id_token;\n }\n\n /**\n * Get current user from shared lib storage\n */\n async getCurrentUser(): Promise<User | null> {\n try {\n return await getUser(this.storage);\n } catch (error) {\n this.logger.error(\"Failed to get user from shared storage:\", error);\n return null;\n }\n }\n\n /**\n * Clear all authentication data using shared lib utilities\n */\n async clearSession(): Promise<void> {\n try {\n await clearTokens(this.storage);\n\n // Clear user session using shared utilities\n const userSession = new GenericUserSession(this.storage);\n await userSession.clear();\n\n // Stop token refresher when session is cleared\n this.tokenRefresher?.setAuthenticationState(false);\n\n this.events.emit(AuthEvent.USER_SESSION_CHANGED, null);\n this.logger.info(\"Session cleared using shared lib utilities\");\n } catch (error) {\n this.logger.error(\"Failed to clear session:\", error);\n throw error;\n }\n }\n\n /**\n * Manually trigger token refresh\n */\n async refreshTokens(): Promise<void> {\n if (!this.tokenRefresher) {\n throw new Error(\n \"Token refresher not initialized. Call initializeWithAuthConfig first.\",\n );\n }\n\n return this.tokenRefresher.refreshTokens();\n }\n\n /**\n * Get token refresher state for debugging\n */\n getTokenRefresherState(): {\n isInitialized: boolean;\n isAuthenticated: boolean;\n isAutoRefreshActive: boolean;\n } | null {\n return this.tokenRefresher?.getState() || null;\n }\n\n /**\n * Clean up resources when session manager is destroyed\n */\n async destroy(): Promise<void> {\n await this.tokenRefresher?.destroy();\n this.tokenRefresher = undefined;\n this.logger.info(\"SessionManager destroyed\");\n }\n}\n"]}
@@ -0,0 +1,54 @@
1
+ import type { AuthStorage } from "../../types.js";
2
+ import type { AuthenticationEvents } from "./AuthenticationEvents.js";
3
+ import type { AuthConfig } from "../../server/config.js";
4
+ /**
5
+ * TokenRefresher handles automatic token refresh for vanilla.js implementation
6
+ * Inspired by the React useRefresh hook and BrowserAuthenticationRefresher
7
+ */
8
+ export declare class TokenRefresher {
9
+ private refresher?;
10
+ private storage;
11
+ private events;
12
+ private authConfig?;
13
+ private isAuthenticated;
14
+ private isDestroyed;
15
+ private logger;
16
+ constructor(storage: AuthStorage, events: AuthenticationEvents, authConfig?: AuthConfig);
17
+ /**
18
+ * Initialize the token refresher with auth configuration
19
+ */
20
+ initialize(authConfig: AuthConfig): Promise<void>;
21
+ /**
22
+ * Set authentication state and manage auto-refresh accordingly
23
+ */
24
+ setAuthenticationState(isAuthenticated: boolean): void;
25
+ /**
26
+ * Manually refresh tokens
27
+ */
28
+ refreshTokens(): Promise<void>;
29
+ /**
30
+ * Start automatic token refresh
31
+ */
32
+ private startAutoRefresh;
33
+ /**
34
+ * Stop automatic token refresh
35
+ */
36
+ private stopAutoRefresh;
37
+ /**
38
+ * Clean up resources
39
+ */
40
+ cleanup(): Promise<void>;
41
+ /**
42
+ * Destroy the token refresher permanently
43
+ */
44
+ destroy(): Promise<void>;
45
+ /**
46
+ * Get current refresh state
47
+ */
48
+ getState(): {
49
+ isInitialized: boolean;
50
+ isAuthenticated: boolean;
51
+ isAutoRefreshActive: boolean;
52
+ };
53
+ }
54
+ //# sourceMappingURL=TokenRefresher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TokenRefresher.d.ts","sourceRoot":"","sources":["../../../src/vanillajs/auth/TokenRefresher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAMtE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAIzD;;;GAGG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,SAAS,CAAC,CAAiC;IACnD,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,UAAU,CAAC,CAAa;IAChC,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,MAAM,CAAsB;gBAGlC,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,oBAAoB,EAC5B,UAAU,CAAC,EAAE,UAAU;IASzB;;OAEG;IACG,UAAU,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAoDvD;;OAEG;IACH,sBAAsB,CAAC,eAAe,EAAE,OAAO,GAAG,IAAI;IAgBtD;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAuBpC;;OAEG;YACW,gBAAgB;IAwB9B;;OAEG;IACH,OAAO,CAAC,eAAe;IAOvB;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAW9B;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAM9B;;OAEG;IACH,QAAQ,IAAI;QACV,aAAa,EAAE,OAAO,CAAC;QACvB,eAAe,EAAE,OAAO,CAAC;QACzB,mBAAmB,EAAE,OAAO,CAAC;KAC9B;CAOF"}