@arow-software/auth-client 2.0.0 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -66,10 +66,16 @@ interface AuthContextValue extends AuthState {
66
66
  */
67
67
  interface AuthConfig {
68
68
  /**
69
- * Base URL of the ArowAuth SSO server
69
+ * Base URL of the ArowAuth SSO UI (used for login redirects)
70
70
  * @example "https://sso.arowsoftware.co.uk"
71
71
  */
72
72
  ssoBaseUrl: string;
73
+ /**
74
+ * Base URL of the ArowAuth API (used for token exchange, refresh, etc.)
75
+ * If not provided, falls back to ssoBaseUrl for backward compatibility.
76
+ * @example "https://sso-api.arowsoftware.co.uk"
77
+ */
78
+ ssoApiUrl?: string;
73
79
  /**
74
80
  * Client ID registered with ArowAuth
75
81
  * @example "arowtrades"
package/dist/index.d.ts CHANGED
@@ -66,10 +66,16 @@ interface AuthContextValue extends AuthState {
66
66
  */
67
67
  interface AuthConfig {
68
68
  /**
69
- * Base URL of the ArowAuth SSO server
69
+ * Base URL of the ArowAuth SSO UI (used for login redirects)
70
70
  * @example "https://sso.arowsoftware.co.uk"
71
71
  */
72
72
  ssoBaseUrl: string;
73
+ /**
74
+ * Base URL of the ArowAuth API (used for token exchange, refresh, etc.)
75
+ * If not provided, falls back to ssoBaseUrl for backward compatibility.
76
+ * @example "https://sso-api.arowsoftware.co.uk"
77
+ */
78
+ ssoApiUrl?: string;
73
79
  /**
74
80
  * Client ID registered with ArowAuth
75
81
  * @example "arowtrades"
package/dist/index.js CHANGED
@@ -126,7 +126,7 @@ async function refreshTokens() {
126
126
  async function performRefresh(refreshToken) {
127
127
  if (!config) return null;
128
128
  try {
129
- const response = await fetch(`${config.ssoBaseUrl}/api/auth/refresh`, {
129
+ const response = await fetch(`${config.ssoApiUrl || config.ssoBaseUrl}/api/auth/refresh`, {
130
130
  method: "POST",
131
131
  headers: {
132
132
  "Content-Type": "application/json"
@@ -346,7 +346,7 @@ function parseCodeFromQuery() {
346
346
  state: params.get("state") || void 0
347
347
  };
348
348
  }
349
- async function exchangeCodeForTokens(ssoBaseUrl, clientId, redirectUri, code) {
349
+ async function exchangeCodeForTokens(ssoApiUrl, clientId, redirectUri, code) {
350
350
  try {
351
351
  const codeVerifier = sessionStorage.getItem("arow_pkce_code_verifier");
352
352
  if (!codeVerifier) {
@@ -360,7 +360,7 @@ async function exchangeCodeForTokens(ssoBaseUrl, clientId, redirectUri, code) {
360
360
  redirect_uri: redirectUri,
361
361
  code_verifier: codeVerifier
362
362
  });
363
- const response = await fetch(`${ssoBaseUrl}/oauth/token`, {
363
+ const response = await fetch(`${ssoApiUrl}/oauth/token`, {
364
364
  method: "POST",
365
365
  headers: {
366
366
  "Content-Type": "application/x-www-form-urlencoded"
@@ -418,7 +418,7 @@ function AuthProvider(props) {
418
418
  onLogout
419
419
  };
420
420
  initTokenManager(fullConfig);
421
- }, [config2.ssoBaseUrl, config2.clientId, config2.apiBaseUrl, onTokenRefresh, onAuthError, onLogout]);
421
+ }, [config2.ssoBaseUrl, config2.ssoApiUrl, config2.clientId, config2.apiBaseUrl, onTokenRefresh, onAuthError, onLogout]);
422
422
  react.useEffect(() => {
423
423
  const startProactive = () => {
424
424
  scheduleProactiveRefresh(
@@ -438,7 +438,7 @@ function AuthProvider(props) {
438
438
  if (codeData) {
439
439
  const finalRedirectUri = config2.redirectUri || `${window.location.origin}/callback`;
440
440
  const tokens = await exchangeCodeForTokens(
441
- config2.ssoBaseUrl,
441
+ config2.ssoApiUrl || config2.ssoBaseUrl,
442
442
  config2.clientId,
443
443
  finalRedirectUri,
444
444
  codeData.code
@@ -541,6 +541,22 @@ function AuthProvider(props) {
541
541
  window.location.href = authUrl;
542
542
  }, [config2.ssoBaseUrl, config2.clientId, config2.redirectUri, config2.scopes]);
543
543
  const logout = react.useCallback(async () => {
544
+ const refreshToken = getRefreshToken();
545
+ if (refreshToken) {
546
+ const ssoApi = config2.ssoApiUrl || config2.ssoBaseUrl;
547
+ const body = new URLSearchParams({
548
+ token: refreshToken,
549
+ token_type_hint: "refresh_token",
550
+ client_id: config2.clientId
551
+ });
552
+ fetch(`${ssoApi}/oauth/revoke`, {
553
+ method: "POST",
554
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
555
+ body: body.toString()
556
+ }).catch(() => {
557
+ });
558
+ }
559
+ cancelProactiveRefresh();
544
560
  clearTokens();
545
561
  setState({
546
562
  user: null,
@@ -549,7 +565,7 @@ function AuthProvider(props) {
549
565
  error: null
550
566
  });
551
567
  onLogout?.();
552
- }, [onLogout]);
568
+ }, [onLogout, config2.ssoApiUrl, config2.ssoBaseUrl, config2.clientId]);
553
569
  const refreshUser = react.useCallback(async () => {
554
570
  const token = await getValidAccessToken();
555
571
  if (token) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/tokenManager.ts","../src/pkce.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","/**\n * PKCE (Proof Key for Code Exchange) helper functions for OAuth 2.0 Authorization Code Flow\n * \n * RFC 7636: https://datatracker.ietf.org/doc/html/rfc7636\n */\n\n/**\n * Generate a cryptographically random code verifier\n * Returns a base64url-encoded string of 32 random bytes (43 characters)\n */\nexport function generateCodeVerifier(): string {\n const array = new Uint8Array(32);\n crypto.getRandomValues(array);\n return base64UrlEncode(array);\n}\n\n/**\n * Generate a code challenge from a code verifier using SHA-256\n * @param verifier - The code verifier string\n * @returns Promise resolving to the base64url-encoded SHA-256 hash\n */\nexport async function generateCodeChallenge(verifier: string): Promise<string> {\n const encoder = new TextEncoder();\n const data = encoder.encode(verifier);\n const hash = await crypto.subtle.digest('SHA-256', data);\n return base64UrlEncode(new Uint8Array(hash));\n}\n\n/**\n * Encode a byte array to base64url format (RFC 4648 Section 5)\n * @param bytes - The byte array to encode\n * @returns Base64url-encoded string\n */\nfunction base64UrlEncode(bytes: Uint8Array): string {\n let str = '';\n bytes.forEach(b => str += String.fromCharCode(b));\n return btoa(str)\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\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';\nimport { generateCodeVerifier, generateCodeChallenge } from './pkce';\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 with PKCE\n */\nasync function buildAuthUrl(\n ssoBaseUrl: string,\n clientId: string,\n redirectUri: string | undefined,\n scopes: string[] = ['openid', 'email', 'profile'],\n redirectPath?: string\n): Promise<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 // Generate PKCE parameters\n const codeVerifier = generateCodeVerifier();\n const codeChallenge = await generateCodeChallenge(codeVerifier);\n \n // Store code verifier for later use in token exchange\n sessionStorage.setItem('arow_pkce_code_verifier', codeVerifier);\n\n const params = new URLSearchParams({\n client_id: clientId,\n redirect_uri: finalRedirectUri,\n response_type: 'code',\n scope: scopes.join(' '),\n code_challenge: codeChallenge,\n code_challenge_method: 'S256',\n });\n\n return `${ssoBaseUrl}/oauth/authorize?${params.toString()}`;\n}\n\n/**\n * Parse authorization code from URL query params (PKCE callback)\n */\nfunction parseCodeFromQuery(): { code: string; state?: string } | null {\n if (typeof window === 'undefined') return null;\n \n const params = new URLSearchParams(window.location.search);\n const code = params.get('code');\n \n if (!code) return null;\n \n return {\n code,\n state: params.get('state') || undefined,\n };\n}\n\n/**\n * Exchange authorization code for tokens using PKCE\n */\nasync function exchangeCodeForTokens(\n ssoBaseUrl: string,\n clientId: string,\n redirectUri: string,\n code: string\n): Promise<TokenPair | null> {\n try {\n // Retrieve and remove code verifier from session storage\n const codeVerifier = sessionStorage.getItem('arow_pkce_code_verifier');\n if (!codeVerifier) {\n throw new Error('Code verifier not found in session storage');\n }\n sessionStorage.removeItem('arow_pkce_code_verifier');\n\n // Build the token exchange request body\n const body = new URLSearchParams({\n grant_type: 'authorization_code',\n code,\n client_id: clientId,\n redirect_uri: redirectUri,\n code_verifier: codeVerifier,\n });\n\n const response = await fetch(`${ssoBaseUrl}/oauth/token`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: body.toString(),\n });\n\n if (!response.ok) {\n throw new Error(`Token exchange failed: ${response.status} ${response.statusText}`);\n }\n\n const data = await response.json();\n \n return {\n accessToken: data.access_token || data.accessToken,\n refreshToken: data.refresh_token || data.refreshToken,\n expiresIn: data.expires_in || data.expiresIn,\n tokenType: data.token_type || data.tokenType || 'Bearer',\n };\n } catch (error) {\n console.error('Failed to exchange code for tokens:', error);\n return null;\n }\n}\n\n/**\n * Parse tokens from URL hash fragment (SSO callback - DEPRECATED, v1 backward compatibility)\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 // PRIORITY 1: Check for authorization code in query params (PKCE v2 flow)\n const codeData = parseCodeFromQuery();\n if (codeData) {\n const finalRedirectUri = config.redirectUri || `${window.location.origin}/callback`;\n const tokens = await exchangeCodeForTokens(\n config.ssoBaseUrl,\n config.clientId,\n finalRedirectUri,\n codeData.code\n );\n \n if (tokens) {\n setTokens(tokens.accessToken, tokens.refreshToken);\n \n // Clean up URL - remove query params\n const cleanUrl = window.location.pathname;\n window.history.replaceState(null, '', cleanUrl);\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?.(tokens);\n startProactive();\n \n const user = parseUserFromToken(tokens.accessToken);\n setState({\n user,\n isAuthenticated: true,\n isLoading: false,\n error: null,\n });\n return;\n } else {\n // Code exchange failed\n setState({\n user: null,\n isAuthenticated: false,\n isLoading: false,\n error: 'Failed to exchange authorization code for tokens',\n });\n return;\n }\n }\n\n // PRIORITY 2: Check for tokens in URL hash (v1 implicit flow - backward compatibility)\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(async (redirectPath?: string) => {\n const authUrl = await 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/pkce.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.ssoApiUrl || 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","/**\n * PKCE (Proof Key for Code Exchange) helper functions for OAuth 2.0 Authorization Code Flow\n * \n * RFC 7636: https://datatracker.ietf.org/doc/html/rfc7636\n */\n\n/**\n * Generate a cryptographically random code verifier\n * Returns a base64url-encoded string of 32 random bytes (43 characters)\n */\nexport function generateCodeVerifier(): string {\n const array = new Uint8Array(32);\n crypto.getRandomValues(array);\n return base64UrlEncode(array);\n}\n\n/**\n * Generate a code challenge from a code verifier using SHA-256\n * @param verifier - The code verifier string\n * @returns Promise resolving to the base64url-encoded SHA-256 hash\n */\nexport async function generateCodeChallenge(verifier: string): Promise<string> {\n const encoder = new TextEncoder();\n const data = encoder.encode(verifier);\n const hash = await crypto.subtle.digest('SHA-256', data);\n return base64UrlEncode(new Uint8Array(hash));\n}\n\n/**\n * Encode a byte array to base64url format (RFC 4648 Section 5)\n * @param bytes - The byte array to encode\n * @returns Base64url-encoded string\n */\nfunction base64UrlEncode(bytes: Uint8Array): string {\n let str = '';\n bytes.forEach(b => str += String.fromCharCode(b));\n return btoa(str)\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\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 getRefreshToken,\n setTokens,\n clearTokens,\n isTokenExpired,\n decodeJwt,\n getValidAccessToken,\n scheduleProactiveRefresh,\n cancelProactiveRefresh,\n} from './tokenManager';\nimport { generateCodeVerifier, generateCodeChallenge } from './pkce';\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 with PKCE\n */\nasync function buildAuthUrl(\n ssoBaseUrl: string,\n clientId: string,\n redirectUri: string | undefined,\n scopes: string[] = ['openid', 'email', 'profile'],\n redirectPath?: string\n): Promise<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 // Generate PKCE parameters\n const codeVerifier = generateCodeVerifier();\n const codeChallenge = await generateCodeChallenge(codeVerifier);\n \n // Store code verifier for later use in token exchange\n sessionStorage.setItem('arow_pkce_code_verifier', codeVerifier);\n\n const params = new URLSearchParams({\n client_id: clientId,\n redirect_uri: finalRedirectUri,\n response_type: 'code',\n scope: scopes.join(' '),\n code_challenge: codeChallenge,\n code_challenge_method: 'S256',\n });\n\n return `${ssoBaseUrl}/oauth/authorize?${params.toString()}`;\n}\n\n/**\n * Parse authorization code from URL query params (PKCE callback)\n */\nfunction parseCodeFromQuery(): { code: string; state?: string } | null {\n if (typeof window === 'undefined') return null;\n \n const params = new URLSearchParams(window.location.search);\n const code = params.get('code');\n \n if (!code) return null;\n \n return {\n code,\n state: params.get('state') || undefined,\n };\n}\n\n/**\n * Exchange authorization code for tokens using PKCE\n */\nasync function exchangeCodeForTokens(\n ssoApiUrl: string,\n clientId: string,\n redirectUri: string,\n code: string\n): Promise<TokenPair | null> {\n try {\n // Retrieve and remove code verifier from session storage\n const codeVerifier = sessionStorage.getItem('arow_pkce_code_verifier');\n if (!codeVerifier) {\n throw new Error('Code verifier not found in session storage');\n }\n sessionStorage.removeItem('arow_pkce_code_verifier');\n\n // Build the token exchange request body\n const body = new URLSearchParams({\n grant_type: 'authorization_code',\n code,\n client_id: clientId,\n redirect_uri: redirectUri,\n code_verifier: codeVerifier,\n });\n\n const response = await fetch(`${ssoApiUrl}/oauth/token`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: body.toString(),\n });\n\n if (!response.ok) {\n throw new Error(`Token exchange failed: ${response.status} ${response.statusText}`);\n }\n\n const data = await response.json();\n \n return {\n accessToken: data.access_token || data.accessToken,\n refreshToken: data.refresh_token || data.refreshToken,\n expiresIn: data.expires_in || data.expiresIn,\n tokenType: data.token_type || data.tokenType || 'Bearer',\n };\n } catch (error) {\n console.error('Failed to exchange code for tokens:', error);\n return null;\n }\n}\n\n/**\n * Parse tokens from URL hash fragment (SSO callback - DEPRECATED, v1 backward compatibility)\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.ssoApiUrl, 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 // PRIORITY 1: Check for authorization code in query params (PKCE v2 flow)\n const codeData = parseCodeFromQuery();\n if (codeData) {\n const finalRedirectUri = config.redirectUri || `${window.location.origin}/callback`;\n const tokens = await exchangeCodeForTokens(\n config.ssoApiUrl || config.ssoBaseUrl,\n config.clientId,\n finalRedirectUri,\n codeData.code\n );\n \n if (tokens) {\n setTokens(tokens.accessToken, tokens.refreshToken);\n \n // Clean up URL - remove query params\n const cleanUrl = window.location.pathname;\n window.history.replaceState(null, '', cleanUrl);\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?.(tokens);\n startProactive();\n \n const user = parseUserFromToken(tokens.accessToken);\n setState({\n user,\n isAuthenticated: true,\n isLoading: false,\n error: null,\n });\n return;\n } else {\n // Code exchange failed\n setState({\n user: null,\n isAuthenticated: false,\n isLoading: false,\n error: 'Failed to exchange authorization code for tokens',\n });\n return;\n }\n }\n\n // PRIORITY 2: Check for tokens in URL hash (v1 implicit flow - backward compatibility)\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(async (redirectPath?: string) => {\n const authUrl = await 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 - revoke refresh token, clear local tokens\n const logout = useCallback(async () => {\n // Fire-and-forget: revoke the refresh token at SSO\n const refreshToken = getRefreshToken();\n if (refreshToken) {\n const ssoApi = config.ssoApiUrl || config.ssoBaseUrl;\n const body = new URLSearchParams({\n token: refreshToken,\n token_type_hint: 'refresh_token',\n client_id: config.clientId,\n });\n fetch(`${ssoApi}/oauth/revoke`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: body.toString(),\n }).catch(() => { /* ignore */ });\n }\n\n cancelProactiveRefresh();\n clearTokens();\n setState({\n user: null,\n isAuthenticated: false,\n isLoading: false,\n error: null,\n });\n onLogout?.();\n }, [onLogout, config.ssoApiUrl, config.ssoBaseUrl, config.clientId]);\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
@@ -124,7 +124,7 @@ async function refreshTokens() {
124
124
  async function performRefresh(refreshToken) {
125
125
  if (!config) return null;
126
126
  try {
127
- const response = await fetch(`${config.ssoBaseUrl}/api/auth/refresh`, {
127
+ const response = await fetch(`${config.ssoApiUrl || config.ssoBaseUrl}/api/auth/refresh`, {
128
128
  method: "POST",
129
129
  headers: {
130
130
  "Content-Type": "application/json"
@@ -344,7 +344,7 @@ function parseCodeFromQuery() {
344
344
  state: params.get("state") || void 0
345
345
  };
346
346
  }
347
- async function exchangeCodeForTokens(ssoBaseUrl, clientId, redirectUri, code) {
347
+ async function exchangeCodeForTokens(ssoApiUrl, clientId, redirectUri, code) {
348
348
  try {
349
349
  const codeVerifier = sessionStorage.getItem("arow_pkce_code_verifier");
350
350
  if (!codeVerifier) {
@@ -358,7 +358,7 @@ async function exchangeCodeForTokens(ssoBaseUrl, clientId, redirectUri, code) {
358
358
  redirect_uri: redirectUri,
359
359
  code_verifier: codeVerifier
360
360
  });
361
- const response = await fetch(`${ssoBaseUrl}/oauth/token`, {
361
+ const response = await fetch(`${ssoApiUrl}/oauth/token`, {
362
362
  method: "POST",
363
363
  headers: {
364
364
  "Content-Type": "application/x-www-form-urlencoded"
@@ -416,7 +416,7 @@ function AuthProvider(props) {
416
416
  onLogout
417
417
  };
418
418
  initTokenManager(fullConfig);
419
- }, [config2.ssoBaseUrl, config2.clientId, config2.apiBaseUrl, onTokenRefresh, onAuthError, onLogout]);
419
+ }, [config2.ssoBaseUrl, config2.ssoApiUrl, config2.clientId, config2.apiBaseUrl, onTokenRefresh, onAuthError, onLogout]);
420
420
  useEffect(() => {
421
421
  const startProactive = () => {
422
422
  scheduleProactiveRefresh(
@@ -436,7 +436,7 @@ function AuthProvider(props) {
436
436
  if (codeData) {
437
437
  const finalRedirectUri = config2.redirectUri || `${window.location.origin}/callback`;
438
438
  const tokens = await exchangeCodeForTokens(
439
- config2.ssoBaseUrl,
439
+ config2.ssoApiUrl || config2.ssoBaseUrl,
440
440
  config2.clientId,
441
441
  finalRedirectUri,
442
442
  codeData.code
@@ -539,6 +539,22 @@ function AuthProvider(props) {
539
539
  window.location.href = authUrl;
540
540
  }, [config2.ssoBaseUrl, config2.clientId, config2.redirectUri, config2.scopes]);
541
541
  const logout = useCallback(async () => {
542
+ const refreshToken = getRefreshToken();
543
+ if (refreshToken) {
544
+ const ssoApi = config2.ssoApiUrl || config2.ssoBaseUrl;
545
+ const body = new URLSearchParams({
546
+ token: refreshToken,
547
+ token_type_hint: "refresh_token",
548
+ client_id: config2.clientId
549
+ });
550
+ fetch(`${ssoApi}/oauth/revoke`, {
551
+ method: "POST",
552
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
553
+ body: body.toString()
554
+ }).catch(() => {
555
+ });
556
+ }
557
+ cancelProactiveRefresh();
542
558
  clearTokens();
543
559
  setState({
544
560
  user: null,
@@ -547,7 +563,7 @@ function AuthProvider(props) {
547
563
  error: null
548
564
  });
549
565
  onLogout?.();
550
- }, [onLogout]);
566
+ }, [onLogout, config2.ssoApiUrl, config2.ssoBaseUrl, config2.clientId]);
551
567
  const refreshUser = useCallback(async () => {
552
568
  const token = await getValidAccessToken();
553
569
  if (token) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/tokenManager.ts","../src/pkce.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","/**\n * PKCE (Proof Key for Code Exchange) helper functions for OAuth 2.0 Authorization Code Flow\n * \n * RFC 7636: https://datatracker.ietf.org/doc/html/rfc7636\n */\n\n/**\n * Generate a cryptographically random code verifier\n * Returns a base64url-encoded string of 32 random bytes (43 characters)\n */\nexport function generateCodeVerifier(): string {\n const array = new Uint8Array(32);\n crypto.getRandomValues(array);\n return base64UrlEncode(array);\n}\n\n/**\n * Generate a code challenge from a code verifier using SHA-256\n * @param verifier - The code verifier string\n * @returns Promise resolving to the base64url-encoded SHA-256 hash\n */\nexport async function generateCodeChallenge(verifier: string): Promise<string> {\n const encoder = new TextEncoder();\n const data = encoder.encode(verifier);\n const hash = await crypto.subtle.digest('SHA-256', data);\n return base64UrlEncode(new Uint8Array(hash));\n}\n\n/**\n * Encode a byte array to base64url format (RFC 4648 Section 5)\n * @param bytes - The byte array to encode\n * @returns Base64url-encoded string\n */\nfunction base64UrlEncode(bytes: Uint8Array): string {\n let str = '';\n bytes.forEach(b => str += String.fromCharCode(b));\n return btoa(str)\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\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';\nimport { generateCodeVerifier, generateCodeChallenge } from './pkce';\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 with PKCE\n */\nasync function buildAuthUrl(\n ssoBaseUrl: string,\n clientId: string,\n redirectUri: string | undefined,\n scopes: string[] = ['openid', 'email', 'profile'],\n redirectPath?: string\n): Promise<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 // Generate PKCE parameters\n const codeVerifier = generateCodeVerifier();\n const codeChallenge = await generateCodeChallenge(codeVerifier);\n \n // Store code verifier for later use in token exchange\n sessionStorage.setItem('arow_pkce_code_verifier', codeVerifier);\n\n const params = new URLSearchParams({\n client_id: clientId,\n redirect_uri: finalRedirectUri,\n response_type: 'code',\n scope: scopes.join(' '),\n code_challenge: codeChallenge,\n code_challenge_method: 'S256',\n });\n\n return `${ssoBaseUrl}/oauth/authorize?${params.toString()}`;\n}\n\n/**\n * Parse authorization code from URL query params (PKCE callback)\n */\nfunction parseCodeFromQuery(): { code: string; state?: string } | null {\n if (typeof window === 'undefined') return null;\n \n const params = new URLSearchParams(window.location.search);\n const code = params.get('code');\n \n if (!code) return null;\n \n return {\n code,\n state: params.get('state') || undefined,\n };\n}\n\n/**\n * Exchange authorization code for tokens using PKCE\n */\nasync function exchangeCodeForTokens(\n ssoBaseUrl: string,\n clientId: string,\n redirectUri: string,\n code: string\n): Promise<TokenPair | null> {\n try {\n // Retrieve and remove code verifier from session storage\n const codeVerifier = sessionStorage.getItem('arow_pkce_code_verifier');\n if (!codeVerifier) {\n throw new Error('Code verifier not found in session storage');\n }\n sessionStorage.removeItem('arow_pkce_code_verifier');\n\n // Build the token exchange request body\n const body = new URLSearchParams({\n grant_type: 'authorization_code',\n code,\n client_id: clientId,\n redirect_uri: redirectUri,\n code_verifier: codeVerifier,\n });\n\n const response = await fetch(`${ssoBaseUrl}/oauth/token`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: body.toString(),\n });\n\n if (!response.ok) {\n throw new Error(`Token exchange failed: ${response.status} ${response.statusText}`);\n }\n\n const data = await response.json();\n \n return {\n accessToken: data.access_token || data.accessToken,\n refreshToken: data.refresh_token || data.refreshToken,\n expiresIn: data.expires_in || data.expiresIn,\n tokenType: data.token_type || data.tokenType || 'Bearer',\n };\n } catch (error) {\n console.error('Failed to exchange code for tokens:', error);\n return null;\n }\n}\n\n/**\n * Parse tokens from URL hash fragment (SSO callback - DEPRECATED, v1 backward compatibility)\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 // PRIORITY 1: Check for authorization code in query params (PKCE v2 flow)\n const codeData = parseCodeFromQuery();\n if (codeData) {\n const finalRedirectUri = config.redirectUri || `${window.location.origin}/callback`;\n const tokens = await exchangeCodeForTokens(\n config.ssoBaseUrl,\n config.clientId,\n finalRedirectUri,\n codeData.code\n );\n \n if (tokens) {\n setTokens(tokens.accessToken, tokens.refreshToken);\n \n // Clean up URL - remove query params\n const cleanUrl = window.location.pathname;\n window.history.replaceState(null, '', cleanUrl);\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?.(tokens);\n startProactive();\n \n const user = parseUserFromToken(tokens.accessToken);\n setState({\n user,\n isAuthenticated: true,\n isLoading: false,\n error: null,\n });\n return;\n } else {\n // Code exchange failed\n setState({\n user: null,\n isAuthenticated: false,\n isLoading: false,\n error: 'Failed to exchange authorization code for tokens',\n });\n return;\n }\n }\n\n // PRIORITY 2: Check for tokens in URL hash (v1 implicit flow - backward compatibility)\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(async (redirectPath?: string) => {\n const authUrl = await 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/pkce.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.ssoApiUrl || 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","/**\n * PKCE (Proof Key for Code Exchange) helper functions for OAuth 2.0 Authorization Code Flow\n * \n * RFC 7636: https://datatracker.ietf.org/doc/html/rfc7636\n */\n\n/**\n * Generate a cryptographically random code verifier\n * Returns a base64url-encoded string of 32 random bytes (43 characters)\n */\nexport function generateCodeVerifier(): string {\n const array = new Uint8Array(32);\n crypto.getRandomValues(array);\n return base64UrlEncode(array);\n}\n\n/**\n * Generate a code challenge from a code verifier using SHA-256\n * @param verifier - The code verifier string\n * @returns Promise resolving to the base64url-encoded SHA-256 hash\n */\nexport async function generateCodeChallenge(verifier: string): Promise<string> {\n const encoder = new TextEncoder();\n const data = encoder.encode(verifier);\n const hash = await crypto.subtle.digest('SHA-256', data);\n return base64UrlEncode(new Uint8Array(hash));\n}\n\n/**\n * Encode a byte array to base64url format (RFC 4648 Section 5)\n * @param bytes - The byte array to encode\n * @returns Base64url-encoded string\n */\nfunction base64UrlEncode(bytes: Uint8Array): string {\n let str = '';\n bytes.forEach(b => str += String.fromCharCode(b));\n return btoa(str)\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\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 getRefreshToken,\n setTokens,\n clearTokens,\n isTokenExpired,\n decodeJwt,\n getValidAccessToken,\n scheduleProactiveRefresh,\n cancelProactiveRefresh,\n} from './tokenManager';\nimport { generateCodeVerifier, generateCodeChallenge } from './pkce';\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 with PKCE\n */\nasync function buildAuthUrl(\n ssoBaseUrl: string,\n clientId: string,\n redirectUri: string | undefined,\n scopes: string[] = ['openid', 'email', 'profile'],\n redirectPath?: string\n): Promise<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 // Generate PKCE parameters\n const codeVerifier = generateCodeVerifier();\n const codeChallenge = await generateCodeChallenge(codeVerifier);\n \n // Store code verifier for later use in token exchange\n sessionStorage.setItem('arow_pkce_code_verifier', codeVerifier);\n\n const params = new URLSearchParams({\n client_id: clientId,\n redirect_uri: finalRedirectUri,\n response_type: 'code',\n scope: scopes.join(' '),\n code_challenge: codeChallenge,\n code_challenge_method: 'S256',\n });\n\n return `${ssoBaseUrl}/oauth/authorize?${params.toString()}`;\n}\n\n/**\n * Parse authorization code from URL query params (PKCE callback)\n */\nfunction parseCodeFromQuery(): { code: string; state?: string } | null {\n if (typeof window === 'undefined') return null;\n \n const params = new URLSearchParams(window.location.search);\n const code = params.get('code');\n \n if (!code) return null;\n \n return {\n code,\n state: params.get('state') || undefined,\n };\n}\n\n/**\n * Exchange authorization code for tokens using PKCE\n */\nasync function exchangeCodeForTokens(\n ssoApiUrl: string,\n clientId: string,\n redirectUri: string,\n code: string\n): Promise<TokenPair | null> {\n try {\n // Retrieve and remove code verifier from session storage\n const codeVerifier = sessionStorage.getItem('arow_pkce_code_verifier');\n if (!codeVerifier) {\n throw new Error('Code verifier not found in session storage');\n }\n sessionStorage.removeItem('arow_pkce_code_verifier');\n\n // Build the token exchange request body\n const body = new URLSearchParams({\n grant_type: 'authorization_code',\n code,\n client_id: clientId,\n redirect_uri: redirectUri,\n code_verifier: codeVerifier,\n });\n\n const response = await fetch(`${ssoApiUrl}/oauth/token`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: body.toString(),\n });\n\n if (!response.ok) {\n throw new Error(`Token exchange failed: ${response.status} ${response.statusText}`);\n }\n\n const data = await response.json();\n \n return {\n accessToken: data.access_token || data.accessToken,\n refreshToken: data.refresh_token || data.refreshToken,\n expiresIn: data.expires_in || data.expiresIn,\n tokenType: data.token_type || data.tokenType || 'Bearer',\n };\n } catch (error) {\n console.error('Failed to exchange code for tokens:', error);\n return null;\n }\n}\n\n/**\n * Parse tokens from URL hash fragment (SSO callback - DEPRECATED, v1 backward compatibility)\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.ssoApiUrl, 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 // PRIORITY 1: Check for authorization code in query params (PKCE v2 flow)\n const codeData = parseCodeFromQuery();\n if (codeData) {\n const finalRedirectUri = config.redirectUri || `${window.location.origin}/callback`;\n const tokens = await exchangeCodeForTokens(\n config.ssoApiUrl || config.ssoBaseUrl,\n config.clientId,\n finalRedirectUri,\n codeData.code\n );\n \n if (tokens) {\n setTokens(tokens.accessToken, tokens.refreshToken);\n \n // Clean up URL - remove query params\n const cleanUrl = window.location.pathname;\n window.history.replaceState(null, '', cleanUrl);\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?.(tokens);\n startProactive();\n \n const user = parseUserFromToken(tokens.accessToken);\n setState({\n user,\n isAuthenticated: true,\n isLoading: false,\n error: null,\n });\n return;\n } else {\n // Code exchange failed\n setState({\n user: null,\n isAuthenticated: false,\n isLoading: false,\n error: 'Failed to exchange authorization code for tokens',\n });\n return;\n }\n }\n\n // PRIORITY 2: Check for tokens in URL hash (v1 implicit flow - backward compatibility)\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(async (redirectPath?: string) => {\n const authUrl = await 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 - revoke refresh token, clear local tokens\n const logout = useCallback(async () => {\n // Fire-and-forget: revoke the refresh token at SSO\n const refreshToken = getRefreshToken();\n if (refreshToken) {\n const ssoApi = config.ssoApiUrl || config.ssoBaseUrl;\n const body = new URLSearchParams({\n token: refreshToken,\n token_type_hint: 'refresh_token',\n client_id: config.clientId,\n });\n fetch(`${ssoApi}/oauth/revoke`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: body.toString(),\n }).catch(() => { /* ignore */ });\n }\n\n cancelProactiveRefresh();\n clearTokens();\n setState({\n user: null,\n isAuthenticated: false,\n isLoading: false,\n error: null,\n });\n onLogout?.();\n }, [onLogout, config.ssoApiUrl, config.ssoBaseUrl, config.clientId]);\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": "2.0.0",
3
+ "version": "2.1.1",
4
4
  "description": "Reusable auth package for ArowAuth SSO integration",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",