@arow-software/auth-client 1.2.0 → 1.3.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/dist/index.d.mts CHANGED
@@ -133,7 +133,11 @@ declare function getAccessToken(): string | null;
133
133
  */
134
134
  declare function getRefreshToken(): string | null;
135
135
  /**
136
- * Store tokens in storage
136
+ * Get the stored token expiry timestamp (seconds since epoch)
137
+ */
138
+ declare function getTokenExpiry(): number | null;
139
+ /**
140
+ * Store tokens in storage, including the expiry timestamp decoded from the JWT
137
141
  */
138
142
  declare function setTokens(accessToken: string, refreshToken: string): void;
139
143
  /**
@@ -161,6 +165,16 @@ declare function refreshTokens(): Promise<TokenPair | null>;
161
165
  * Get a valid access token, refreshing if necessary
162
166
  */
163
167
  declare function getValidAccessToken(): Promise<string | null>;
168
+ /**
169
+ * Cancel any pending proactive refresh timer
170
+ */
171
+ declare function cancelProactiveRefresh(): void;
172
+ /**
173
+ * Schedule a proactive token refresh ~30 seconds before expiry.
174
+ * Calls `onRefreshed` with the new token pair on success so the
175
+ * AuthProvider can update React state without a re-mount.
176
+ */
177
+ declare function scheduleProactiveRefresh(onRefreshed?: (tokens: TokenPair) => void, onFailed?: () => void): void;
164
178
 
165
179
  /**
166
180
  * Create and configure axios instance with auth interceptors
@@ -248,4 +262,4 @@ declare function useUser(): User | null;
248
262
  */
249
263
  declare function useAuthClient(): AxiosInstance;
250
264
 
251
- export { type AuthConfig, AuthContext, type AuthContextValue, AuthProvider, type AuthProviderProps, type AuthState, type JwtPayload, type TokenPair, type User, clearTokens, createApiClient, createAuthClient, decodeJwt, getAccessToken, getRefreshToken, getUserFromToken, getValidAccessToken, hasValidToken, initTokenManager, isTokenExpired, refreshTokens, setTokens, useAuth, useAuthClient, useIsAuthenticated, useUser };
265
+ export { type AuthConfig, AuthContext, type AuthContextValue, AuthProvider, type AuthProviderProps, type AuthState, type JwtPayload, type TokenPair, type User, cancelProactiveRefresh, clearTokens, createApiClient, createAuthClient, decodeJwt, getAccessToken, getRefreshToken, getTokenExpiry, getUserFromToken, getValidAccessToken, hasValidToken, initTokenManager, isTokenExpired, refreshTokens, scheduleProactiveRefresh, setTokens, useAuth, useAuthClient, useIsAuthenticated, useUser };
package/dist/index.d.ts CHANGED
@@ -133,7 +133,11 @@ declare function getAccessToken(): string | null;
133
133
  */
134
134
  declare function getRefreshToken(): string | null;
135
135
  /**
136
- * Store tokens in storage
136
+ * Get the stored token expiry timestamp (seconds since epoch)
137
+ */
138
+ declare function getTokenExpiry(): number | null;
139
+ /**
140
+ * Store tokens in storage, including the expiry timestamp decoded from the JWT
137
141
  */
138
142
  declare function setTokens(accessToken: string, refreshToken: string): void;
139
143
  /**
@@ -161,6 +165,16 @@ declare function refreshTokens(): Promise<TokenPair | null>;
161
165
  * Get a valid access token, refreshing if necessary
162
166
  */
163
167
  declare function getValidAccessToken(): Promise<string | null>;
168
+ /**
169
+ * Cancel any pending proactive refresh timer
170
+ */
171
+ declare function cancelProactiveRefresh(): void;
172
+ /**
173
+ * Schedule a proactive token refresh ~30 seconds before expiry.
174
+ * Calls `onRefreshed` with the new token pair on success so the
175
+ * AuthProvider can update React state without a re-mount.
176
+ */
177
+ declare function scheduleProactiveRefresh(onRefreshed?: (tokens: TokenPair) => void, onFailed?: () => void): void;
164
178
 
165
179
  /**
166
180
  * Create and configure axios instance with auth interceptors
@@ -248,4 +262,4 @@ declare function useUser(): User | null;
248
262
  */
249
263
  declare function useAuthClient(): AxiosInstance;
250
264
 
251
- export { type AuthConfig, AuthContext, type AuthContextValue, AuthProvider, type AuthProviderProps, type AuthState, type JwtPayload, type TokenPair, type User, clearTokens, createApiClient, createAuthClient, decodeJwt, getAccessToken, getRefreshToken, getUserFromToken, getValidAccessToken, hasValidToken, initTokenManager, isTokenExpired, refreshTokens, setTokens, useAuth, useAuthClient, useIsAuthenticated, useUser };
265
+ export { type AuthConfig, AuthContext, type AuthContextValue, AuthProvider, type AuthProviderProps, type AuthState, type JwtPayload, type TokenPair, type User, cancelProactiveRefresh, clearTokens, createApiClient, createAuthClient, decodeJwt, getAccessToken, getRefreshToken, getTokenExpiry, getUserFromToken, getValidAccessToken, hasValidToken, initTokenManager, isTokenExpired, refreshTokens, scheduleProactiveRefresh, setTokens, useAuth, useAuthClient, useIsAuthenticated, useUser };
package/dist/index.js CHANGED
@@ -14,10 +14,13 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
14
14
  var DEFAULT_STORAGE_PREFIX = "arowauth";
15
15
  var ACCESS_TOKEN_KEY = "access_token";
16
16
  var REFRESH_TOKEN_KEY = "refresh_token";
17
+ var TOKEN_EXPIRY_KEY = "token_expiry";
17
18
  var EXPIRY_BUFFER_SECONDS = 300;
19
+ var PROACTIVE_REFRESH_BUFFER_SECONDS = 30;
18
20
  var config = null;
19
21
  var isRefreshing = false;
20
22
  var refreshPromise = null;
23
+ var proactiveRefreshTimer = null;
21
24
  function initTokenManager(authConfig) {
22
25
  config = authConfig;
23
26
  }
@@ -61,15 +64,25 @@ function getAccessToken() {
61
64
  function getRefreshToken() {
62
65
  return getStorage().getItem(getKey(REFRESH_TOKEN_KEY));
63
66
  }
67
+ function getTokenExpiry() {
68
+ const expiry = getStorage().getItem(getKey(TOKEN_EXPIRY_KEY));
69
+ return expiry ? parseInt(expiry, 10) : null;
70
+ }
64
71
  function setTokens(accessToken, refreshToken) {
65
72
  const storage = getStorage();
66
73
  storage.setItem(getKey(ACCESS_TOKEN_KEY), accessToken);
67
74
  storage.setItem(getKey(REFRESH_TOKEN_KEY), refreshToken);
75
+ const payload = decodeJwt(accessToken);
76
+ if (payload?.exp) {
77
+ storage.setItem(getKey(TOKEN_EXPIRY_KEY), String(payload.exp));
78
+ }
68
79
  }
69
80
  function clearTokens() {
70
81
  const storage = getStorage();
71
82
  storage.removeItem(getKey(ACCESS_TOKEN_KEY));
72
83
  storage.removeItem(getKey(REFRESH_TOKEN_KEY));
84
+ storage.removeItem(getKey(TOKEN_EXPIRY_KEY));
85
+ cancelProactiveRefresh();
73
86
  }
74
87
  function isTokenExpired(token) {
75
88
  const accessToken = token ?? getAccessToken();
@@ -149,6 +162,30 @@ async function getValidAccessToken() {
149
162
  const refreshed = await refreshTokens();
150
163
  return refreshed?.accessToken ?? null;
151
164
  }
165
+ function cancelProactiveRefresh() {
166
+ if (proactiveRefreshTimer !== null) {
167
+ clearTimeout(proactiveRefreshTimer);
168
+ proactiveRefreshTimer = null;
169
+ }
170
+ }
171
+ function scheduleProactiveRefresh(onRefreshed, onFailed) {
172
+ cancelProactiveRefresh();
173
+ const expiry = getTokenExpiry();
174
+ if (!expiry) return;
175
+ const now = Math.floor(Date.now() / 1e3);
176
+ const delaySeconds = expiry - now - PROACTIVE_REFRESH_BUFFER_SECONDS;
177
+ if (delaySeconds <= 0) return;
178
+ proactiveRefreshTimer = setTimeout(async () => {
179
+ proactiveRefreshTimer = null;
180
+ const tokens = await refreshTokens();
181
+ if (tokens) {
182
+ scheduleProactiveRefresh(onRefreshed, onFailed);
183
+ onRefreshed?.(tokens);
184
+ } else {
185
+ onFailed?.();
186
+ }
187
+ }, delaySeconds * 1e3);
188
+ }
152
189
 
153
190
  // src/apiInterceptor.ts
154
191
  var isRefreshing2 = false;
@@ -314,6 +351,18 @@ function AuthProvider(props) {
314
351
  initTokenManager(fullConfig);
315
352
  }, [config2.ssoBaseUrl, config2.clientId, config2.apiBaseUrl, onTokenRefresh, onAuthError, onLogout]);
316
353
  react.useEffect(() => {
354
+ const startProactive = () => {
355
+ scheduleProactiveRefresh(
356
+ (tokens) => {
357
+ const user = parseUserFromToken(tokens.accessToken);
358
+ setState((prev) => ({ ...prev, user, isAuthenticated: true, error: null }));
359
+ onTokenRefresh?.(tokens);
360
+ },
361
+ () => {
362
+ setState({ user: null, isAuthenticated: false, isLoading: false, error: null });
363
+ }
364
+ );
365
+ };
317
366
  const initAuth = async () => {
318
367
  try {
319
368
  const hashTokens = parseTokensFromHash();
@@ -326,6 +375,7 @@ function AuthProvider(props) {
326
375
  window.history.replaceState(null, "", redirectPath);
327
376
  }
328
377
  onTokenRefresh?.(hashTokens);
378
+ startProactive();
329
379
  }
330
380
  const token = getAccessToken();
331
381
  if (token && !isTokenExpired(token)) {
@@ -336,6 +386,7 @@ function AuthProvider(props) {
336
386
  isLoading: false,
337
387
  error: null
338
388
  });
389
+ startProactive();
339
390
  return;
340
391
  }
341
392
  if (token) {
@@ -348,6 +399,7 @@ function AuthProvider(props) {
348
399
  isLoading: false,
349
400
  error: null
350
401
  });
402
+ startProactive();
351
403
  return;
352
404
  }
353
405
  }
@@ -367,6 +419,9 @@ function AuthProvider(props) {
367
419
  }
368
420
  };
369
421
  initAuth();
422
+ return () => {
423
+ cancelProactiveRefresh();
424
+ };
370
425
  }, [onTokenRefresh]);
371
426
  const login = react.useCallback((redirectPath) => {
372
427
  const authUrl = buildAuthUrl(
@@ -527,18 +582,21 @@ function useAuthClient() {
527
582
 
528
583
  exports.AuthContext = AuthContext;
529
584
  exports.AuthProvider = AuthProvider;
585
+ exports.cancelProactiveRefresh = cancelProactiveRefresh;
530
586
  exports.clearTokens = clearTokens;
531
587
  exports.createApiClient = createApiClient;
532
588
  exports.createAuthClient = createAuthClient;
533
589
  exports.decodeJwt = decodeJwt;
534
590
  exports.getAccessToken = getAccessToken;
535
591
  exports.getRefreshToken = getRefreshToken;
592
+ exports.getTokenExpiry = getTokenExpiry;
536
593
  exports.getUserFromToken = getUserFromToken;
537
594
  exports.getValidAccessToken = getValidAccessToken;
538
595
  exports.hasValidToken = hasValidToken;
539
596
  exports.initTokenManager = initTokenManager;
540
597
  exports.isTokenExpired = isTokenExpired;
541
598
  exports.refreshTokens = refreshTokens;
599
+ exports.scheduleProactiveRefresh = scheduleProactiveRefresh;
542
600
  exports.setTokens = setTokens;
543
601
  exports.useAuth = useAuth;
544
602
  exports.useAuthClient = useAuthClient;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/tokenManager.ts","../src/apiInterceptor.ts","../src/AuthProvider.tsx","../src/hooks/useAuth.ts","../src/hooks/useAuthClient.ts"],"names":["isRefreshing","config","createContext","useState","useEffect","useCallback","useMemo","useContext","requestQueue","processQueue"],"mappings":"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","file":"index.js","sourcesContent":["import type { JwtPayload, TokenPair, AuthConfig } from './types';\n\nconst DEFAULT_STORAGE_PREFIX = 'arowauth';\nconst ACCESS_TOKEN_KEY = 'access_token';\nconst REFRESH_TOKEN_KEY = 'refresh_token';\n\n// Buffer time before expiry to trigger refresh (5 minutes)\nconst EXPIRY_BUFFER_SECONDS = 300;\n\nlet config: AuthConfig | null = null;\nlet isRefreshing = false;\nlet refreshPromise: Promise<TokenPair | null> | null = null;\n\n/**\n * Initialize token manager with configuration\n */\nexport function initTokenManager(authConfig: AuthConfig): void {\n config = authConfig;\n}\n\n/**\n * Get the storage instance (localStorage or sessionStorage)\n */\nfunction getStorage(): Storage {\n if (typeof window === 'undefined') {\n // SSR fallback - return a no-op storage\n return {\n getItem: () => null,\n setItem: () => {},\n removeItem: () => {},\n clear: () => {},\n key: () => null,\n length: 0,\n };\n }\n return config?.useSessionStorage ? sessionStorage : localStorage;\n}\n\n/**\n * Get storage key with prefix\n */\nfunction getKey(key: string): string {\n const prefix = config?.storagePrefix || DEFAULT_STORAGE_PREFIX;\n return `${prefix}_${key}`;\n}\n\n/**\n * Decode a JWT token without verification\n */\nexport function decodeJwt(token: string): JwtPayload | null {\n try {\n const parts = token.split('.');\n if (parts.length !== 3) return null;\n \n const payload = parts[1];\n // Handle URL-safe base64\n const base64 = payload.replace(/-/g, '+').replace(/_/g, '/');\n const jsonPayload = decodeURIComponent(\n atob(base64)\n .split('')\n .map((c) => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2))\n .join('')\n );\n \n return JSON.parse(jsonPayload) as JwtPayload;\n } catch {\n return null;\n }\n}\n\n/**\n * Get the access token from storage\n */\nexport function getAccessToken(): string | null {\n return getStorage().getItem(getKey(ACCESS_TOKEN_KEY));\n}\n\n/**\n * Get the refresh token from storage\n */\nexport function getRefreshToken(): string | null {\n return getStorage().getItem(getKey(REFRESH_TOKEN_KEY));\n}\n\n/**\n * Store tokens in storage\n */\nexport function setTokens(accessToken: string, refreshToken: string): void {\n const storage = getStorage();\n storage.setItem(getKey(ACCESS_TOKEN_KEY), accessToken);\n storage.setItem(getKey(REFRESH_TOKEN_KEY), refreshToken);\n}\n\n/**\n * Clear all tokens from storage\n */\nexport function clearTokens(): void {\n const storage = getStorage();\n storage.removeItem(getKey(ACCESS_TOKEN_KEY));\n storage.removeItem(getKey(REFRESH_TOKEN_KEY));\n}\n\n/**\n * Check if the access token is expired or about to expire\n */\nexport function isTokenExpired(token?: string | null): boolean {\n const accessToken = token ?? getAccessToken();\n if (!accessToken) return true;\n \n const payload = decodeJwt(accessToken);\n if (!payload || !payload.exp) return true;\n \n // Check if token expires within buffer period\n const now = Math.floor(Date.now() / 1000);\n return payload.exp <= now + EXPIRY_BUFFER_SECONDS;\n}\n\n/**\n * Check if we have a valid (non-expired) access token\n */\nexport function hasValidToken(): boolean {\n const token = getAccessToken();\n return token !== null && !isTokenExpired(token);\n}\n\n/**\n * Get user info from the current access token\n */\nexport function getUserFromToken(): JwtPayload | null {\n const token = getAccessToken();\n if (!token) return null;\n return decodeJwt(token);\n}\n\n/**\n * Refresh tokens using the refresh token\n * Handles concurrent refresh requests by returning the same promise\n */\nexport async function refreshTokens(): Promise<TokenPair | null> {\n if (!config) {\n throw new Error('TokenManager not initialized. Call initTokenManager first.');\n }\n\n const refreshToken = getRefreshToken();\n if (!refreshToken) {\n clearTokens();\n return null;\n }\n\n // If already refreshing, return the existing promise\n if (isRefreshing && refreshPromise) {\n return refreshPromise;\n }\n\n isRefreshing = true;\n refreshPromise = performRefresh(refreshToken);\n\n try {\n const result = await refreshPromise;\n return result;\n } finally {\n isRefreshing = false;\n refreshPromise = null;\n }\n}\n\n/**\n * Perform the actual token refresh request\n */\nasync function performRefresh(refreshToken: string): Promise<TokenPair | null> {\n if (!config) return null;\n\n try {\n const response = await fetch(`${config.ssoBaseUrl}/api/auth/refresh`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ refreshToken }),\n });\n\n if (!response.ok) {\n clearTokens();\n config.onAuthError?.(new Error('Token refresh failed'));\n return null;\n }\n\n const data = await response.json();\n const tokens: TokenPair = {\n accessToken: data.accessToken || data.access_token,\n refreshToken: data.refreshToken || data.refresh_token,\n expiresIn: data.expiresIn || data.expires_in,\n tokenType: data.tokenType || data.token_type || 'Bearer',\n };\n\n setTokens(tokens.accessToken, tokens.refreshToken);\n config.onTokenRefresh?.(tokens);\n\n return tokens;\n } catch (error) {\n clearTokens();\n config.onAuthError?.(error instanceof Error ? error : new Error('Token refresh failed'));\n return null;\n }\n}\n\n/**\n * Get a valid access token, refreshing if necessary\n */\nexport async function getValidAccessToken(): Promise<string | null> {\n const token = getAccessToken();\n \n if (token && !isTokenExpired(token)) {\n return token;\n }\n\n const refreshed = await refreshTokens();\n return refreshed?.accessToken ?? null;\n}\n","import type { AxiosInstance, InternalAxiosRequestConfig, AxiosResponse, AxiosError } from 'axios';\nimport { getAccessToken, getValidAccessToken, clearTokens } from './tokenManager';\nimport type { AuthConfig } from './types';\n\ninterface QueuedRequest {\n resolve: (token: string | null) => void;\n reject: (error: Error) => void;\n}\n\nlet isRefreshing = false;\nlet requestQueue: QueuedRequest[] = [];\n\n/**\n * Process queued requests after token refresh\n */\nfunction processQueue(token: string | null, error: Error | null = null): void {\n requestQueue.forEach((request) => {\n if (error) {\n request.reject(error);\n } else {\n request.resolve(token);\n }\n });\n requestQueue = [];\n}\n\n/**\n * Create and configure axios instance with auth interceptors\n */\nexport function createAuthClient(\n axiosInstance: AxiosInstance,\n config: AuthConfig\n): AxiosInstance {\n // Request interceptor - attach Bearer token\n axiosInstance.interceptors.request.use(\n async (requestConfig: InternalAxiosRequestConfig): Promise<InternalAxiosRequestConfig> => {\n // Skip auth for refresh endpoint to avoid infinite loop\n if (requestConfig.url?.includes('/api/auth/refresh')) {\n return requestConfig;\n }\n\n const token = getAccessToken();\n if (token) {\n requestConfig.headers = requestConfig.headers || {};\n requestConfig.headers.Authorization = `Bearer ${token}`;\n }\n return requestConfig;\n },\n (error: unknown) => Promise.reject(error)\n );\n\n // Response interceptor - handle 401 and refresh token\n axiosInstance.interceptors.response.use(\n (response: AxiosResponse) => response,\n async (error: AxiosError): Promise<AxiosResponse> => {\n const originalRequest = error.config as InternalAxiosRequestConfig & {\n _retry?: boolean;\n };\n\n // Only handle 401 errors\n if (error.response?.status !== 401) {\n return Promise.reject(error);\n }\n\n // Don't retry if already retried or no config\n if (originalRequest._retry || !originalRequest) {\n clearTokens();\n config.onAuthError?.(new Error('Authentication failed'));\n return Promise.reject(error);\n }\n\n // Don't retry refresh endpoint\n if (originalRequest.url?.includes('/api/auth/refresh')) {\n clearTokens();\n config.onAuthError?.(new Error('Token refresh failed'));\n return Promise.reject(error);\n }\n\n // If already refreshing, queue this request\n if (isRefreshing) {\n return new Promise((resolve, reject) => {\n requestQueue.push({\n resolve: (token) => {\n if (token) {\n originalRequest.headers = originalRequest.headers || {};\n originalRequest.headers.Authorization = `Bearer ${token}`;\n resolve(axiosInstance(originalRequest));\n } else {\n reject(new Error('Token refresh failed'));\n }\n },\n reject,\n });\n });\n }\n\n originalRequest._retry = true;\n isRefreshing = true;\n\n try {\n const token = await getValidAccessToken();\n \n if (!token) {\n processQueue(null, new Error('Token refresh failed'));\n clearTokens();\n config.onAuthError?.(new Error('Token refresh failed'));\n return Promise.reject(error);\n }\n\n processQueue(token);\n \n originalRequest.headers = originalRequest.headers || {};\n originalRequest.headers.Authorization = `Bearer ${token}`;\n \n return axiosInstance(originalRequest);\n } catch (refreshError) {\n processQueue(null, refreshError instanceof Error ? refreshError : new Error('Token refresh failed'));\n clearTokens();\n config.onAuthError?.(refreshError instanceof Error ? refreshError : new Error('Token refresh failed'));\n return Promise.reject(refreshError);\n } finally {\n isRefreshing = false;\n }\n }\n );\n\n return axiosInstance;\n}\n\n/**\n * Create a new axios instance with auth interceptors\n */\nexport function createApiClient(config: AuthConfig): AxiosInstance {\n // Dynamic import to avoid bundling axios if not used\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const axios = require('axios');\n \n const instance = axios.create({\n baseURL: config.apiBaseUrl,\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n return createAuthClient(instance, config);\n}\n","import React, { createContext, useEffect, useState, useCallback, useMemo } from 'react';\nimport type { User, AuthState, AuthContextValue, AuthProviderProps, TokenPair, AuthConfig } from './types';\nimport {\n initTokenManager,\n getAccessToken,\n setTokens,\n clearTokens,\n isTokenExpired,\n decodeJwt,\n getValidAccessToken,\n} from './tokenManager';\n\n// Create context with undefined default\nexport const AuthContext = createContext<AuthContextValue | undefined>(undefined);\n\n/**\n * Parse user from JWT payload\n */\nfunction parseUserFromToken(token: string): User | null {\n const payload = decodeJwt(token);\n if (!payload) return null;\n\n return {\n id: payload.sub,\n email: payload.email,\n firstName: payload.given_name,\n lastName: payload.family_name,\n displayName: payload.name,\n avatarUrl: payload.picture,\n emailVerified: payload.email_verified ?? false,\n roles: payload.roles,\n permissions: payload.permissions,\n };\n}\n\n/**\n * Build the SSO authorization URL\n */\nfunction buildAuthUrl(\n ssoBaseUrl: string,\n clientId: string,\n redirectUri: string | undefined,\n scopes: string[] = ['openid', 'email', 'profile'],\n redirectPath?: string\n): string {\n const finalRedirectUri = redirectUri || `${window.location.origin}/callback`;\n \n // Store the original path to redirect back after login\n if (redirectPath) {\n sessionStorage.setItem('arowauth_redirect_path', redirectPath);\n }\n\n const params = new URLSearchParams({\n client_id: clientId,\n redirect_uri: finalRedirectUri,\n response_type: 'token',\n scope: scopes.join(' '),\n });\n\n return `${ssoBaseUrl}/oauth/authorize?${params.toString()}`;\n}\n\n/**\n * Parse tokens from URL hash fragment (SSO callback)\n */\nfunction parseTokensFromHash(): TokenPair | null {\n if (typeof window === 'undefined') return null;\n \n const hash = window.location.hash;\n if (!hash) return null;\n\n // Parse hash fragment: #access_token=xxx&refresh_token=yyy&...\n const params = new URLSearchParams(hash.substring(1));\n \n const accessToken = params.get('access_token') || params.get('token');\n const refreshToken = params.get('refresh_token');\n\n if (accessToken && refreshToken) {\n return {\n accessToken,\n refreshToken,\n expiresIn: params.get('expires_in') ? parseInt(params.get('expires_in')!, 10) : undefined,\n tokenType: params.get('token_type') || 'Bearer',\n };\n }\n\n return null;\n}\n\n/**\n * AuthProvider component - wraps app with auth context\n */\nexport function AuthProvider(props: AuthProviderProps): React.ReactElement {\n const { children, onTokenRefresh, onAuthError, onLogout, ...config } = props;\n\n const [state, setState] = useState<AuthState>({\n user: null,\n isAuthenticated: false,\n isLoading: true,\n error: null,\n });\n\n // Initialize token manager with config\n useEffect(() => {\n const fullConfig: AuthConfig = {\n ...config,\n onTokenRefresh,\n onAuthError: (error: Error) => {\n setState((prev: AuthState) => ({ ...prev, error: error.message }));\n onAuthError?.(error);\n },\n onLogout,\n };\n initTokenManager(fullConfig);\n }, [config.ssoBaseUrl, config.clientId, config.apiBaseUrl, onTokenRefresh, onAuthError, onLogout]);\n\n // Handle SSO callback and initial auth check\n useEffect(() => {\n const initAuth = async () => {\n try {\n // Check for tokens in URL hash (SSO callback)\n const hashTokens = parseTokensFromHash();\n if (hashTokens) {\n setTokens(hashTokens.accessToken, hashTokens.refreshToken);\n \n // Clean up URL\n window.history.replaceState(null, '', window.location.pathname + window.location.search);\n \n // Redirect to original path if stored\n const redirectPath = sessionStorage.getItem('arowauth_redirect_path');\n if (redirectPath) {\n sessionStorage.removeItem('arowauth_redirect_path');\n window.history.replaceState(null, '', redirectPath);\n }\n\n onTokenRefresh?.(hashTokens);\n }\n\n // Check for existing valid token\n const token = getAccessToken();\n if (token && !isTokenExpired(token)) {\n const user = parseUserFromToken(token);\n setState({\n user,\n isAuthenticated: true,\n isLoading: false,\n error: null,\n });\n return;\n }\n\n // Try to refresh if we have a token but it's expired\n if (token) {\n const newToken = await getValidAccessToken();\n if (newToken) {\n const user = parseUserFromToken(newToken);\n setState({\n user,\n isAuthenticated: true,\n isLoading: false,\n error: null,\n });\n return;\n }\n }\n\n // No valid auth\n setState({\n user: null,\n isAuthenticated: false,\n isLoading: false,\n error: null,\n });\n } catch (error) {\n setState({\n user: null,\n isAuthenticated: false,\n isLoading: false,\n error: error instanceof Error ? error.message : 'Authentication error',\n });\n }\n };\n\n initAuth();\n }, [onTokenRefresh]);\n\n // Login - redirect to SSO\n const login = useCallback((redirectPath?: string) => {\n const authUrl = buildAuthUrl(\n config.ssoBaseUrl,\n config.clientId,\n config.redirectUri,\n config.scopes,\n redirectPath || window.location.pathname\n );\n window.location.href = authUrl;\n }, [config.ssoBaseUrl, config.clientId, config.redirectUri, config.scopes]);\n\n // Logout - clear tokens and optionally call SSO logout\n const logout = useCallback(async () => {\n clearTokens();\n setState({\n user: null,\n isAuthenticated: false,\n isLoading: false,\n error: null,\n });\n onLogout?.();\n }, [onLogout]);\n\n // Refresh user data from token\n const refreshUser = useCallback(async () => {\n const token = await getValidAccessToken();\n if (token) {\n const user = parseUserFromToken(token);\n setState((prev: AuthState) => ({\n ...prev,\n user,\n isAuthenticated: true,\n error: null,\n }));\n } else {\n setState({\n user: null,\n isAuthenticated: false,\n isLoading: false,\n error: null,\n });\n }\n }, []);\n\n // Memoize context value\n const contextValue = useMemo<AuthContextValue>(\n () => ({\n ...state,\n login,\n logout,\n refreshUser,\n }),\n [state, login, logout, refreshUser]\n );\n\n return (\n <AuthContext.Provider value={contextValue}>\n {children}\n </AuthContext.Provider>\n );\n}\n","import { useContext } from 'react';\nimport { AuthContext } from '../AuthProvider';\nimport type { AuthContextValue, User } from '../types';\n\n/**\n * Hook to access auth state and actions\n * \n * @returns Auth context value with user, isAuthenticated, login, logout, etc.\n * @throws Error if used outside of AuthProvider\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * const { user, isAuthenticated, login, logout, isLoading } = useAuth();\n * \n * if (isLoading) return <div>Loading...</div>;\n * \n * if (!isAuthenticated) {\n * return <button onClick={() => login()}>Login</button>;\n * }\n * \n * return (\n * <div>\n * <p>Welcome, {user?.displayName || user?.email}!</p>\n * <button onClick={logout}>Logout</button>\n * </div>\n * );\n * }\n * ```\n */\nexport function useAuth(): AuthContextValue {\n const context = useContext(AuthContext);\n \n if (context === undefined) {\n throw new Error('useAuth must be used within an AuthProvider');\n }\n \n return context;\n}\n\n/**\n * Hook to check if user is authenticated (convenience wrapper)\n * \n * @returns Boolean indicating if user is authenticated\n */\nexport function useIsAuthenticated(): boolean {\n const { isAuthenticated } = useAuth();\n return isAuthenticated;\n}\n\n/**\n * Hook to get current user (convenience wrapper)\n * \n * @returns Current user or null\n */\nexport function useUser(): User | null {\n const { user } = useAuth();\n return user;\n}\n","import { useMemo, useContext } from 'react';\nimport type { AxiosInstance, InternalAxiosRequestConfig, AxiosResponse, AxiosError } from 'axios';\nimport { AuthContext } from '../AuthProvider';\nimport { getAccessToken, getValidAccessToken, clearTokens } from '../tokenManager';\n\ninterface QueuedRequest {\n resolve: (token: string | null) => void;\n reject: (error: Error) => void;\n}\n\n/**\n * Hook to get a configured axios instance with auth interceptors\n * \n * The returned axios instance will:\n * - Automatically attach Bearer token to requests\n * - Handle 401 responses by refreshing tokens and retrying\n * - Queue concurrent requests during token refresh\n * \n * @returns Configured axios instance\n * @throws Error if used outside of AuthProvider\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * const client = useAuthClient();\n * \n * const fetchData = async () => {\n * try {\n * const response = await client.get('/api/data');\n * console.log(response.data);\n * } catch (error) {\n * console.error('Failed to fetch data', error);\n * }\n * };\n * \n * return <button onClick={fetchData}>Fetch Data</button>;\n * }\n * ```\n */\nexport function useAuthClient(): AxiosInstance {\n const context = useContext(AuthContext);\n \n if (context === undefined) {\n throw new Error('useAuthClient must be used within an AuthProvider');\n }\n\n const client = useMemo(() => {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const axios = require('axios');\n \n const instance: AxiosInstance = axios.create({\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n let isRefreshing = false;\n let requestQueue: QueuedRequest[] = [];\n\n const processQueue = (token: string | null, error: Error | null = null): void => {\n requestQueue.forEach((req) => {\n if (error) {\n req.reject(error);\n } else {\n req.resolve(token);\n }\n });\n requestQueue = [];\n };\n\n // Request interceptor\n instance.interceptors.request.use(\n async (config: InternalAxiosRequestConfig): Promise<InternalAxiosRequestConfig> => {\n if (config.url?.includes('/api/auth/refresh')) {\n return config;\n }\n const token = getAccessToken();\n if (token) {\n config.headers = config.headers || {};\n config.headers.Authorization = `Bearer ${token}`;\n }\n return config;\n },\n (error: unknown) => Promise.reject(error)\n );\n\n // Response interceptor\n instance.interceptors.response.use(\n (response: AxiosResponse) => response,\n async (error: AxiosError): Promise<AxiosResponse> => {\n const originalRequest = error.config as InternalAxiosRequestConfig & {\n _retry?: boolean;\n };\n\n if (error.response?.status !== 401 || originalRequest._retry) {\n return Promise.reject(error);\n }\n\n if (originalRequest.url?.includes('/api/auth/refresh')) {\n clearTokens();\n return Promise.reject(error);\n }\n\n if (isRefreshing) {\n return new Promise((resolve, reject) => {\n requestQueue.push({\n resolve: (token) => {\n if (token) {\n originalRequest.headers = originalRequest.headers || {};\n originalRequest.headers.Authorization = `Bearer ${token}`;\n resolve(instance(originalRequest));\n } else {\n reject(new Error('Token refresh failed'));\n }\n },\n reject,\n });\n });\n }\n\n originalRequest._retry = true;\n isRefreshing = true;\n\n try {\n const token = await getValidAccessToken();\n if (!token) {\n processQueue(null, new Error('Token refresh failed'));\n clearTokens();\n return Promise.reject(error);\n }\n\n processQueue(token);\n originalRequest.headers = originalRequest.headers || {};\n originalRequest.headers.Authorization = `Bearer ${token}`;\n return instance(originalRequest);\n } catch (refreshError) {\n processQueue(null, refreshError instanceof Error ? refreshError : new Error('Refresh failed'));\n clearTokens();\n return Promise.reject(refreshError);\n } finally {\n isRefreshing = false;\n }\n }\n );\n\n return instance;\n }, []);\n\n return client;\n}\n"]}
1
+ {"version":3,"sources":["../src/tokenManager.ts","../src/apiInterceptor.ts","../src/AuthProvider.tsx","../src/hooks/useAuth.ts","../src/hooks/useAuthClient.ts"],"names":["isRefreshing","config","createContext","useState","useEffect","useCallback","useMemo","useContext","requestQueue","processQueue"],"mappings":"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","file":"index.js","sourcesContent":["import type { JwtPayload, TokenPair, AuthConfig } from './types';\n\nconst DEFAULT_STORAGE_PREFIX = 'arowauth';\nconst ACCESS_TOKEN_KEY = 'access_token';\nconst REFRESH_TOKEN_KEY = 'refresh_token';\nconst TOKEN_EXPIRY_KEY = 'token_expiry';\n\n// Buffer time before expiry to trigger refresh (5 minutes for isTokenExpired checks)\nconst EXPIRY_BUFFER_SECONDS = 300;\n\n// Proactive refresh fires 30 seconds before expiry\nconst PROACTIVE_REFRESH_BUFFER_SECONDS = 30;\n\nlet config: AuthConfig | null = null;\nlet isRefreshing = false;\nlet refreshPromise: Promise<TokenPair | null> | null = null;\nlet proactiveRefreshTimer: ReturnType<typeof setTimeout> | null = null;\n\n/**\n * Initialize token manager with configuration\n */\nexport function initTokenManager(authConfig: AuthConfig): void {\n config = authConfig;\n}\n\n/**\n * Get the storage instance (localStorage or sessionStorage)\n */\nfunction getStorage(): Storage {\n if (typeof window === 'undefined') {\n // SSR fallback - return a no-op storage\n return {\n getItem: () => null,\n setItem: () => {},\n removeItem: () => {},\n clear: () => {},\n key: () => null,\n length: 0,\n };\n }\n return config?.useSessionStorage ? sessionStorage : localStorage;\n}\n\n/**\n * Get storage key with prefix\n */\nfunction getKey(key: string): string {\n const prefix = config?.storagePrefix || DEFAULT_STORAGE_PREFIX;\n return `${prefix}_${key}`;\n}\n\n/**\n * Decode a JWT token without verification\n */\nexport function decodeJwt(token: string): JwtPayload | null {\n try {\n const parts = token.split('.');\n if (parts.length !== 3) return null;\n \n const payload = parts[1];\n // Handle URL-safe base64\n const base64 = payload.replace(/-/g, '+').replace(/_/g, '/');\n const jsonPayload = decodeURIComponent(\n atob(base64)\n .split('')\n .map((c) => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2))\n .join('')\n );\n \n return JSON.parse(jsonPayload) as JwtPayload;\n } catch {\n return null;\n }\n}\n\n/**\n * Get the access token from storage\n */\nexport function getAccessToken(): string | null {\n return getStorage().getItem(getKey(ACCESS_TOKEN_KEY));\n}\n\n/**\n * Get the refresh token from storage\n */\nexport function getRefreshToken(): string | null {\n return getStorage().getItem(getKey(REFRESH_TOKEN_KEY));\n}\n\n/**\n * Get the stored token expiry timestamp (seconds since epoch)\n */\nexport function getTokenExpiry(): number | null {\n const expiry = getStorage().getItem(getKey(TOKEN_EXPIRY_KEY));\n return expiry ? parseInt(expiry, 10) : null;\n}\n\n/**\n * Store tokens in storage, including the expiry timestamp decoded from the JWT\n */\nexport function setTokens(accessToken: string, refreshToken: string): void {\n const storage = getStorage();\n storage.setItem(getKey(ACCESS_TOKEN_KEY), accessToken);\n storage.setItem(getKey(REFRESH_TOKEN_KEY), refreshToken);\n\n // Persist expiry from JWT exp claim\n const payload = decodeJwt(accessToken);\n if (payload?.exp) {\n storage.setItem(getKey(TOKEN_EXPIRY_KEY), String(payload.exp));\n }\n}\n\n/**\n * Clear all tokens from storage\n */\nexport function clearTokens(): void {\n const storage = getStorage();\n storage.removeItem(getKey(ACCESS_TOKEN_KEY));\n storage.removeItem(getKey(REFRESH_TOKEN_KEY));\n storage.removeItem(getKey(TOKEN_EXPIRY_KEY));\n cancelProactiveRefresh();\n}\n\n/**\n * Check if the access token is expired or about to expire\n */\nexport function isTokenExpired(token?: string | null): boolean {\n const accessToken = token ?? getAccessToken();\n if (!accessToken) return true;\n \n const payload = decodeJwt(accessToken);\n if (!payload || !payload.exp) return true;\n \n // Check if token expires within buffer period\n const now = Math.floor(Date.now() / 1000);\n return payload.exp <= now + EXPIRY_BUFFER_SECONDS;\n}\n\n/**\n * Check if we have a valid (non-expired) access token\n */\nexport function hasValidToken(): boolean {\n const token = getAccessToken();\n return token !== null && !isTokenExpired(token);\n}\n\n/**\n * Get user info from the current access token\n */\nexport function getUserFromToken(): JwtPayload | null {\n const token = getAccessToken();\n if (!token) return null;\n return decodeJwt(token);\n}\n\n/**\n * Refresh tokens using the refresh token\n * Handles concurrent refresh requests by returning the same promise\n */\nexport async function refreshTokens(): Promise<TokenPair | null> {\n if (!config) {\n throw new Error('TokenManager not initialized. Call initTokenManager first.');\n }\n\n const refreshToken = getRefreshToken();\n if (!refreshToken) {\n clearTokens();\n return null;\n }\n\n // If already refreshing, return the existing promise\n if (isRefreshing && refreshPromise) {\n return refreshPromise;\n }\n\n isRefreshing = true;\n refreshPromise = performRefresh(refreshToken);\n\n try {\n const result = await refreshPromise;\n return result;\n } finally {\n isRefreshing = false;\n refreshPromise = null;\n }\n}\n\n/**\n * Perform the actual token refresh request\n */\nasync function performRefresh(refreshToken: string): Promise<TokenPair | null> {\n if (!config) return null;\n\n try {\n const response = await fetch(`${config.ssoBaseUrl}/api/auth/refresh`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ refreshToken }),\n });\n\n if (!response.ok) {\n clearTokens();\n config.onAuthError?.(new Error('Token refresh failed'));\n return null;\n }\n\n const data = await response.json();\n const tokens: TokenPair = {\n accessToken: data.accessToken || data.access_token,\n refreshToken: data.refreshToken || data.refresh_token,\n expiresIn: data.expiresIn || data.expires_in,\n tokenType: data.tokenType || data.token_type || 'Bearer',\n };\n\n setTokens(tokens.accessToken, tokens.refreshToken);\n config.onTokenRefresh?.(tokens);\n\n return tokens;\n } catch (error) {\n clearTokens();\n config.onAuthError?.(error instanceof Error ? error : new Error('Token refresh failed'));\n return null;\n }\n}\n\n/**\n * Get a valid access token, refreshing if necessary\n */\nexport async function getValidAccessToken(): Promise<string | null> {\n const token = getAccessToken();\n \n if (token && !isTokenExpired(token)) {\n return token;\n }\n\n const refreshed = await refreshTokens();\n return refreshed?.accessToken ?? null;\n}\n\n/**\n * Cancel any pending proactive refresh timer\n */\nexport function cancelProactiveRefresh(): void {\n if (proactiveRefreshTimer !== null) {\n clearTimeout(proactiveRefreshTimer);\n proactiveRefreshTimer = null;\n }\n}\n\n/**\n * Schedule a proactive token refresh ~30 seconds before expiry.\n * Calls `onRefreshed` with the new token pair on success so the\n * AuthProvider can update React state without a re-mount.\n */\nexport function scheduleProactiveRefresh(\n onRefreshed?: (tokens: TokenPair) => void,\n onFailed?: () => void,\n): void {\n cancelProactiveRefresh();\n\n const expiry = getTokenExpiry();\n if (!expiry) return;\n\n const now = Math.floor(Date.now() / 1000);\n const delaySeconds = expiry - now - PROACTIVE_REFRESH_BUFFER_SECONDS;\n\n // If already past the proactive window, don't schedule (the normal\n // isTokenExpired / 401 fallback will handle it)\n if (delaySeconds <= 0) return;\n\n proactiveRefreshTimer = setTimeout(async () => {\n proactiveRefreshTimer = null;\n const tokens = await refreshTokens();\n if (tokens) {\n // Re-schedule for the next cycle\n scheduleProactiveRefresh(onRefreshed, onFailed);\n onRefreshed?.(tokens);\n } else {\n onFailed?.();\n }\n }, delaySeconds * 1000);\n}\n","import type { AxiosInstance, InternalAxiosRequestConfig, AxiosResponse, AxiosError } from 'axios';\nimport { getAccessToken, getValidAccessToken, clearTokens } from './tokenManager';\nimport type { AuthConfig } from './types';\n\ninterface QueuedRequest {\n resolve: (token: string | null) => void;\n reject: (error: Error) => void;\n}\n\nlet isRefreshing = false;\nlet requestQueue: QueuedRequest[] = [];\n\n/**\n * Process queued requests after token refresh\n */\nfunction processQueue(token: string | null, error: Error | null = null): void {\n requestQueue.forEach((request) => {\n if (error) {\n request.reject(error);\n } else {\n request.resolve(token);\n }\n });\n requestQueue = [];\n}\n\n/**\n * Create and configure axios instance with auth interceptors\n */\nexport function createAuthClient(\n axiosInstance: AxiosInstance,\n config: AuthConfig\n): AxiosInstance {\n // Request interceptor - attach Bearer token\n axiosInstance.interceptors.request.use(\n async (requestConfig: InternalAxiosRequestConfig): Promise<InternalAxiosRequestConfig> => {\n // Skip auth for refresh endpoint to avoid infinite loop\n if (requestConfig.url?.includes('/api/auth/refresh')) {\n return requestConfig;\n }\n\n const token = getAccessToken();\n if (token) {\n requestConfig.headers = requestConfig.headers || {};\n requestConfig.headers.Authorization = `Bearer ${token}`;\n }\n return requestConfig;\n },\n (error: unknown) => Promise.reject(error)\n );\n\n // Response interceptor - handle 401 and refresh token\n axiosInstance.interceptors.response.use(\n (response: AxiosResponse) => response,\n async (error: AxiosError): Promise<AxiosResponse> => {\n const originalRequest = error.config as InternalAxiosRequestConfig & {\n _retry?: boolean;\n };\n\n // Only handle 401 errors\n if (error.response?.status !== 401) {\n return Promise.reject(error);\n }\n\n // Don't retry if already retried or no config\n if (originalRequest._retry || !originalRequest) {\n clearTokens();\n config.onAuthError?.(new Error('Authentication failed'));\n return Promise.reject(error);\n }\n\n // Don't retry refresh endpoint\n if (originalRequest.url?.includes('/api/auth/refresh')) {\n clearTokens();\n config.onAuthError?.(new Error('Token refresh failed'));\n return Promise.reject(error);\n }\n\n // If already refreshing, queue this request\n if (isRefreshing) {\n return new Promise((resolve, reject) => {\n requestQueue.push({\n resolve: (token) => {\n if (token) {\n originalRequest.headers = originalRequest.headers || {};\n originalRequest.headers.Authorization = `Bearer ${token}`;\n resolve(axiosInstance(originalRequest));\n } else {\n reject(new Error('Token refresh failed'));\n }\n },\n reject,\n });\n });\n }\n\n originalRequest._retry = true;\n isRefreshing = true;\n\n try {\n const token = await getValidAccessToken();\n \n if (!token) {\n processQueue(null, new Error('Token refresh failed'));\n clearTokens();\n config.onAuthError?.(new Error('Token refresh failed'));\n return Promise.reject(error);\n }\n\n processQueue(token);\n \n originalRequest.headers = originalRequest.headers || {};\n originalRequest.headers.Authorization = `Bearer ${token}`;\n \n return axiosInstance(originalRequest);\n } catch (refreshError) {\n processQueue(null, refreshError instanceof Error ? refreshError : new Error('Token refresh failed'));\n clearTokens();\n config.onAuthError?.(refreshError instanceof Error ? refreshError : new Error('Token refresh failed'));\n return Promise.reject(refreshError);\n } finally {\n isRefreshing = false;\n }\n }\n );\n\n return axiosInstance;\n}\n\n/**\n * Create a new axios instance with auth interceptors\n */\nexport function createApiClient(config: AuthConfig): AxiosInstance {\n // Dynamic import to avoid bundling axios if not used\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const axios = require('axios');\n \n const instance = axios.create({\n baseURL: config.apiBaseUrl,\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n return createAuthClient(instance, config);\n}\n","import React, { createContext, useEffect, useState, useCallback, useMemo } from 'react';\nimport type { User, AuthState, AuthContextValue, AuthProviderProps, TokenPair, AuthConfig } from './types';\nimport {\n initTokenManager,\n getAccessToken,\n setTokens,\n clearTokens,\n isTokenExpired,\n decodeJwt,\n getValidAccessToken,\n scheduleProactiveRefresh,\n cancelProactiveRefresh,\n} from './tokenManager';\n\n// Create context with undefined default\nexport const AuthContext = createContext<AuthContextValue | undefined>(undefined);\n\n/**\n * Parse user from JWT payload\n */\nfunction parseUserFromToken(token: string): User | null {\n const payload = decodeJwt(token);\n if (!payload) return null;\n\n return {\n id: payload.sub,\n email: payload.email,\n firstName: payload.given_name,\n lastName: payload.family_name,\n displayName: payload.name,\n avatarUrl: payload.picture,\n emailVerified: payload.email_verified ?? false,\n roles: payload.roles,\n permissions: payload.permissions,\n };\n}\n\n/**\n * Build the SSO authorization URL\n */\nfunction buildAuthUrl(\n ssoBaseUrl: string,\n clientId: string,\n redirectUri: string | undefined,\n scopes: string[] = ['openid', 'email', 'profile'],\n redirectPath?: string\n): string {\n const finalRedirectUri = redirectUri || `${window.location.origin}/callback`;\n \n // Store the original path to redirect back after login\n if (redirectPath) {\n sessionStorage.setItem('arowauth_redirect_path', redirectPath);\n }\n\n const params = new URLSearchParams({\n client_id: clientId,\n redirect_uri: finalRedirectUri,\n response_type: 'token',\n scope: scopes.join(' '),\n });\n\n return `${ssoBaseUrl}/oauth/authorize?${params.toString()}`;\n}\n\n/**\n * Parse tokens from URL hash fragment (SSO callback)\n */\nfunction parseTokensFromHash(): TokenPair | null {\n if (typeof window === 'undefined') return null;\n \n const hash = window.location.hash;\n if (!hash) return null;\n\n // Parse hash fragment: #access_token=xxx&refresh_token=yyy&...\n const params = new URLSearchParams(hash.substring(1));\n \n const accessToken = params.get('access_token') || params.get('token');\n const refreshToken = params.get('refresh_token');\n\n if (accessToken && refreshToken) {\n return {\n accessToken,\n refreshToken,\n expiresIn: params.get('expires_in') ? parseInt(params.get('expires_in')!, 10) : undefined,\n tokenType: params.get('token_type') || 'Bearer',\n };\n }\n\n return null;\n}\n\n/**\n * AuthProvider component - wraps app with auth context\n */\nexport function AuthProvider(props: AuthProviderProps): React.ReactElement {\n const { children, onTokenRefresh, onAuthError, onLogout, ...config } = props;\n\n const [state, setState] = useState<AuthState>({\n user: null,\n isAuthenticated: false,\n isLoading: true,\n error: null,\n });\n\n // Initialize token manager with config\n useEffect(() => {\n const fullConfig: AuthConfig = {\n ...config,\n onTokenRefresh,\n onAuthError: (error: Error) => {\n setState((prev: AuthState) => ({ ...prev, error: error.message }));\n onAuthError?.(error);\n },\n onLogout,\n };\n initTokenManager(fullConfig);\n }, [config.ssoBaseUrl, config.clientId, config.apiBaseUrl, onTokenRefresh, onAuthError, onLogout]);\n\n // Handle SSO callback and initial auth check\n useEffect(() => {\n const startProactive = () => {\n scheduleProactiveRefresh(\n (tokens) => {\n const user = parseUserFromToken(tokens.accessToken);\n setState((prev: AuthState) => ({ ...prev, user, isAuthenticated: true, error: null }));\n onTokenRefresh?.(tokens);\n },\n () => {\n setState({ user: null, isAuthenticated: false, isLoading: false, error: null });\n },\n );\n };\n\n const initAuth = async () => {\n try {\n // Check for tokens in URL hash (SSO callback)\n const hashTokens = parseTokensFromHash();\n if (hashTokens) {\n setTokens(hashTokens.accessToken, hashTokens.refreshToken);\n \n // Clean up URL\n window.history.replaceState(null, '', window.location.pathname + window.location.search);\n \n // Redirect to original path if stored\n const redirectPath = sessionStorage.getItem('arowauth_redirect_path');\n if (redirectPath) {\n sessionStorage.removeItem('arowauth_redirect_path');\n window.history.replaceState(null, '', redirectPath);\n }\n\n onTokenRefresh?.(hashTokens);\n startProactive();\n }\n\n // Check for existing valid token\n const token = getAccessToken();\n if (token && !isTokenExpired(token)) {\n const user = parseUserFromToken(token);\n setState({\n user,\n isAuthenticated: true,\n isLoading: false,\n error: null,\n });\n startProactive();\n return;\n }\n\n // Try to refresh if we have a token but it's expired\n if (token) {\n const newToken = await getValidAccessToken();\n if (newToken) {\n const user = parseUserFromToken(newToken);\n setState({\n user,\n isAuthenticated: true,\n isLoading: false,\n error: null,\n });\n startProactive();\n return;\n }\n }\n\n // No valid auth\n setState({\n user: null,\n isAuthenticated: false,\n isLoading: false,\n error: null,\n });\n } catch (error) {\n setState({\n user: null,\n isAuthenticated: false,\n isLoading: false,\n error: error instanceof Error ? error.message : 'Authentication error',\n });\n }\n };\n\n initAuth();\n\n return () => {\n cancelProactiveRefresh();\n };\n }, [onTokenRefresh]);\n\n // Login - redirect to SSO\n const login = useCallback((redirectPath?: string) => {\n const authUrl = buildAuthUrl(\n config.ssoBaseUrl,\n config.clientId,\n config.redirectUri,\n config.scopes,\n redirectPath || window.location.pathname\n );\n window.location.href = authUrl;\n }, [config.ssoBaseUrl, config.clientId, config.redirectUri, config.scopes]);\n\n // Logout - clear tokens and optionally call SSO logout\n const logout = useCallback(async () => {\n clearTokens();\n setState({\n user: null,\n isAuthenticated: false,\n isLoading: false,\n error: null,\n });\n onLogout?.();\n }, [onLogout]);\n\n // Refresh user data from token\n const refreshUser = useCallback(async () => {\n const token = await getValidAccessToken();\n if (token) {\n const user = parseUserFromToken(token);\n setState((prev: AuthState) => ({\n ...prev,\n user,\n isAuthenticated: true,\n error: null,\n }));\n } else {\n setState({\n user: null,\n isAuthenticated: false,\n isLoading: false,\n error: null,\n });\n }\n }, []);\n\n // Memoize context value\n const contextValue = useMemo<AuthContextValue>(\n () => ({\n ...state,\n login,\n logout,\n refreshUser,\n }),\n [state, login, logout, refreshUser]\n );\n\n return (\n <AuthContext.Provider value={contextValue}>\n {children}\n </AuthContext.Provider>\n );\n}\n","import { useContext } from 'react';\nimport { AuthContext } from '../AuthProvider';\nimport type { AuthContextValue, User } from '../types';\n\n/**\n * Hook to access auth state and actions\n * \n * @returns Auth context value with user, isAuthenticated, login, logout, etc.\n * @throws Error if used outside of AuthProvider\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * const { user, isAuthenticated, login, logout, isLoading } = useAuth();\n * \n * if (isLoading) return <div>Loading...</div>;\n * \n * if (!isAuthenticated) {\n * return <button onClick={() => login()}>Login</button>;\n * }\n * \n * return (\n * <div>\n * <p>Welcome, {user?.displayName || user?.email}!</p>\n * <button onClick={logout}>Logout</button>\n * </div>\n * );\n * }\n * ```\n */\nexport function useAuth(): AuthContextValue {\n const context = useContext(AuthContext);\n \n if (context === undefined) {\n throw new Error('useAuth must be used within an AuthProvider');\n }\n \n return context;\n}\n\n/**\n * Hook to check if user is authenticated (convenience wrapper)\n * \n * @returns Boolean indicating if user is authenticated\n */\nexport function useIsAuthenticated(): boolean {\n const { isAuthenticated } = useAuth();\n return isAuthenticated;\n}\n\n/**\n * Hook to get current user (convenience wrapper)\n * \n * @returns Current user or null\n */\nexport function useUser(): User | null {\n const { user } = useAuth();\n return user;\n}\n","import { useMemo, useContext } from 'react';\nimport type { AxiosInstance, InternalAxiosRequestConfig, AxiosResponse, AxiosError } from 'axios';\nimport { AuthContext } from '../AuthProvider';\nimport { getAccessToken, getValidAccessToken, clearTokens } from '../tokenManager';\n\ninterface QueuedRequest {\n resolve: (token: string | null) => void;\n reject: (error: Error) => void;\n}\n\n/**\n * Hook to get a configured axios instance with auth interceptors\n * \n * The returned axios instance will:\n * - Automatically attach Bearer token to requests\n * - Handle 401 responses by refreshing tokens and retrying\n * - Queue concurrent requests during token refresh\n * \n * @returns Configured axios instance\n * @throws Error if used outside of AuthProvider\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * const client = useAuthClient();\n * \n * const fetchData = async () => {\n * try {\n * const response = await client.get('/api/data');\n * console.log(response.data);\n * } catch (error) {\n * console.error('Failed to fetch data', error);\n * }\n * };\n * \n * return <button onClick={fetchData}>Fetch Data</button>;\n * }\n * ```\n */\nexport function useAuthClient(): AxiosInstance {\n const context = useContext(AuthContext);\n \n if (context === undefined) {\n throw new Error('useAuthClient must be used within an AuthProvider');\n }\n\n const client = useMemo(() => {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const axios = require('axios');\n \n const instance: AxiosInstance = axios.create({\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n let isRefreshing = false;\n let requestQueue: QueuedRequest[] = [];\n\n const processQueue = (token: string | null, error: Error | null = null): void => {\n requestQueue.forEach((req) => {\n if (error) {\n req.reject(error);\n } else {\n req.resolve(token);\n }\n });\n requestQueue = [];\n };\n\n // Request interceptor\n instance.interceptors.request.use(\n async (config: InternalAxiosRequestConfig): Promise<InternalAxiosRequestConfig> => {\n if (config.url?.includes('/api/auth/refresh')) {\n return config;\n }\n const token = getAccessToken();\n if (token) {\n config.headers = config.headers || {};\n config.headers.Authorization = `Bearer ${token}`;\n }\n return config;\n },\n (error: unknown) => Promise.reject(error)\n );\n\n // Response interceptor\n instance.interceptors.response.use(\n (response: AxiosResponse) => response,\n async (error: AxiosError): Promise<AxiosResponse> => {\n const originalRequest = error.config as InternalAxiosRequestConfig & {\n _retry?: boolean;\n };\n\n if (error.response?.status !== 401 || originalRequest._retry) {\n return Promise.reject(error);\n }\n\n if (originalRequest.url?.includes('/api/auth/refresh')) {\n clearTokens();\n return Promise.reject(error);\n }\n\n if (isRefreshing) {\n return new Promise((resolve, reject) => {\n requestQueue.push({\n resolve: (token) => {\n if (token) {\n originalRequest.headers = originalRequest.headers || {};\n originalRequest.headers.Authorization = `Bearer ${token}`;\n resolve(instance(originalRequest));\n } else {\n reject(new Error('Token refresh failed'));\n }\n },\n reject,\n });\n });\n }\n\n originalRequest._retry = true;\n isRefreshing = true;\n\n try {\n const token = await getValidAccessToken();\n if (!token) {\n processQueue(null, new Error('Token refresh failed'));\n clearTokens();\n return Promise.reject(error);\n }\n\n processQueue(token);\n originalRequest.headers = originalRequest.headers || {};\n originalRequest.headers.Authorization = `Bearer ${token}`;\n return instance(originalRequest);\n } catch (refreshError) {\n processQueue(null, refreshError instanceof Error ? refreshError : new Error('Refresh failed'));\n clearTokens();\n return Promise.reject(refreshError);\n } finally {\n isRefreshing = false;\n }\n }\n );\n\n return instance;\n }, []);\n\n return client;\n}\n"]}
package/dist/index.mjs CHANGED
@@ -12,10 +12,13 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
12
12
  var DEFAULT_STORAGE_PREFIX = "arowauth";
13
13
  var ACCESS_TOKEN_KEY = "access_token";
14
14
  var REFRESH_TOKEN_KEY = "refresh_token";
15
+ var TOKEN_EXPIRY_KEY = "token_expiry";
15
16
  var EXPIRY_BUFFER_SECONDS = 300;
17
+ var PROACTIVE_REFRESH_BUFFER_SECONDS = 30;
16
18
  var config = null;
17
19
  var isRefreshing = false;
18
20
  var refreshPromise = null;
21
+ var proactiveRefreshTimer = null;
19
22
  function initTokenManager(authConfig) {
20
23
  config = authConfig;
21
24
  }
@@ -59,15 +62,25 @@ function getAccessToken() {
59
62
  function getRefreshToken() {
60
63
  return getStorage().getItem(getKey(REFRESH_TOKEN_KEY));
61
64
  }
65
+ function getTokenExpiry() {
66
+ const expiry = getStorage().getItem(getKey(TOKEN_EXPIRY_KEY));
67
+ return expiry ? parseInt(expiry, 10) : null;
68
+ }
62
69
  function setTokens(accessToken, refreshToken) {
63
70
  const storage = getStorage();
64
71
  storage.setItem(getKey(ACCESS_TOKEN_KEY), accessToken);
65
72
  storage.setItem(getKey(REFRESH_TOKEN_KEY), refreshToken);
73
+ const payload = decodeJwt(accessToken);
74
+ if (payload?.exp) {
75
+ storage.setItem(getKey(TOKEN_EXPIRY_KEY), String(payload.exp));
76
+ }
66
77
  }
67
78
  function clearTokens() {
68
79
  const storage = getStorage();
69
80
  storage.removeItem(getKey(ACCESS_TOKEN_KEY));
70
81
  storage.removeItem(getKey(REFRESH_TOKEN_KEY));
82
+ storage.removeItem(getKey(TOKEN_EXPIRY_KEY));
83
+ cancelProactiveRefresh();
71
84
  }
72
85
  function isTokenExpired(token) {
73
86
  const accessToken = token ?? getAccessToken();
@@ -147,6 +160,30 @@ async function getValidAccessToken() {
147
160
  const refreshed = await refreshTokens();
148
161
  return refreshed?.accessToken ?? null;
149
162
  }
163
+ function cancelProactiveRefresh() {
164
+ if (proactiveRefreshTimer !== null) {
165
+ clearTimeout(proactiveRefreshTimer);
166
+ proactiveRefreshTimer = null;
167
+ }
168
+ }
169
+ function scheduleProactiveRefresh(onRefreshed, onFailed) {
170
+ cancelProactiveRefresh();
171
+ const expiry = getTokenExpiry();
172
+ if (!expiry) return;
173
+ const now = Math.floor(Date.now() / 1e3);
174
+ const delaySeconds = expiry - now - PROACTIVE_REFRESH_BUFFER_SECONDS;
175
+ if (delaySeconds <= 0) return;
176
+ proactiveRefreshTimer = setTimeout(async () => {
177
+ proactiveRefreshTimer = null;
178
+ const tokens = await refreshTokens();
179
+ if (tokens) {
180
+ scheduleProactiveRefresh(onRefreshed, onFailed);
181
+ onRefreshed?.(tokens);
182
+ } else {
183
+ onFailed?.();
184
+ }
185
+ }, delaySeconds * 1e3);
186
+ }
150
187
 
151
188
  // src/apiInterceptor.ts
152
189
  var isRefreshing2 = false;
@@ -312,6 +349,18 @@ function AuthProvider(props) {
312
349
  initTokenManager(fullConfig);
313
350
  }, [config2.ssoBaseUrl, config2.clientId, config2.apiBaseUrl, onTokenRefresh, onAuthError, onLogout]);
314
351
  useEffect(() => {
352
+ const startProactive = () => {
353
+ scheduleProactiveRefresh(
354
+ (tokens) => {
355
+ const user = parseUserFromToken(tokens.accessToken);
356
+ setState((prev) => ({ ...prev, user, isAuthenticated: true, error: null }));
357
+ onTokenRefresh?.(tokens);
358
+ },
359
+ () => {
360
+ setState({ user: null, isAuthenticated: false, isLoading: false, error: null });
361
+ }
362
+ );
363
+ };
315
364
  const initAuth = async () => {
316
365
  try {
317
366
  const hashTokens = parseTokensFromHash();
@@ -324,6 +373,7 @@ function AuthProvider(props) {
324
373
  window.history.replaceState(null, "", redirectPath);
325
374
  }
326
375
  onTokenRefresh?.(hashTokens);
376
+ startProactive();
327
377
  }
328
378
  const token = getAccessToken();
329
379
  if (token && !isTokenExpired(token)) {
@@ -334,6 +384,7 @@ function AuthProvider(props) {
334
384
  isLoading: false,
335
385
  error: null
336
386
  });
387
+ startProactive();
337
388
  return;
338
389
  }
339
390
  if (token) {
@@ -346,6 +397,7 @@ function AuthProvider(props) {
346
397
  isLoading: false,
347
398
  error: null
348
399
  });
400
+ startProactive();
349
401
  return;
350
402
  }
351
403
  }
@@ -365,6 +417,9 @@ function AuthProvider(props) {
365
417
  }
366
418
  };
367
419
  initAuth();
420
+ return () => {
421
+ cancelProactiveRefresh();
422
+ };
368
423
  }, [onTokenRefresh]);
369
424
  const login = useCallback((redirectPath) => {
370
425
  const authUrl = buildAuthUrl(
@@ -523,6 +578,6 @@ function useAuthClient() {
523
578
  return client;
524
579
  }
525
580
 
526
- export { AuthContext, AuthProvider, clearTokens, createApiClient, createAuthClient, decodeJwt, getAccessToken, getRefreshToken, getUserFromToken, getValidAccessToken, hasValidToken, initTokenManager, isTokenExpired, refreshTokens, setTokens, useAuth, useAuthClient, useIsAuthenticated, useUser };
581
+ export { AuthContext, AuthProvider, cancelProactiveRefresh, clearTokens, createApiClient, createAuthClient, decodeJwt, getAccessToken, getRefreshToken, getTokenExpiry, getUserFromToken, getValidAccessToken, hasValidToken, initTokenManager, isTokenExpired, refreshTokens, scheduleProactiveRefresh, setTokens, useAuth, useAuthClient, useIsAuthenticated, useUser };
527
582
  //# sourceMappingURL=index.mjs.map
528
583
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/tokenManager.ts","../src/apiInterceptor.ts","../src/AuthProvider.tsx","../src/hooks/useAuth.ts","../src/hooks/useAuthClient.ts"],"names":["isRefreshing","config","useContext","useMemo","requestQueue","processQueue"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { JwtPayload, TokenPair, AuthConfig } from './types';\n\nconst DEFAULT_STORAGE_PREFIX = 'arowauth';\nconst ACCESS_TOKEN_KEY = 'access_token';\nconst REFRESH_TOKEN_KEY = 'refresh_token';\n\n// Buffer time before expiry to trigger refresh (5 minutes)\nconst EXPIRY_BUFFER_SECONDS = 300;\n\nlet config: AuthConfig | null = null;\nlet isRefreshing = false;\nlet refreshPromise: Promise<TokenPair | null> | null = null;\n\n/**\n * Initialize token manager with configuration\n */\nexport function initTokenManager(authConfig: AuthConfig): void {\n config = authConfig;\n}\n\n/**\n * Get the storage instance (localStorage or sessionStorage)\n */\nfunction getStorage(): Storage {\n if (typeof window === 'undefined') {\n // SSR fallback - return a no-op storage\n return {\n getItem: () => null,\n setItem: () => {},\n removeItem: () => {},\n clear: () => {},\n key: () => null,\n length: 0,\n };\n }\n return config?.useSessionStorage ? sessionStorage : localStorage;\n}\n\n/**\n * Get storage key with prefix\n */\nfunction getKey(key: string): string {\n const prefix = config?.storagePrefix || DEFAULT_STORAGE_PREFIX;\n return `${prefix}_${key}`;\n}\n\n/**\n * Decode a JWT token without verification\n */\nexport function decodeJwt(token: string): JwtPayload | null {\n try {\n const parts = token.split('.');\n if (parts.length !== 3) return null;\n \n const payload = parts[1];\n // Handle URL-safe base64\n const base64 = payload.replace(/-/g, '+').replace(/_/g, '/');\n const jsonPayload = decodeURIComponent(\n atob(base64)\n .split('')\n .map((c) => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2))\n .join('')\n );\n \n return JSON.parse(jsonPayload) as JwtPayload;\n } catch {\n return null;\n }\n}\n\n/**\n * Get the access token from storage\n */\nexport function getAccessToken(): string | null {\n return getStorage().getItem(getKey(ACCESS_TOKEN_KEY));\n}\n\n/**\n * Get the refresh token from storage\n */\nexport function getRefreshToken(): string | null {\n return getStorage().getItem(getKey(REFRESH_TOKEN_KEY));\n}\n\n/**\n * Store tokens in storage\n */\nexport function setTokens(accessToken: string, refreshToken: string): void {\n const storage = getStorage();\n storage.setItem(getKey(ACCESS_TOKEN_KEY), accessToken);\n storage.setItem(getKey(REFRESH_TOKEN_KEY), refreshToken);\n}\n\n/**\n * Clear all tokens from storage\n */\nexport function clearTokens(): void {\n const storage = getStorage();\n storage.removeItem(getKey(ACCESS_TOKEN_KEY));\n storage.removeItem(getKey(REFRESH_TOKEN_KEY));\n}\n\n/**\n * Check if the access token is expired or about to expire\n */\nexport function isTokenExpired(token?: string | null): boolean {\n const accessToken = token ?? getAccessToken();\n if (!accessToken) return true;\n \n const payload = decodeJwt(accessToken);\n if (!payload || !payload.exp) return true;\n \n // Check if token expires within buffer period\n const now = Math.floor(Date.now() / 1000);\n return payload.exp <= now + EXPIRY_BUFFER_SECONDS;\n}\n\n/**\n * Check if we have a valid (non-expired) access token\n */\nexport function hasValidToken(): boolean {\n const token = getAccessToken();\n return token !== null && !isTokenExpired(token);\n}\n\n/**\n * Get user info from the current access token\n */\nexport function getUserFromToken(): JwtPayload | null {\n const token = getAccessToken();\n if (!token) return null;\n return decodeJwt(token);\n}\n\n/**\n * Refresh tokens using the refresh token\n * Handles concurrent refresh requests by returning the same promise\n */\nexport async function refreshTokens(): Promise<TokenPair | null> {\n if (!config) {\n throw new Error('TokenManager not initialized. Call initTokenManager first.');\n }\n\n const refreshToken = getRefreshToken();\n if (!refreshToken) {\n clearTokens();\n return null;\n }\n\n // If already refreshing, return the existing promise\n if (isRefreshing && refreshPromise) {\n return refreshPromise;\n }\n\n isRefreshing = true;\n refreshPromise = performRefresh(refreshToken);\n\n try {\n const result = await refreshPromise;\n return result;\n } finally {\n isRefreshing = false;\n refreshPromise = null;\n }\n}\n\n/**\n * Perform the actual token refresh request\n */\nasync function performRefresh(refreshToken: string): Promise<TokenPair | null> {\n if (!config) return null;\n\n try {\n const response = await fetch(`${config.ssoBaseUrl}/api/auth/refresh`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ refreshToken }),\n });\n\n if (!response.ok) {\n clearTokens();\n config.onAuthError?.(new Error('Token refresh failed'));\n return null;\n }\n\n const data = await response.json();\n const tokens: TokenPair = {\n accessToken: data.accessToken || data.access_token,\n refreshToken: data.refreshToken || data.refresh_token,\n expiresIn: data.expiresIn || data.expires_in,\n tokenType: data.tokenType || data.token_type || 'Bearer',\n };\n\n setTokens(tokens.accessToken, tokens.refreshToken);\n config.onTokenRefresh?.(tokens);\n\n return tokens;\n } catch (error) {\n clearTokens();\n config.onAuthError?.(error instanceof Error ? error : new Error('Token refresh failed'));\n return null;\n }\n}\n\n/**\n * Get a valid access token, refreshing if necessary\n */\nexport async function getValidAccessToken(): Promise<string | null> {\n const token = getAccessToken();\n \n if (token && !isTokenExpired(token)) {\n return token;\n }\n\n const refreshed = await refreshTokens();\n return refreshed?.accessToken ?? null;\n}\n","import type { AxiosInstance, InternalAxiosRequestConfig, AxiosResponse, AxiosError } from 'axios';\nimport { getAccessToken, getValidAccessToken, clearTokens } from './tokenManager';\nimport type { AuthConfig } from './types';\n\ninterface QueuedRequest {\n resolve: (token: string | null) => void;\n reject: (error: Error) => void;\n}\n\nlet isRefreshing = false;\nlet requestQueue: QueuedRequest[] = [];\n\n/**\n * Process queued requests after token refresh\n */\nfunction processQueue(token: string | null, error: Error | null = null): void {\n requestQueue.forEach((request) => {\n if (error) {\n request.reject(error);\n } else {\n request.resolve(token);\n }\n });\n requestQueue = [];\n}\n\n/**\n * Create and configure axios instance with auth interceptors\n */\nexport function createAuthClient(\n axiosInstance: AxiosInstance,\n config: AuthConfig\n): AxiosInstance {\n // Request interceptor - attach Bearer token\n axiosInstance.interceptors.request.use(\n async (requestConfig: InternalAxiosRequestConfig): Promise<InternalAxiosRequestConfig> => {\n // Skip auth for refresh endpoint to avoid infinite loop\n if (requestConfig.url?.includes('/api/auth/refresh')) {\n return requestConfig;\n }\n\n const token = getAccessToken();\n if (token) {\n requestConfig.headers = requestConfig.headers || {};\n requestConfig.headers.Authorization = `Bearer ${token}`;\n }\n return requestConfig;\n },\n (error: unknown) => Promise.reject(error)\n );\n\n // Response interceptor - handle 401 and refresh token\n axiosInstance.interceptors.response.use(\n (response: AxiosResponse) => response,\n async (error: AxiosError): Promise<AxiosResponse> => {\n const originalRequest = error.config as InternalAxiosRequestConfig & {\n _retry?: boolean;\n };\n\n // Only handle 401 errors\n if (error.response?.status !== 401) {\n return Promise.reject(error);\n }\n\n // Don't retry if already retried or no config\n if (originalRequest._retry || !originalRequest) {\n clearTokens();\n config.onAuthError?.(new Error('Authentication failed'));\n return Promise.reject(error);\n }\n\n // Don't retry refresh endpoint\n if (originalRequest.url?.includes('/api/auth/refresh')) {\n clearTokens();\n config.onAuthError?.(new Error('Token refresh failed'));\n return Promise.reject(error);\n }\n\n // If already refreshing, queue this request\n if (isRefreshing) {\n return new Promise((resolve, reject) => {\n requestQueue.push({\n resolve: (token) => {\n if (token) {\n originalRequest.headers = originalRequest.headers || {};\n originalRequest.headers.Authorization = `Bearer ${token}`;\n resolve(axiosInstance(originalRequest));\n } else {\n reject(new Error('Token refresh failed'));\n }\n },\n reject,\n });\n });\n }\n\n originalRequest._retry = true;\n isRefreshing = true;\n\n try {\n const token = await getValidAccessToken();\n \n if (!token) {\n processQueue(null, new Error('Token refresh failed'));\n clearTokens();\n config.onAuthError?.(new Error('Token refresh failed'));\n return Promise.reject(error);\n }\n\n processQueue(token);\n \n originalRequest.headers = originalRequest.headers || {};\n originalRequest.headers.Authorization = `Bearer ${token}`;\n \n return axiosInstance(originalRequest);\n } catch (refreshError) {\n processQueue(null, refreshError instanceof Error ? refreshError : new Error('Token refresh failed'));\n clearTokens();\n config.onAuthError?.(refreshError instanceof Error ? refreshError : new Error('Token refresh failed'));\n return Promise.reject(refreshError);\n } finally {\n isRefreshing = false;\n }\n }\n );\n\n return axiosInstance;\n}\n\n/**\n * Create a new axios instance with auth interceptors\n */\nexport function createApiClient(config: AuthConfig): AxiosInstance {\n // Dynamic import to avoid bundling axios if not used\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const axios = require('axios');\n \n const instance = axios.create({\n baseURL: config.apiBaseUrl,\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n return createAuthClient(instance, config);\n}\n","import React, { createContext, useEffect, useState, useCallback, useMemo } from 'react';\nimport type { User, AuthState, AuthContextValue, AuthProviderProps, TokenPair, AuthConfig } from './types';\nimport {\n initTokenManager,\n getAccessToken,\n setTokens,\n clearTokens,\n isTokenExpired,\n decodeJwt,\n getValidAccessToken,\n} from './tokenManager';\n\n// Create context with undefined default\nexport const AuthContext = createContext<AuthContextValue | undefined>(undefined);\n\n/**\n * Parse user from JWT payload\n */\nfunction parseUserFromToken(token: string): User | null {\n const payload = decodeJwt(token);\n if (!payload) return null;\n\n return {\n id: payload.sub,\n email: payload.email,\n firstName: payload.given_name,\n lastName: payload.family_name,\n displayName: payload.name,\n avatarUrl: payload.picture,\n emailVerified: payload.email_verified ?? false,\n roles: payload.roles,\n permissions: payload.permissions,\n };\n}\n\n/**\n * Build the SSO authorization URL\n */\nfunction buildAuthUrl(\n ssoBaseUrl: string,\n clientId: string,\n redirectUri: string | undefined,\n scopes: string[] = ['openid', 'email', 'profile'],\n redirectPath?: string\n): string {\n const finalRedirectUri = redirectUri || `${window.location.origin}/callback`;\n \n // Store the original path to redirect back after login\n if (redirectPath) {\n sessionStorage.setItem('arowauth_redirect_path', redirectPath);\n }\n\n const params = new URLSearchParams({\n client_id: clientId,\n redirect_uri: finalRedirectUri,\n response_type: 'token',\n scope: scopes.join(' '),\n });\n\n return `${ssoBaseUrl}/oauth/authorize?${params.toString()}`;\n}\n\n/**\n * Parse tokens from URL hash fragment (SSO callback)\n */\nfunction parseTokensFromHash(): TokenPair | null {\n if (typeof window === 'undefined') return null;\n \n const hash = window.location.hash;\n if (!hash) return null;\n\n // Parse hash fragment: #access_token=xxx&refresh_token=yyy&...\n const params = new URLSearchParams(hash.substring(1));\n \n const accessToken = params.get('access_token') || params.get('token');\n const refreshToken = params.get('refresh_token');\n\n if (accessToken && refreshToken) {\n return {\n accessToken,\n refreshToken,\n expiresIn: params.get('expires_in') ? parseInt(params.get('expires_in')!, 10) : undefined,\n tokenType: params.get('token_type') || 'Bearer',\n };\n }\n\n return null;\n}\n\n/**\n * AuthProvider component - wraps app with auth context\n */\nexport function AuthProvider(props: AuthProviderProps): React.ReactElement {\n const { children, onTokenRefresh, onAuthError, onLogout, ...config } = props;\n\n const [state, setState] = useState<AuthState>({\n user: null,\n isAuthenticated: false,\n isLoading: true,\n error: null,\n });\n\n // Initialize token manager with config\n useEffect(() => {\n const fullConfig: AuthConfig = {\n ...config,\n onTokenRefresh,\n onAuthError: (error: Error) => {\n setState((prev: AuthState) => ({ ...prev, error: error.message }));\n onAuthError?.(error);\n },\n onLogout,\n };\n initTokenManager(fullConfig);\n }, [config.ssoBaseUrl, config.clientId, config.apiBaseUrl, onTokenRefresh, onAuthError, onLogout]);\n\n // Handle SSO callback and initial auth check\n useEffect(() => {\n const initAuth = async () => {\n try {\n // Check for tokens in URL hash (SSO callback)\n const hashTokens = parseTokensFromHash();\n if (hashTokens) {\n setTokens(hashTokens.accessToken, hashTokens.refreshToken);\n \n // Clean up URL\n window.history.replaceState(null, '', window.location.pathname + window.location.search);\n \n // Redirect to original path if stored\n const redirectPath = sessionStorage.getItem('arowauth_redirect_path');\n if (redirectPath) {\n sessionStorage.removeItem('arowauth_redirect_path');\n window.history.replaceState(null, '', redirectPath);\n }\n\n onTokenRefresh?.(hashTokens);\n }\n\n // Check for existing valid token\n const token = getAccessToken();\n if (token && !isTokenExpired(token)) {\n const user = parseUserFromToken(token);\n setState({\n user,\n isAuthenticated: true,\n isLoading: false,\n error: null,\n });\n return;\n }\n\n // Try to refresh if we have a token but it's expired\n if (token) {\n const newToken = await getValidAccessToken();\n if (newToken) {\n const user = parseUserFromToken(newToken);\n setState({\n user,\n isAuthenticated: true,\n isLoading: false,\n error: null,\n });\n return;\n }\n }\n\n // No valid auth\n setState({\n user: null,\n isAuthenticated: false,\n isLoading: false,\n error: null,\n });\n } catch (error) {\n setState({\n user: null,\n isAuthenticated: false,\n isLoading: false,\n error: error instanceof Error ? error.message : 'Authentication error',\n });\n }\n };\n\n initAuth();\n }, [onTokenRefresh]);\n\n // Login - redirect to SSO\n const login = useCallback((redirectPath?: string) => {\n const authUrl = buildAuthUrl(\n config.ssoBaseUrl,\n config.clientId,\n config.redirectUri,\n config.scopes,\n redirectPath || window.location.pathname\n );\n window.location.href = authUrl;\n }, [config.ssoBaseUrl, config.clientId, config.redirectUri, config.scopes]);\n\n // Logout - clear tokens and optionally call SSO logout\n const logout = useCallback(async () => {\n clearTokens();\n setState({\n user: null,\n isAuthenticated: false,\n isLoading: false,\n error: null,\n });\n onLogout?.();\n }, [onLogout]);\n\n // Refresh user data from token\n const refreshUser = useCallback(async () => {\n const token = await getValidAccessToken();\n if (token) {\n const user = parseUserFromToken(token);\n setState((prev: AuthState) => ({\n ...prev,\n user,\n isAuthenticated: true,\n error: null,\n }));\n } else {\n setState({\n user: null,\n isAuthenticated: false,\n isLoading: false,\n error: null,\n });\n }\n }, []);\n\n // Memoize context value\n const contextValue = useMemo<AuthContextValue>(\n () => ({\n ...state,\n login,\n logout,\n refreshUser,\n }),\n [state, login, logout, refreshUser]\n );\n\n return (\n <AuthContext.Provider value={contextValue}>\n {children}\n </AuthContext.Provider>\n );\n}\n","import { useContext } from 'react';\nimport { AuthContext } from '../AuthProvider';\nimport type { AuthContextValue, User } from '../types';\n\n/**\n * Hook to access auth state and actions\n * \n * @returns Auth context value with user, isAuthenticated, login, logout, etc.\n * @throws Error if used outside of AuthProvider\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * const { user, isAuthenticated, login, logout, isLoading } = useAuth();\n * \n * if (isLoading) return <div>Loading...</div>;\n * \n * if (!isAuthenticated) {\n * return <button onClick={() => login()}>Login</button>;\n * }\n * \n * return (\n * <div>\n * <p>Welcome, {user?.displayName || user?.email}!</p>\n * <button onClick={logout}>Logout</button>\n * </div>\n * );\n * }\n * ```\n */\nexport function useAuth(): AuthContextValue {\n const context = useContext(AuthContext);\n \n if (context === undefined) {\n throw new Error('useAuth must be used within an AuthProvider');\n }\n \n return context;\n}\n\n/**\n * Hook to check if user is authenticated (convenience wrapper)\n * \n * @returns Boolean indicating if user is authenticated\n */\nexport function useIsAuthenticated(): boolean {\n const { isAuthenticated } = useAuth();\n return isAuthenticated;\n}\n\n/**\n * Hook to get current user (convenience wrapper)\n * \n * @returns Current user or null\n */\nexport function useUser(): User | null {\n const { user } = useAuth();\n return user;\n}\n","import { useMemo, useContext } from 'react';\nimport type { AxiosInstance, InternalAxiosRequestConfig, AxiosResponse, AxiosError } from 'axios';\nimport { AuthContext } from '../AuthProvider';\nimport { getAccessToken, getValidAccessToken, clearTokens } from '../tokenManager';\n\ninterface QueuedRequest {\n resolve: (token: string | null) => void;\n reject: (error: Error) => void;\n}\n\n/**\n * Hook to get a configured axios instance with auth interceptors\n * \n * The returned axios instance will:\n * - Automatically attach Bearer token to requests\n * - Handle 401 responses by refreshing tokens and retrying\n * - Queue concurrent requests during token refresh\n * \n * @returns Configured axios instance\n * @throws Error if used outside of AuthProvider\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * const client = useAuthClient();\n * \n * const fetchData = async () => {\n * try {\n * const response = await client.get('/api/data');\n * console.log(response.data);\n * } catch (error) {\n * console.error('Failed to fetch data', error);\n * }\n * };\n * \n * return <button onClick={fetchData}>Fetch Data</button>;\n * }\n * ```\n */\nexport function useAuthClient(): AxiosInstance {\n const context = useContext(AuthContext);\n \n if (context === undefined) {\n throw new Error('useAuthClient must be used within an AuthProvider');\n }\n\n const client = useMemo(() => {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const axios = require('axios');\n \n const instance: AxiosInstance = axios.create({\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n let isRefreshing = false;\n let requestQueue: QueuedRequest[] = [];\n\n const processQueue = (token: string | null, error: Error | null = null): void => {\n requestQueue.forEach((req) => {\n if (error) {\n req.reject(error);\n } else {\n req.resolve(token);\n }\n });\n requestQueue = [];\n };\n\n // Request interceptor\n instance.interceptors.request.use(\n async (config: InternalAxiosRequestConfig): Promise<InternalAxiosRequestConfig> => {\n if (config.url?.includes('/api/auth/refresh')) {\n return config;\n }\n const token = getAccessToken();\n if (token) {\n config.headers = config.headers || {};\n config.headers.Authorization = `Bearer ${token}`;\n }\n return config;\n },\n (error: unknown) => Promise.reject(error)\n );\n\n // Response interceptor\n instance.interceptors.response.use(\n (response: AxiosResponse) => response,\n async (error: AxiosError): Promise<AxiosResponse> => {\n const originalRequest = error.config as InternalAxiosRequestConfig & {\n _retry?: boolean;\n };\n\n if (error.response?.status !== 401 || originalRequest._retry) {\n return Promise.reject(error);\n }\n\n if (originalRequest.url?.includes('/api/auth/refresh')) {\n clearTokens();\n return Promise.reject(error);\n }\n\n if (isRefreshing) {\n return new Promise((resolve, reject) => {\n requestQueue.push({\n resolve: (token) => {\n if (token) {\n originalRequest.headers = originalRequest.headers || {};\n originalRequest.headers.Authorization = `Bearer ${token}`;\n resolve(instance(originalRequest));\n } else {\n reject(new Error('Token refresh failed'));\n }\n },\n reject,\n });\n });\n }\n\n originalRequest._retry = true;\n isRefreshing = true;\n\n try {\n const token = await getValidAccessToken();\n if (!token) {\n processQueue(null, new Error('Token refresh failed'));\n clearTokens();\n return Promise.reject(error);\n }\n\n processQueue(token);\n originalRequest.headers = originalRequest.headers || {};\n originalRequest.headers.Authorization = `Bearer ${token}`;\n return instance(originalRequest);\n } catch (refreshError) {\n processQueue(null, refreshError instanceof Error ? refreshError : new Error('Refresh failed'));\n clearTokens();\n return Promise.reject(refreshError);\n } finally {\n isRefreshing = false;\n }\n }\n );\n\n return instance;\n }, []);\n\n return client;\n}\n"]}
1
+ {"version":3,"sources":["../src/tokenManager.ts","../src/apiInterceptor.ts","../src/AuthProvider.tsx","../src/hooks/useAuth.ts","../src/hooks/useAuthClient.ts"],"names":["isRefreshing","config","useContext","useMemo","requestQueue","processQueue"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { JwtPayload, TokenPair, AuthConfig } from './types';\n\nconst DEFAULT_STORAGE_PREFIX = 'arowauth';\nconst ACCESS_TOKEN_KEY = 'access_token';\nconst REFRESH_TOKEN_KEY = 'refresh_token';\nconst TOKEN_EXPIRY_KEY = 'token_expiry';\n\n// Buffer time before expiry to trigger refresh (5 minutes for isTokenExpired checks)\nconst EXPIRY_BUFFER_SECONDS = 300;\n\n// Proactive refresh fires 30 seconds before expiry\nconst PROACTIVE_REFRESH_BUFFER_SECONDS = 30;\n\nlet config: AuthConfig | null = null;\nlet isRefreshing = false;\nlet refreshPromise: Promise<TokenPair | null> | null = null;\nlet proactiveRefreshTimer: ReturnType<typeof setTimeout> | null = null;\n\n/**\n * Initialize token manager with configuration\n */\nexport function initTokenManager(authConfig: AuthConfig): void {\n config = authConfig;\n}\n\n/**\n * Get the storage instance (localStorage or sessionStorage)\n */\nfunction getStorage(): Storage {\n if (typeof window === 'undefined') {\n // SSR fallback - return a no-op storage\n return {\n getItem: () => null,\n setItem: () => {},\n removeItem: () => {},\n clear: () => {},\n key: () => null,\n length: 0,\n };\n }\n return config?.useSessionStorage ? sessionStorage : localStorage;\n}\n\n/**\n * Get storage key with prefix\n */\nfunction getKey(key: string): string {\n const prefix = config?.storagePrefix || DEFAULT_STORAGE_PREFIX;\n return `${prefix}_${key}`;\n}\n\n/**\n * Decode a JWT token without verification\n */\nexport function decodeJwt(token: string): JwtPayload | null {\n try {\n const parts = token.split('.');\n if (parts.length !== 3) return null;\n \n const payload = parts[1];\n // Handle URL-safe base64\n const base64 = payload.replace(/-/g, '+').replace(/_/g, '/');\n const jsonPayload = decodeURIComponent(\n atob(base64)\n .split('')\n .map((c) => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2))\n .join('')\n );\n \n return JSON.parse(jsonPayload) as JwtPayload;\n } catch {\n return null;\n }\n}\n\n/**\n * Get the access token from storage\n */\nexport function getAccessToken(): string | null {\n return getStorage().getItem(getKey(ACCESS_TOKEN_KEY));\n}\n\n/**\n * Get the refresh token from storage\n */\nexport function getRefreshToken(): string | null {\n return getStorage().getItem(getKey(REFRESH_TOKEN_KEY));\n}\n\n/**\n * Get the stored token expiry timestamp (seconds since epoch)\n */\nexport function getTokenExpiry(): number | null {\n const expiry = getStorage().getItem(getKey(TOKEN_EXPIRY_KEY));\n return expiry ? parseInt(expiry, 10) : null;\n}\n\n/**\n * Store tokens in storage, including the expiry timestamp decoded from the JWT\n */\nexport function setTokens(accessToken: string, refreshToken: string): void {\n const storage = getStorage();\n storage.setItem(getKey(ACCESS_TOKEN_KEY), accessToken);\n storage.setItem(getKey(REFRESH_TOKEN_KEY), refreshToken);\n\n // Persist expiry from JWT exp claim\n const payload = decodeJwt(accessToken);\n if (payload?.exp) {\n storage.setItem(getKey(TOKEN_EXPIRY_KEY), String(payload.exp));\n }\n}\n\n/**\n * Clear all tokens from storage\n */\nexport function clearTokens(): void {\n const storage = getStorage();\n storage.removeItem(getKey(ACCESS_TOKEN_KEY));\n storage.removeItem(getKey(REFRESH_TOKEN_KEY));\n storage.removeItem(getKey(TOKEN_EXPIRY_KEY));\n cancelProactiveRefresh();\n}\n\n/**\n * Check if the access token is expired or about to expire\n */\nexport function isTokenExpired(token?: string | null): boolean {\n const accessToken = token ?? getAccessToken();\n if (!accessToken) return true;\n \n const payload = decodeJwt(accessToken);\n if (!payload || !payload.exp) return true;\n \n // Check if token expires within buffer period\n const now = Math.floor(Date.now() / 1000);\n return payload.exp <= now + EXPIRY_BUFFER_SECONDS;\n}\n\n/**\n * Check if we have a valid (non-expired) access token\n */\nexport function hasValidToken(): boolean {\n const token = getAccessToken();\n return token !== null && !isTokenExpired(token);\n}\n\n/**\n * Get user info from the current access token\n */\nexport function getUserFromToken(): JwtPayload | null {\n const token = getAccessToken();\n if (!token) return null;\n return decodeJwt(token);\n}\n\n/**\n * Refresh tokens using the refresh token\n * Handles concurrent refresh requests by returning the same promise\n */\nexport async function refreshTokens(): Promise<TokenPair | null> {\n if (!config) {\n throw new Error('TokenManager not initialized. Call initTokenManager first.');\n }\n\n const refreshToken = getRefreshToken();\n if (!refreshToken) {\n clearTokens();\n return null;\n }\n\n // If already refreshing, return the existing promise\n if (isRefreshing && refreshPromise) {\n return refreshPromise;\n }\n\n isRefreshing = true;\n refreshPromise = performRefresh(refreshToken);\n\n try {\n const result = await refreshPromise;\n return result;\n } finally {\n isRefreshing = false;\n refreshPromise = null;\n }\n}\n\n/**\n * Perform the actual token refresh request\n */\nasync function performRefresh(refreshToken: string): Promise<TokenPair | null> {\n if (!config) return null;\n\n try {\n const response = await fetch(`${config.ssoBaseUrl}/api/auth/refresh`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ refreshToken }),\n });\n\n if (!response.ok) {\n clearTokens();\n config.onAuthError?.(new Error('Token refresh failed'));\n return null;\n }\n\n const data = await response.json();\n const tokens: TokenPair = {\n accessToken: data.accessToken || data.access_token,\n refreshToken: data.refreshToken || data.refresh_token,\n expiresIn: data.expiresIn || data.expires_in,\n tokenType: data.tokenType || data.token_type || 'Bearer',\n };\n\n setTokens(tokens.accessToken, tokens.refreshToken);\n config.onTokenRefresh?.(tokens);\n\n return tokens;\n } catch (error) {\n clearTokens();\n config.onAuthError?.(error instanceof Error ? error : new Error('Token refresh failed'));\n return null;\n }\n}\n\n/**\n * Get a valid access token, refreshing if necessary\n */\nexport async function getValidAccessToken(): Promise<string | null> {\n const token = getAccessToken();\n \n if (token && !isTokenExpired(token)) {\n return token;\n }\n\n const refreshed = await refreshTokens();\n return refreshed?.accessToken ?? null;\n}\n\n/**\n * Cancel any pending proactive refresh timer\n */\nexport function cancelProactiveRefresh(): void {\n if (proactiveRefreshTimer !== null) {\n clearTimeout(proactiveRefreshTimer);\n proactiveRefreshTimer = null;\n }\n}\n\n/**\n * Schedule a proactive token refresh ~30 seconds before expiry.\n * Calls `onRefreshed` with the new token pair on success so the\n * AuthProvider can update React state without a re-mount.\n */\nexport function scheduleProactiveRefresh(\n onRefreshed?: (tokens: TokenPair) => void,\n onFailed?: () => void,\n): void {\n cancelProactiveRefresh();\n\n const expiry = getTokenExpiry();\n if (!expiry) return;\n\n const now = Math.floor(Date.now() / 1000);\n const delaySeconds = expiry - now - PROACTIVE_REFRESH_BUFFER_SECONDS;\n\n // If already past the proactive window, don't schedule (the normal\n // isTokenExpired / 401 fallback will handle it)\n if (delaySeconds <= 0) return;\n\n proactiveRefreshTimer = setTimeout(async () => {\n proactiveRefreshTimer = null;\n const tokens = await refreshTokens();\n if (tokens) {\n // Re-schedule for the next cycle\n scheduleProactiveRefresh(onRefreshed, onFailed);\n onRefreshed?.(tokens);\n } else {\n onFailed?.();\n }\n }, delaySeconds * 1000);\n}\n","import type { AxiosInstance, InternalAxiosRequestConfig, AxiosResponse, AxiosError } from 'axios';\nimport { getAccessToken, getValidAccessToken, clearTokens } from './tokenManager';\nimport type { AuthConfig } from './types';\n\ninterface QueuedRequest {\n resolve: (token: string | null) => void;\n reject: (error: Error) => void;\n}\n\nlet isRefreshing = false;\nlet requestQueue: QueuedRequest[] = [];\n\n/**\n * Process queued requests after token refresh\n */\nfunction processQueue(token: string | null, error: Error | null = null): void {\n requestQueue.forEach((request) => {\n if (error) {\n request.reject(error);\n } else {\n request.resolve(token);\n }\n });\n requestQueue = [];\n}\n\n/**\n * Create and configure axios instance with auth interceptors\n */\nexport function createAuthClient(\n axiosInstance: AxiosInstance,\n config: AuthConfig\n): AxiosInstance {\n // Request interceptor - attach Bearer token\n axiosInstance.interceptors.request.use(\n async (requestConfig: InternalAxiosRequestConfig): Promise<InternalAxiosRequestConfig> => {\n // Skip auth for refresh endpoint to avoid infinite loop\n if (requestConfig.url?.includes('/api/auth/refresh')) {\n return requestConfig;\n }\n\n const token = getAccessToken();\n if (token) {\n requestConfig.headers = requestConfig.headers || {};\n requestConfig.headers.Authorization = `Bearer ${token}`;\n }\n return requestConfig;\n },\n (error: unknown) => Promise.reject(error)\n );\n\n // Response interceptor - handle 401 and refresh token\n axiosInstance.interceptors.response.use(\n (response: AxiosResponse) => response,\n async (error: AxiosError): Promise<AxiosResponse> => {\n const originalRequest = error.config as InternalAxiosRequestConfig & {\n _retry?: boolean;\n };\n\n // Only handle 401 errors\n if (error.response?.status !== 401) {\n return Promise.reject(error);\n }\n\n // Don't retry if already retried or no config\n if (originalRequest._retry || !originalRequest) {\n clearTokens();\n config.onAuthError?.(new Error('Authentication failed'));\n return Promise.reject(error);\n }\n\n // Don't retry refresh endpoint\n if (originalRequest.url?.includes('/api/auth/refresh')) {\n clearTokens();\n config.onAuthError?.(new Error('Token refresh failed'));\n return Promise.reject(error);\n }\n\n // If already refreshing, queue this request\n if (isRefreshing) {\n return new Promise((resolve, reject) => {\n requestQueue.push({\n resolve: (token) => {\n if (token) {\n originalRequest.headers = originalRequest.headers || {};\n originalRequest.headers.Authorization = `Bearer ${token}`;\n resolve(axiosInstance(originalRequest));\n } else {\n reject(new Error('Token refresh failed'));\n }\n },\n reject,\n });\n });\n }\n\n originalRequest._retry = true;\n isRefreshing = true;\n\n try {\n const token = await getValidAccessToken();\n \n if (!token) {\n processQueue(null, new Error('Token refresh failed'));\n clearTokens();\n config.onAuthError?.(new Error('Token refresh failed'));\n return Promise.reject(error);\n }\n\n processQueue(token);\n \n originalRequest.headers = originalRequest.headers || {};\n originalRequest.headers.Authorization = `Bearer ${token}`;\n \n return axiosInstance(originalRequest);\n } catch (refreshError) {\n processQueue(null, refreshError instanceof Error ? refreshError : new Error('Token refresh failed'));\n clearTokens();\n config.onAuthError?.(refreshError instanceof Error ? refreshError : new Error('Token refresh failed'));\n return Promise.reject(refreshError);\n } finally {\n isRefreshing = false;\n }\n }\n );\n\n return axiosInstance;\n}\n\n/**\n * Create a new axios instance with auth interceptors\n */\nexport function createApiClient(config: AuthConfig): AxiosInstance {\n // Dynamic import to avoid bundling axios if not used\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const axios = require('axios');\n \n const instance = axios.create({\n baseURL: config.apiBaseUrl,\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n return createAuthClient(instance, config);\n}\n","import React, { createContext, useEffect, useState, useCallback, useMemo } from 'react';\nimport type { User, AuthState, AuthContextValue, AuthProviderProps, TokenPair, AuthConfig } from './types';\nimport {\n initTokenManager,\n getAccessToken,\n setTokens,\n clearTokens,\n isTokenExpired,\n decodeJwt,\n getValidAccessToken,\n scheduleProactiveRefresh,\n cancelProactiveRefresh,\n} from './tokenManager';\n\n// Create context with undefined default\nexport const AuthContext = createContext<AuthContextValue | undefined>(undefined);\n\n/**\n * Parse user from JWT payload\n */\nfunction parseUserFromToken(token: string): User | null {\n const payload = decodeJwt(token);\n if (!payload) return null;\n\n return {\n id: payload.sub,\n email: payload.email,\n firstName: payload.given_name,\n lastName: payload.family_name,\n displayName: payload.name,\n avatarUrl: payload.picture,\n emailVerified: payload.email_verified ?? false,\n roles: payload.roles,\n permissions: payload.permissions,\n };\n}\n\n/**\n * Build the SSO authorization URL\n */\nfunction buildAuthUrl(\n ssoBaseUrl: string,\n clientId: string,\n redirectUri: string | undefined,\n scopes: string[] = ['openid', 'email', 'profile'],\n redirectPath?: string\n): string {\n const finalRedirectUri = redirectUri || `${window.location.origin}/callback`;\n \n // Store the original path to redirect back after login\n if (redirectPath) {\n sessionStorage.setItem('arowauth_redirect_path', redirectPath);\n }\n\n const params = new URLSearchParams({\n client_id: clientId,\n redirect_uri: finalRedirectUri,\n response_type: 'token',\n scope: scopes.join(' '),\n });\n\n return `${ssoBaseUrl}/oauth/authorize?${params.toString()}`;\n}\n\n/**\n * Parse tokens from URL hash fragment (SSO callback)\n */\nfunction parseTokensFromHash(): TokenPair | null {\n if (typeof window === 'undefined') return null;\n \n const hash = window.location.hash;\n if (!hash) return null;\n\n // Parse hash fragment: #access_token=xxx&refresh_token=yyy&...\n const params = new URLSearchParams(hash.substring(1));\n \n const accessToken = params.get('access_token') || params.get('token');\n const refreshToken = params.get('refresh_token');\n\n if (accessToken && refreshToken) {\n return {\n accessToken,\n refreshToken,\n expiresIn: params.get('expires_in') ? parseInt(params.get('expires_in')!, 10) : undefined,\n tokenType: params.get('token_type') || 'Bearer',\n };\n }\n\n return null;\n}\n\n/**\n * AuthProvider component - wraps app with auth context\n */\nexport function AuthProvider(props: AuthProviderProps): React.ReactElement {\n const { children, onTokenRefresh, onAuthError, onLogout, ...config } = props;\n\n const [state, setState] = useState<AuthState>({\n user: null,\n isAuthenticated: false,\n isLoading: true,\n error: null,\n });\n\n // Initialize token manager with config\n useEffect(() => {\n const fullConfig: AuthConfig = {\n ...config,\n onTokenRefresh,\n onAuthError: (error: Error) => {\n setState((prev: AuthState) => ({ ...prev, error: error.message }));\n onAuthError?.(error);\n },\n onLogout,\n };\n initTokenManager(fullConfig);\n }, [config.ssoBaseUrl, config.clientId, config.apiBaseUrl, onTokenRefresh, onAuthError, onLogout]);\n\n // Handle SSO callback and initial auth check\n useEffect(() => {\n const startProactive = () => {\n scheduleProactiveRefresh(\n (tokens) => {\n const user = parseUserFromToken(tokens.accessToken);\n setState((prev: AuthState) => ({ ...prev, user, isAuthenticated: true, error: null }));\n onTokenRefresh?.(tokens);\n },\n () => {\n setState({ user: null, isAuthenticated: false, isLoading: false, error: null });\n },\n );\n };\n\n const initAuth = async () => {\n try {\n // Check for tokens in URL hash (SSO callback)\n const hashTokens = parseTokensFromHash();\n if (hashTokens) {\n setTokens(hashTokens.accessToken, hashTokens.refreshToken);\n \n // Clean up URL\n window.history.replaceState(null, '', window.location.pathname + window.location.search);\n \n // Redirect to original path if stored\n const redirectPath = sessionStorage.getItem('arowauth_redirect_path');\n if (redirectPath) {\n sessionStorage.removeItem('arowauth_redirect_path');\n window.history.replaceState(null, '', redirectPath);\n }\n\n onTokenRefresh?.(hashTokens);\n startProactive();\n }\n\n // Check for existing valid token\n const token = getAccessToken();\n if (token && !isTokenExpired(token)) {\n const user = parseUserFromToken(token);\n setState({\n user,\n isAuthenticated: true,\n isLoading: false,\n error: null,\n });\n startProactive();\n return;\n }\n\n // Try to refresh if we have a token but it's expired\n if (token) {\n const newToken = await getValidAccessToken();\n if (newToken) {\n const user = parseUserFromToken(newToken);\n setState({\n user,\n isAuthenticated: true,\n isLoading: false,\n error: null,\n });\n startProactive();\n return;\n }\n }\n\n // No valid auth\n setState({\n user: null,\n isAuthenticated: false,\n isLoading: false,\n error: null,\n });\n } catch (error) {\n setState({\n user: null,\n isAuthenticated: false,\n isLoading: false,\n error: error instanceof Error ? error.message : 'Authentication error',\n });\n }\n };\n\n initAuth();\n\n return () => {\n cancelProactiveRefresh();\n };\n }, [onTokenRefresh]);\n\n // Login - redirect to SSO\n const login = useCallback((redirectPath?: string) => {\n const authUrl = buildAuthUrl(\n config.ssoBaseUrl,\n config.clientId,\n config.redirectUri,\n config.scopes,\n redirectPath || window.location.pathname\n );\n window.location.href = authUrl;\n }, [config.ssoBaseUrl, config.clientId, config.redirectUri, config.scopes]);\n\n // Logout - clear tokens and optionally call SSO logout\n const logout = useCallback(async () => {\n clearTokens();\n setState({\n user: null,\n isAuthenticated: false,\n isLoading: false,\n error: null,\n });\n onLogout?.();\n }, [onLogout]);\n\n // Refresh user data from token\n const refreshUser = useCallback(async () => {\n const token = await getValidAccessToken();\n if (token) {\n const user = parseUserFromToken(token);\n setState((prev: AuthState) => ({\n ...prev,\n user,\n isAuthenticated: true,\n error: null,\n }));\n } else {\n setState({\n user: null,\n isAuthenticated: false,\n isLoading: false,\n error: null,\n });\n }\n }, []);\n\n // Memoize context value\n const contextValue = useMemo<AuthContextValue>(\n () => ({\n ...state,\n login,\n logout,\n refreshUser,\n }),\n [state, login, logout, refreshUser]\n );\n\n return (\n <AuthContext.Provider value={contextValue}>\n {children}\n </AuthContext.Provider>\n );\n}\n","import { useContext } from 'react';\nimport { AuthContext } from '../AuthProvider';\nimport type { AuthContextValue, User } from '../types';\n\n/**\n * Hook to access auth state and actions\n * \n * @returns Auth context value with user, isAuthenticated, login, logout, etc.\n * @throws Error if used outside of AuthProvider\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * const { user, isAuthenticated, login, logout, isLoading } = useAuth();\n * \n * if (isLoading) return <div>Loading...</div>;\n * \n * if (!isAuthenticated) {\n * return <button onClick={() => login()}>Login</button>;\n * }\n * \n * return (\n * <div>\n * <p>Welcome, {user?.displayName || user?.email}!</p>\n * <button onClick={logout}>Logout</button>\n * </div>\n * );\n * }\n * ```\n */\nexport function useAuth(): AuthContextValue {\n const context = useContext(AuthContext);\n \n if (context === undefined) {\n throw new Error('useAuth must be used within an AuthProvider');\n }\n \n return context;\n}\n\n/**\n * Hook to check if user is authenticated (convenience wrapper)\n * \n * @returns Boolean indicating if user is authenticated\n */\nexport function useIsAuthenticated(): boolean {\n const { isAuthenticated } = useAuth();\n return isAuthenticated;\n}\n\n/**\n * Hook to get current user (convenience wrapper)\n * \n * @returns Current user or null\n */\nexport function useUser(): User | null {\n const { user } = useAuth();\n return user;\n}\n","import { useMemo, useContext } from 'react';\nimport type { AxiosInstance, InternalAxiosRequestConfig, AxiosResponse, AxiosError } from 'axios';\nimport { AuthContext } from '../AuthProvider';\nimport { getAccessToken, getValidAccessToken, clearTokens } from '../tokenManager';\n\ninterface QueuedRequest {\n resolve: (token: string | null) => void;\n reject: (error: Error) => void;\n}\n\n/**\n * Hook to get a configured axios instance with auth interceptors\n * \n * The returned axios instance will:\n * - Automatically attach Bearer token to requests\n * - Handle 401 responses by refreshing tokens and retrying\n * - Queue concurrent requests during token refresh\n * \n * @returns Configured axios instance\n * @throws Error if used outside of AuthProvider\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * const client = useAuthClient();\n * \n * const fetchData = async () => {\n * try {\n * const response = await client.get('/api/data');\n * console.log(response.data);\n * } catch (error) {\n * console.error('Failed to fetch data', error);\n * }\n * };\n * \n * return <button onClick={fetchData}>Fetch Data</button>;\n * }\n * ```\n */\nexport function useAuthClient(): AxiosInstance {\n const context = useContext(AuthContext);\n \n if (context === undefined) {\n throw new Error('useAuthClient must be used within an AuthProvider');\n }\n\n const client = useMemo(() => {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const axios = require('axios');\n \n const instance: AxiosInstance = axios.create({\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n let isRefreshing = false;\n let requestQueue: QueuedRequest[] = [];\n\n const processQueue = (token: string | null, error: Error | null = null): void => {\n requestQueue.forEach((req) => {\n if (error) {\n req.reject(error);\n } else {\n req.resolve(token);\n }\n });\n requestQueue = [];\n };\n\n // Request interceptor\n instance.interceptors.request.use(\n async (config: InternalAxiosRequestConfig): Promise<InternalAxiosRequestConfig> => {\n if (config.url?.includes('/api/auth/refresh')) {\n return config;\n }\n const token = getAccessToken();\n if (token) {\n config.headers = config.headers || {};\n config.headers.Authorization = `Bearer ${token}`;\n }\n return config;\n },\n (error: unknown) => Promise.reject(error)\n );\n\n // Response interceptor\n instance.interceptors.response.use(\n (response: AxiosResponse) => response,\n async (error: AxiosError): Promise<AxiosResponse> => {\n const originalRequest = error.config as InternalAxiosRequestConfig & {\n _retry?: boolean;\n };\n\n if (error.response?.status !== 401 || originalRequest._retry) {\n return Promise.reject(error);\n }\n\n if (originalRequest.url?.includes('/api/auth/refresh')) {\n clearTokens();\n return Promise.reject(error);\n }\n\n if (isRefreshing) {\n return new Promise((resolve, reject) => {\n requestQueue.push({\n resolve: (token) => {\n if (token) {\n originalRequest.headers = originalRequest.headers || {};\n originalRequest.headers.Authorization = `Bearer ${token}`;\n resolve(instance(originalRequest));\n } else {\n reject(new Error('Token refresh failed'));\n }\n },\n reject,\n });\n });\n }\n\n originalRequest._retry = true;\n isRefreshing = true;\n\n try {\n const token = await getValidAccessToken();\n if (!token) {\n processQueue(null, new Error('Token refresh failed'));\n clearTokens();\n return Promise.reject(error);\n }\n\n processQueue(token);\n originalRequest.headers = originalRequest.headers || {};\n originalRequest.headers.Authorization = `Bearer ${token}`;\n return instance(originalRequest);\n } catch (refreshError) {\n processQueue(null, refreshError instanceof Error ? refreshError : new Error('Refresh failed'));\n clearTokens();\n return Promise.reject(refreshError);\n } finally {\n isRefreshing = false;\n }\n }\n );\n\n return instance;\n }, []);\n\n return client;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arow-software/auth-client",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "Reusable auth package for ArowAuth SSO integration",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",