{"version":3,"sources":["../src/types/errors.ts","../src/utils/pkce.ts","../src/utils/token.ts","../src/utils/storage.ts","../src/utils/url.ts","../src/utils/http.ts","../src/utils/dpop.ts","../src/AuthwayClient.ts","../src/popup-callback.ts"],"names":["AuthwayError","_AuthwayError","message","code","statusCode","ConfigurationError","_ConfigurationError","ApiError","_ApiError","response","AuthenticationError","_AuthenticationError","TokenError","_TokenError","TimeoutError","_TimeoutError","MissingRefreshTokenError","_MissingRefreshTokenError","LoginRequiredError","_LoginRequiredError","PopupTimeoutError","_PopupTimeoutError","popup","PopupCancelledError","_PopupCancelledError","generateRandomString","length","charset","randomValues","x","sha256","plain","data","base64URLEncode","buffer","bytes","binary","i","generatePKCEChallenge","codeVerifier","hashed","codeChallenge","state","nonce","verifyState","receivedState","expectedState","decodeToken","token","parts","payload","decoded","base64URLDecode","error","str","base64","pad","extractUser","idToken","claims","getTokenExpiration","MemoryStorage","key","value","LocalStorageCache","SessionStorageCache","createStorage","cacheLocation","createSessionStorage","buildUrl","base","params","url","v","parseCallbackUrl","urlToParse","urlObj","http","options","method","headers","body","timeout","controller","timeoutId","errorData","contentType","post","patch","postForm","formBody","DPOP_KEY_STORAGE_KEY","getDPoPKeyPair","storage","stored","keyPair","publicKey","privateKey","err","publicJwk","privateJwk","createDPoPProof","htm","htu","accessToken","header","encodedHeader","base64UrlEncode","encodedPayload","signature","encodedSignature","input","chars","result","DEFAULT_SCOPE","AuthwayClient","config","errorDescription","isPopup","e","storageError","centralApiUrl","oauthServerUrl","redirectUri","configUrl","remoteConfig","pkce","authUrl","storedPkce","appStateStr","appState","credentials","resolve","reject","intervalId","cleanup","messageHandler","event","isLocalhost","isConfiguredOrigin","error_description","fallbackResult","syntheticEvent","logoutUrl","now","leewayMs","dpopProof","systemClaims","dynamicClaims","provider","connection","timeoutCounter","maxTimeout","timer","popupUrl","redirectUriToCheck","userId","postLogoutUri","fallbackUri","refreshToken","expiresAt","expiresIn","refreshIn","handlePopupCallback","isPopupCallback"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Base Authway error\n */\nexport class AuthwayError extends Error {\n  constructor(\n    message: string,\n    public code: string,\n    public statusCode?: number\n  ) {\n    super(message)\n    this.name = 'AuthwayError'\n    Object.setPrototypeOf(this, AuthwayError.prototype)\n  }\n}\n\n/**\n * Configuration error\n */\nexport class ConfigurationError extends AuthwayError {\n  constructor(message: string) {\n    super(message, 'configuration_error')\n    this.name = 'ConfigurationError'\n    Object.setPrototypeOf(this, ConfigurationError.prototype)\n  }\n}\n\n/**\n * Network/API error\n */\nexport class ApiError extends AuthwayError {\n  constructor(message: string, statusCode: number, public response?: any) {\n    super(message, 'api_error', statusCode)\n    this.name = 'ApiError'\n    Object.setPrototypeOf(this, ApiError.prototype)\n  }\n}\n\n/**\n * Authentication error\n */\nexport class AuthenticationError extends AuthwayError {\n  constructor(message: string, code: string = 'authentication_error') {\n    super(message, code, 401)\n    this.name = 'AuthenticationError'\n    Object.setPrototypeOf(this, AuthenticationError.prototype)\n  }\n}\n\n/**\n * Token error\n */\nexport class TokenError extends AuthwayError {\n  constructor(message: string, code: string = 'token_error') {\n    super(message, code)\n    this.name = 'TokenError'\n    Object.setPrototypeOf(this, TokenError.prototype)\n  }\n}\n\n/**\n * Timeout error\n */\nexport class TimeoutError extends AuthwayError {\n  constructor(message: string = 'Request timeout') {\n    super(message, 'timeout_error', 408)\n    this.name = 'TimeoutError'\n    Object.setPrototypeOf(this, TimeoutError.prototype)\n  }\n}\n\n/**\n * Missing refresh token error\n */\nexport class MissingRefreshTokenError extends TokenError {\n  constructor() {\n    super('No refresh token available', 'missing_refresh_token')\n    this.name = 'MissingRefreshTokenError'\n    Object.setPrototypeOf(this, MissingRefreshTokenError.prototype)\n  }\n}\n\n/**\n * Login required error\n */\nexport class LoginRequiredError extends AuthenticationError {\n  constructor(message: string = 'Login required') {\n    super(message, 'login_required')\n    this.name = 'LoginRequiredError'\n    Object.setPrototypeOf(this, LoginRequiredError.prototype)\n  }\n}\n\n/**\n * Popup timeout error\n */\nexport class PopupTimeoutError extends AuthwayError {\n  constructor(\n    message: string = 'Popup window timed out',\n    public popup: Window | null = null\n  ) {\n    super(message, 'timeout', 408)\n    this.name = 'PopupTimeoutError'\n    Object.setPrototypeOf(this, PopupTimeoutError.prototype)\n  }\n\n  toJSON() {\n    return {\n      name: this.name,\n      message: this.message,\n      code: this.code,\n      statusCode: this.statusCode\n    }\n  }\n}\n\n/**\n * Popup cancelled error\n */\nexport class PopupCancelledError extends AuthwayError {\n  constructor(\n    message: string = 'Popup window was closed',\n    public popup: Window | null = null\n  ) {\n    super(message, 'cancelled')\n    this.name = 'PopupCancelledError'\n    Object.setPrototypeOf(this, PopupCancelledError.prototype)\n  }\n\n  toJSON() {\n    return {\n      name: this.name,\n      message: this.message,\n      code: this.code\n    }\n  }\n}\n","import { PKCEChallenge } from '../types'\n\n/**\n * Generate cryptographically random string\n */\nfunction generateRandomString(length: number): string {\n  const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~'\n  const randomValues = new Uint8Array(length)\n\n  if (typeof window !== 'undefined' && window.crypto) {\n    window.crypto.getRandomValues(randomValues)\n  } else if (typeof global !== 'undefined' && global.crypto) {\n    global.crypto.getRandomValues(randomValues)\n  } else {\n    throw new Error('No secure random number generator available')\n  }\n\n  return Array.from(randomValues)\n    .map(x => charset[x % charset.length])\n    .join('')\n}\n\n/**\n * SHA-256 hash\n */\nasync function sha256(plain: string): Promise<ArrayBuffer> {\n  const encoder = new TextEncoder()\n  const data = encoder.encode(plain)\n\n  if (typeof window !== 'undefined' && window.crypto.subtle) {\n    return window.crypto.subtle.digest('SHA-256', data)\n  } else if (typeof global !== 'undefined' && global.crypto?.subtle) {\n    return global.crypto.subtle.digest('SHA-256', data)\n  }\n\n  throw new Error('No crypto.subtle available')\n}\n\n/**\n * Base64 URL encode\n */\nfunction base64URLEncode(buffer: ArrayBuffer): string {\n  const bytes = new Uint8Array(buffer)\n  let binary = ''\n\n  for (let i = 0; i < bytes.byteLength; i++) {\n    binary += String.fromCharCode(bytes[i])\n  }\n\n  return btoa(binary)\n    .replace(/\\+/g, '-')\n    .replace(/\\//g, '_')\n    .replace(/=/g, '')\n}\n\n/**\n * Generate PKCE challenge\n */\nexport async function generatePKCEChallenge(): Promise<PKCEChallenge> {\n  const codeVerifier = generateRandomString(128)\n  const hashed = await sha256(codeVerifier)\n  const codeChallenge = base64URLEncode(hashed)\n  const state = generateRandomString(32)\n  const nonce = generateRandomString(32)\n\n  return {\n    codeVerifier,\n    codeChallenge,\n    state,\n    nonce\n  }\n}\n\n/**\n * Verify state parameter\n */\nexport function verifyState(receivedState: string, expectedState: string): boolean {\n  return receivedState === expectedState\n}\n","import { TokenClaims, User } from '../types'\nimport { TokenError } from '../types/errors'\n\n/**\n * Decode JWT token\n */\nexport function decodeToken(token: string): TokenClaims {\n  try {\n    const parts = token.split('.')\n    if (parts.length !== 3) {\n      throw new TokenError('Invalid token format')\n    }\n\n    const payload = parts[1]\n    const decoded = base64URLDecode(payload)\n    return JSON.parse(decoded)\n  } catch (error) {\n    throw new TokenError(`Failed to decode token: ${error}`)\n  }\n}\n\n/**\n * Base64 URL decode with UTF-8 support\n */\nfunction base64URLDecode(str: string): string {\n  // Replace URL-safe characters\n  let base64 = str.replace(/-/g, '+').replace(/_/g, '/')\n\n  // Pad with '=' to make length multiple of 4\n  const pad = base64.length % 4\n  if (pad) {\n    if (pad === 1) {\n      throw new Error('Invalid base64 string')\n    }\n    base64 += new Array(5 - pad).join('=')\n  }\n\n  // Decode base64 to binary string\n  const binary = atob(base64)\n\n  // Convert binary string to UTF-8\n  // Handle multi-byte UTF-8 characters properly\n  const bytes = new Uint8Array(binary.length)\n  for (let i = 0; i < binary.length; i++) {\n    bytes[i] = binary.charCodeAt(i)\n  }\n\n  // Decode UTF-8 bytes to string\n  return new TextDecoder('utf-8').decode(bytes)\n}\n\n/**\n * Extract user from ID token\n */\nexport function extractUser(idToken: string): User {\n  const claims = decodeToken(idToken)\n\n  return {\n    ...claims,\n    sub: claims.sub,\n    email: claims.email || '',\n    email_verified: claims.email_verified || false,\n    name: claims.name,\n    given_name: claims.given_name,\n    family_name: claims.family_name,\n    picture: claims.picture,\n    locale: claims.locale,\n    zoneinfo: claims.zoneinfo,\n    updated_at: claims.updated_at,\n  }\n}\n\n/**\n * Check if token is expired\n */\nexport function isTokenExpired(token: string, leeway: number = 60): boolean {\n  try {\n    const claims = decodeToken(token)\n    const now = Math.floor(Date.now() / 1000)\n    return claims.exp < (now + leeway)\n  } catch {\n    return true\n  }\n}\n\n/**\n * Get token expiration time\n */\nexport function getTokenExpiration(token: string): number {\n  const claims = decodeToken(token)\n  return claims.exp * 1000 // Convert to milliseconds\n}\n\n/**\n * Verify token audience\n */\nexport function verifyAudience(token: string, expectedAudience: string): boolean {\n  try {\n    const claims = decodeToken(token)\n    const aud = Array.isArray(claims.aud) ? claims.aud : [claims.aud]\n    return aud.includes(expectedAudience)\n  } catch {\n    return false\n  }\n}\n\n/**\n * Verify token issuer\n */\nexport function verifyIssuer(token: string, expectedIssuer: string): boolean {\n  try {\n    const claims = decodeToken(token)\n    return claims.iss === expectedIssuer\n  } catch {\n    return false\n  }\n}\n","/**\n * Storage interface for token cache\n */\nexport interface IStorage {\n  get(key: string): string | null\n  set(key: string, value: string): void\n  remove(key: string): void\n  clear(): void\n}\n\n/**\n * Memory storage (default, most secure)\n */\nexport class MemoryStorage implements IStorage {\n  private store: Map<string, string> = new Map()\n\n  get(key: string): string | null {\n    return this.store.get(key) || null\n  }\n\n  set(key: string, value: string): void {\n    this.store.set(key, value)\n  }\n\n  remove(key: string): void {\n    this.store.delete(key)\n  }\n\n  clear(): void {\n    this.store.clear()\n  }\n}\n\n/**\n * LocalStorage wrapper\n */\nexport class LocalStorageCache implements IStorage {\n  private prefix = 'authway.'\n\n  get(key: string): string | null {\n    if (typeof window === 'undefined') return null\n    try {\n      return window.localStorage.getItem(this.prefix + key)\n    } catch {\n      return null\n    }\n  }\n\n  set(key: string, value: string): void {\n    if (typeof window === 'undefined') return\n    try {\n      window.localStorage.setItem(this.prefix + key, value)\n    } catch (error) {\n      console.warn('Failed to write to localStorage:', error)\n    }\n  }\n\n  remove(key: string): void {\n    if (typeof window === 'undefined') return\n    try {\n      window.localStorage.removeItem(this.prefix + key)\n    } catch {\n      // Ignore errors\n    }\n  }\n\n  clear(): void {\n    if (typeof window === 'undefined') return\n    try {\n      const keys = Object.keys(window.localStorage)\n      keys.forEach(key => {\n        if (key.startsWith(this.prefix)) {\n          window.localStorage.removeItem(key)\n        }\n      })\n    } catch {\n      // Ignore errors\n    }\n  }\n}\n\n/**\n * SessionStorage wrapper for OAuth state\n */\nexport class SessionStorageCache implements IStorage {\n  private prefix = 'authway.'\n\n  get(key: string): string | null {\n    if (typeof window === 'undefined') return null\n    try {\n      return window.sessionStorage.getItem(this.prefix + key)\n    } catch {\n      return null\n    }\n  }\n\n  set(key: string, value: string): void {\n    if (typeof window === 'undefined') return\n    try {\n      window.sessionStorage.setItem(this.prefix + key, value)\n    } catch (error) {\n      console.warn('Failed to write to sessionStorage:', error)\n    }\n  }\n\n  remove(key: string): void {\n    if (typeof window === 'undefined') return\n    try {\n      window.sessionStorage.removeItem(this.prefix + key)\n    } catch {\n      // Ignore errors\n    }\n  }\n\n  clear(): void {\n    if (typeof window === 'undefined') return\n    try {\n      const keys = Object.keys(window.sessionStorage)\n      keys.forEach(key => {\n        if (key.startsWith(this.prefix)) {\n          window.sessionStorage.removeItem(key)\n        }\n      })\n    } catch {\n      // Ignore errors\n    }\n  }\n}\n\n/**\n * Create storage based on cache location\n */\nexport function createStorage(cacheLocation: 'memory' | 'localstorage'): IStorage {\n  if (cacheLocation === 'localstorage') {\n    return new LocalStorageCache()\n  }\n  return new MemoryStorage()\n}\n\n/**\n * Create session storage for OAuth state (PKCE, appState)\n */\nexport function createSessionStorage(): IStorage {\n  return new SessionStorageCache()\n}\n","/**\n * Build URL with query parameters\n */\nexport function buildUrl(base: string, params: Record<string, any>): string {\n  const url = new URL(base)\n\n  Object.entries(params).forEach(([key, value]) => {\n    if (value !== undefined && value !== null) {\n      if (Array.isArray(value)) {\n        value.forEach(v => url.searchParams.append(key, String(v)))\n      } else {\n        url.searchParams.append(key, String(value))\n      }\n    }\n  })\n\n  return url.toString()\n}\n\n/**\n * Parse query string\n */\nexport function parseQueryString(query: string): Record<string, string> {\n  const params = new URLSearchParams(query)\n  const result: Record<string, string> = {}\n\n  params.forEach((value, key) => {\n    result[key] = value\n  })\n\n  return result\n}\n\n/**\n * Get current URL without query/hash\n */\nexport function getBaseUrl(): string {\n  if (typeof window === 'undefined') return ''\n  return `${window.location.origin}${window.location.pathname}`\n}\n\n/**\n * Parse callback URL\n */\nexport function parseCallbackUrl(url?: string): { code?: string; state?: string; error?: string; error_description?: string } {\n  const urlToParse = url || (typeof window !== 'undefined' ? window.location.href : '')\n  const urlObj = new URL(urlToParse)\n\n  return {\n    code: urlObj.searchParams.get('code') || undefined,\n    state: urlObj.searchParams.get('state') || undefined,\n    error: urlObj.searchParams.get('error') || undefined,\n    error_description: urlObj.searchParams.get('error_description') || undefined\n  }\n}\n","import { ApiError, TimeoutError } from '../types/errors'\n\nexport interface HttpOptions {\n  method?: 'GET' | 'POST' | 'PATCH' | 'DELETE'\n  headers?: Record<string, string>\n  body?: any\n  timeout?: number\n}\n\n/**\n * HTTP client with timeout support\n */\nexport async function http<T = any>(url: string, options: HttpOptions = {}): Promise<T> {\n  const {\n    method = 'GET',\n    headers = {},\n    body,\n    timeout = 10000\n  } = options\n\n  const controller = new AbortController()\n  const timeoutId = setTimeout(() => controller.abort(), timeout)\n\n  try {\n    const response = await fetch(url, {\n      method,\n      headers: {\n        'Content-Type': 'application/json',\n        ...headers\n      },\n      body: body ? JSON.stringify(body) : undefined,\n      signal: controller.signal\n    })\n\n    clearTimeout(timeoutId)\n\n    if (!response.ok) {\n      const errorData = await response.json().catch(() => ({}))\n      throw new ApiError(\n        errorData.message || `HTTP ${response.status}: ${response.statusText}`,\n        response.status,\n        errorData\n      )\n    }\n\n    const contentType = response.headers.get('content-type')\n    if (contentType?.includes('application/json')) {\n      return await response.json()\n    }\n\n    // Detect HTML response (likely auth redirect after logout)\n    if (contentType?.includes('text/html')) {\n      console.warn(\n        '⚠️ Authway: Received HTML response instead of JSON.\\n' +\n        'This usually happens when React Query refetches cached queries after logout.\\n\\n' +\n        '💡 Solution: Clear React Query cache BEFORE calling logout():\\n\\n' +\n        '  const handleLogout = () => {\\n' +\n        '    queryClient.cancelQueries()\\n' +\n        '    queryClient.clear()\\n' +\n        '    logout({ returnTo: window.location.origin })\\n' +\n        '  }\\n\\n' +\n        '📚 See: @authway/react README > \"React Query와 함께 사용\"'\n      )\n    }\n\n    return await response.text() as any\n  } catch (error: any) {\n    clearTimeout(timeoutId)\n\n    if (error.name === 'AbortError') {\n      throw new TimeoutError()\n    }\n\n    if (error instanceof ApiError) {\n      throw error\n    }\n\n    // Detect JSON parse error on HTML content\n    if (error.message?.includes('Unexpected token') && error.message?.includes('<')) {\n      console.warn(\n        '⚠️ Authway: JSON parse error on HTML response.\\n' +\n        'This usually happens when React Query refetches cached queries after logout.\\n\\n' +\n        '💡 Solution: Clear React Query cache BEFORE calling logout():\\n\\n' +\n        '  const handleLogout = () => {\\n' +\n        '    queryClient.cancelQueries()\\n' +\n        '    queryClient.clear()\\n' +\n        '    logout({ returnTo: window.location.origin })\\n' +\n        '  }\\n\\n' +\n        '📚 See: @authway/react README > \"React Query와 함께 사용\"'\n      )\n    }\n\n    throw new ApiError(error.message || 'Network request failed', 0)\n  }\n}\n\n/**\n * GET request\n */\nexport function get<T = any>(url: string, headers?: Record<string, string>, timeout?: number): Promise<T> {\n  return http<T>(url, { method: 'GET', headers, timeout })\n}\n\n/**\n * POST request\n */\nexport function post<T = any>(url: string, body?: any, headers?: Record<string, string>, timeout?: number): Promise<T> {\n  return http<T>(url, { method: 'POST', body, headers, timeout })\n}\n\n/**\n * PATCH request\n */\nexport function patch<T = any>(url: string, body?: any, headers?: Record<string, string>, timeout?: number): Promise<T> {\n  return http<T>(url, { method: 'PATCH', body, headers, timeout })\n}\n\n/**\n * POST form data (application/x-www-form-urlencoded)\n * Used for OAuth token endpoints\n */\nexport async function postForm<T = any>(url: string, data: Record<string, string>, headers?: Record<string, string>, timeout?: number): Promise<T> {\n  const controller = new AbortController()\n  const timeoutId = setTimeout(() => controller.abort(), timeout || 10000)\n\n  try {\n    const formBody = Object.keys(data)\n      .map(key => encodeURIComponent(key) + '=' + encodeURIComponent(data[key]))\n      .join('&')\n\n    const response = await fetch(url, {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/x-www-form-urlencoded',\n        ...headers\n      },\n      body: formBody,\n      signal: controller.signal\n    })\n\n    clearTimeout(timeoutId)\n\n    if (!response.ok) {\n      const errorData = await response.json().catch(() => ({}))\n      throw new ApiError(\n        errorData.error_description || errorData.message || `HTTP ${response.status}: ${response.statusText}`,\n        response.status,\n        errorData\n      )\n    }\n\n    const contentType = response.headers.get('content-type')\n    if (contentType?.includes('application/json')) {\n      return await response.json()\n    }\n\n    // Detect HTML response (likely auth redirect after logout)\n    if (contentType?.includes('text/html')) {\n      console.warn(\n        '⚠️ Authway: Received HTML response instead of JSON.\\n' +\n        'This usually happens when React Query refetches cached queries after logout.\\n\\n' +\n        '💡 Solution: Clear React Query cache BEFORE calling logout():\\n\\n' +\n        '  const handleLogout = () => {\\n' +\n        '    queryClient.cancelQueries()\\n' +\n        '    queryClient.clear()\\n' +\n        '    logout({ returnTo: window.location.origin })\\n' +\n        '  }\\n\\n' +\n        '📚 See: @authway/react README > \"React Query와 함께 사용\"'\n      )\n    }\n\n    return await response.text() as any\n  } catch (error: any) {\n    clearTimeout(timeoutId)\n\n    if (error.name === 'AbortError') {\n      throw new TimeoutError()\n    }\n\n    if (error instanceof ApiError) {\n      throw error\n    }\n\n    // Detect JSON parse error on HTML content\n    if (error.message?.includes('Unexpected token') && error.message?.includes('<')) {\n      console.warn(\n        '⚠️ Authway: JSON parse error on HTML response.\\n' +\n        'This usually happens when React Query refetches cached queries after logout.\\n\\n' +\n        '💡 Solution: Clear React Query cache BEFORE calling logout():\\n\\n' +\n        '  const handleLogout = () => {\\n' +\n        '    queryClient.cancelQueries()\\n' +\n        '    queryClient.clear()\\n' +\n        '    logout({ returnTo: window.location.origin })\\n' +\n        '  }\\n\\n' +\n        '📚 See: @authway/react README > \"React Query와 함께 사용\"'\n      )\n    }\n\n    throw new ApiError(error.message || 'Network request failed', 0)\n  }\n}\n","/**\n * DPoP (Demonstrating Proof-of-Possession) Utilities\n * RFC 9449: https://datatracker.ietf.org/doc/html/rfc9449\n */\n\nimport { IStorage } from './storage'\n\nconst DPOP_KEY_STORAGE_KEY = 'authway_dpop_key'\n\n/**\n * DPoP key pair stored as JWK\n */\ninterface DPoPKeyPair {\n  publicKey: JsonWebKey\n  privateKey: JsonWebKey\n}\n\n/**\n * Generate or retrieve DPoP key pair\n */\nexport async function getDPoPKeyPair(storage: IStorage): Promise<CryptoKeyPair> {\n  // Try to load existing key pair\n  const stored = storage.get(DPOP_KEY_STORAGE_KEY)\n\n  if (stored) {\n    try {\n      const keyPair: DPoPKeyPair = JSON.parse(stored)\n\n      // Import keys from JWK\n      const publicKey = await crypto.subtle.importKey(\n        'jwk',\n        keyPair.publicKey,\n        { name: 'ECDSA', namedCurve: 'P-256' },\n        true,\n        ['verify']\n      )\n\n      const privateKey = await crypto.subtle.importKey(\n        'jwk',\n        keyPair.privateKey,\n        { name: 'ECDSA', namedCurve: 'P-256' },\n        true,\n        ['sign']\n      )\n\n      return { publicKey, privateKey }\n    } catch (err) {\n      // If import fails, generate new keys\n      console.warn('Failed to import DPoP keys, generating new ones:', err)\n    }\n  }\n\n  // Generate new key pair\n  const keyPair = await crypto.subtle.generateKey(\n    { name: 'ECDSA', namedCurve: 'P-256' },\n    true,\n    ['sign', 'verify']\n  )\n\n  // Export and store as JWK\n  const publicJwk = await crypto.subtle.exportKey('jwk', keyPair.publicKey)\n  const privateJwk = await crypto.subtle.exportKey('jwk', keyPair.privateKey)\n\n  storage.set(DPOP_KEY_STORAGE_KEY, JSON.stringify({\n    publicKey: publicJwk,\n    privateKey: privateJwk\n  }))\n\n  return keyPair\n}\n\n/**\n * Create DPoP proof JWT\n */\nexport async function createDPoPProof(\n  keyPair: CryptoKeyPair,\n  htm: string, // HTTP method (GET, POST, etc.)\n  htu: string, // HTTP URI (without query/fragment)\n  accessToken?: string // Optional: include 'ath' claim when using access token\n): Promise<string> {\n  const publicJwk = await crypto.subtle.exportKey('jwk', keyPair.publicKey)\n\n  // DPoP JWT header\n  const header = {\n    typ: 'dpop+jwt',\n    alg: 'ES256',\n    jwk: {\n      kty: publicJwk.kty,\n      crv: publicJwk.crv,\n      x: publicJwk.x,\n      y: publicJwk.y\n    }\n  }\n\n  // DPoP JWT payload\n  const payload: any = {\n    jti: generateRandomString(16), // Unique ID\n    htm,\n    htu,\n    iat: Math.floor(Date.now() / 1000)\n  }\n\n  // Add 'ath' (access token hash) if access token provided\n  if (accessToken) {\n    payload.ath = await hashAccessToken(accessToken)\n  }\n\n  // Encode header and payload\n  const encodedHeader = base64UrlEncode(JSON.stringify(header))\n  const encodedPayload = base64UrlEncode(JSON.stringify(payload))\n\n  // Sign\n  const message = `${encodedHeader}.${encodedPayload}`\n  const encoder = new TextEncoder()\n  const data = encoder.encode(message)\n\n  const signature = await crypto.subtle.sign(\n    { name: 'ECDSA', hash: 'SHA-256' },\n    keyPair.privateKey,\n    data\n  )\n\n  const encodedSignature = base64UrlEncode(new Uint8Array(signature))\n\n  return `${message}.${encodedSignature}`\n}\n\n/**\n * Hash access token for 'ath' claim\n */\nasync function hashAccessToken(token: string): Promise<string> {\n  const encoder = new TextEncoder()\n  const data = encoder.encode(token)\n  const hash = await crypto.subtle.digest('SHA-256', data)\n  return base64UrlEncode(new Uint8Array(hash))\n}\n\n/**\n * Base64 URL encode\n */\nfunction base64UrlEncode(input: Uint8Array | string): string {\n  let base64: string\n\n  if (typeof input === 'string') {\n    base64 = btoa(input)\n  } else {\n    const binary = String.fromCharCode(...input)\n    base64 = btoa(binary)\n  }\n\n  return base64\n    .replace(/\\+/g, '-')\n    .replace(/\\//g, '_')\n    .replace(/=/g, '')\n}\n\n/**\n * Generate random string\n */\nfunction generateRandomString(length: number): string {\n  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'\n  const randomValues = new Uint8Array(length)\n  crypto.getRandomValues(randomValues)\n\n  let result = ''\n  for (let i = 0; i < length; i++) {\n    result += chars[randomValues[i] % chars.length]\n  }\n\n  return result\n}\n\n/**\n * Clear DPoP keys from storage\n */\nexport function clearDPoPKeys(storage: IStorage): void {\n  storage.remove(DPOP_KEY_STORAGE_KEY)\n}\n","import {\n  AuthwayConfig,\n  NormalizedConfig,\n  RedirectLoginOptions,\n  PasswordCredentials,\n  PopupLoginOptions,\n  LogoutOptions,\n  AuthResult,\n  RedirectLoginResult,\n  GetTokenOptions,\n  User,\n  Claims,\n  Identity,\n  LinkAccountOptions,\n  SessionState,\n  PKCEChallenge,\n  ConfigurationError,\n  AuthenticationError,\n  LoginRequiredError,\n  MissingRefreshTokenError,\n  PopupTimeoutError,\n  PopupCancelledError\n} from './types'\nimport {\n  generatePKCEChallenge,\n  verifyState,\n  decodeToken,\n  extractUser,\n  getTokenExpiration,\n  createStorage,\n  IStorage,\n  buildUrl,\n  parseCallbackUrl,\n  post,\n  postForm,\n  patch,\n  createSessionStorage,\n  getDPoPKeyPair,\n  createDPoPProof\n} from './utils'\n\nconst DEFAULT_SCOPE = 'openid profile email'\n\n/**\n * Main Authway authentication client\n */\nexport class AuthwayClient {\n  private config: NormalizedConfig\n  private storage: IStorage\n  private sessionStorage: IStorage\n  private tokenRefreshTimer?: number\n  private dpopKeyPair: CryptoKeyPair | null = null\n\n  // In-memory cache\n  private cache = {\n    user: null as User | null,\n    accessToken: null as string | null,\n    idToken: null as string | null,\n    refreshToken: null as string | null,\n    expiresAt: null as number | null\n  }\n\n  private configReady: Promise<void>\n\n  /**\n   * Static method to handle popup callback context.\n   * Call this before creating AuthwayClient to check if running in a popup.\n   * If in popup context with OAuth params, sends postMessage and closes window.\n   *\n   * @returns true if popup callback was handled (window will close), false otherwise\n   */\n  static handlePopupCallback(): boolean {\n    if (typeof window === 'undefined') return false\n\n    const params = new URLSearchParams(window.location.search)\n    const code = params.get('code')\n    const state = params.get('state')\n    const error = params.get('error')\n    const errorDescription = params.get('error_description')\n\n    // Check if we have OAuth params\n    const hasOAuthParams = (code && state) || error\n\n    if (!hasOAuthParams) return false\n\n    // Check if we're in a popup (window.opener exists)\n    let isPopup = false\n    try {\n      isPopup = !!(window.opener && !window.opener.closed)\n    } catch (e) {\n      // COOP policy may block access to window.opener\n      // Try alternative detection via window.name or sessionStorage\n      isPopup = window.name === 'authway-login' ||\n                sessionStorage.getItem('authway_popup_context') === 'true'\n    }\n\n    if (!isPopup) return false\n\n    // We're in a popup with OAuth params - send message to parent and close\n    try {\n      const message = {\n        type: 'authway-callback',\n        code,\n        state,\n        error,\n        error_description: errorDescription\n      }\n\n      // Send to parent window\n      window.opener.postMessage(message, window.location.origin)\n\n      console.log('✅ Authway: Popup callback handled automatically')\n\n      // Close the popup\n      window.close()\n\n      return true\n    } catch (e) {\n      console.warn('⚠️ Authway: Failed to send postMessage to parent window:', e)\n\n      // Fallback: Store in localStorage for parent to pick up\n      try {\n        localStorage.setItem('authway_popup_result', JSON.stringify({\n          type: 'authway-callback',\n          code,\n          state,\n          error,\n          error_description: errorDescription,\n          timestamp: Date.now()\n        }))\n        window.close()\n        return true\n      } catch (storageError) {\n        console.error('⚠️ Authway: Fallback storage also failed:', storageError)\n      }\n\n      return false\n    }\n  }\n\n  constructor(config: AuthwayConfig) {\n    this.config = this.normalizeConfig(config)\n    this.storage = createStorage(this.config.cacheLocation)\n    this.sessionStorage = createSessionStorage()\n    this.loadFromStorage()\n\n    // Initialize DPoP if enabled\n    if (this.config.useDPoP) {\n      this.initializeDPoP()\n    }\n    \n    // Fetch remote config (async)\n    this.configReady = this.fetchRemoteConfig()\n  }\n\n  /**\n   * Wait for client to be ready (config loaded)\n   */\n  async waitForReady(): Promise<void> {\n    await this.configReady\n  }\n\n  /**\n   * Initialize DPoP key pair\n   */\n  private async initializeDPoP() {\n    try {\n      this.dpopKeyPair = await getDPoPKeyPair(this.storage)\n    } catch (err) {\n      console.error('Failed to initialize DPoP:', err)\n    }\n  }\n\n  // ==========================================\n  // Configuration\n  // ==========================================\n\n  private normalizeConfig(config: AuthwayConfig): NormalizedConfig {\n    if (!config.domain) {\n      throw new ConfigurationError('domain is required - this should be your Central API URL (e.g., http://localhost:8080)')\n    }\n\n    if (!config.clientId) {\n      throw new ConfigurationError('clientId is required')\n    }\n\n    // Normalize domain (Central API URL)\n    let centralApiUrl = config.domain\n    if (!centralApiUrl.startsWith('http://') && !centralApiUrl.startsWith('https://')) {\n      centralApiUrl = `https://${centralApiUrl}`\n    }\n\n    // Support legacy authwayUrl (deprecated)\n    if (config.authwayUrl) {\n      console.warn('⚠️ authwayUrl is deprecated. Use \"domain\" instead to specify Central API URL.')\n      centralApiUrl = config.authwayUrl\n    }\n\n    // Auto-detect OAuth server URL (Hydra) from Central API URL\n    // For local dev: http://localhost:8080 or :8081 -> http://localhost:4444\n    // For production: Use oauthServerUrl if provided, otherwise same as Central API\n    let oauthServerUrl = config.oauthServerUrl || centralApiUrl\n    if (oauthServerUrl.includes(':8080') || oauthServerUrl.includes(':8081')) {\n      oauthServerUrl = oauthServerUrl.replace(/:(8080|8081)/, ':4444')\n    }\n\n    let redirectUri = config.redirectUri\n    if (!redirectUri && typeof window !== 'undefined') {\n      redirectUri = window.location.origin\n    }\n    if (!redirectUri) {\n      console.warn(\n        '⚠️ Authway: No redirectUri configured and window.location.origin not available.\\n' +\n        'Users may land on auth server after login/logout. Set redirectUri in config.'\n      )\n      redirectUri = ''\n    }\n\n    // Configuration info logging\n    if (centralApiUrl.includes(':8081')) {\n      console.log(\n        '✅ Using Auth Backend (port 8081) as API endpoint.\\n' +\n        'Auth Backend will proxy API calls to Central API (port 8080) and handle CORS.'\n      )\n    } else if (centralApiUrl.includes(':8080')) {\n      console.warn(\n        '⚠️ WARNING: domain is set to port 8080 (Central API).\\n' +\n        'Direct access to Central API may have CORS issues for browser apps.\\n' +\n        'For SPAs, consider using Auth Backend (port 8081) which provides CORS support.\\n' +\n        'Recommended config: { domain: \"http://localhost:8081\", ... }'\n      )\n    }\n\n    return {\n      domain: oauthServerUrl,        // OAuth server URL (Hydra) - for backwards compatibility\n      oauthServerUrl,                // OAuth server URL (Hydra) - new field\n      centralApiUrl,                 // Central API URL - new field\n      authwayUrl: centralApiUrl,     // Deprecated - kept for backwards compatibility\n      clientId: config.clientId,\n      redirectUri,\n      audience: config.audience,\n      scope: config.scope || DEFAULT_SCOPE,\n      useRefreshTokens: config.useRefreshTokens ?? true,\n      cacheLocation: config.cacheLocation || 'localstorage',\n      tenantId: config.tenantId,\n      enableDynamicClaims: config.enableDynamicClaims ?? true,\n      claimsUpdateInterval: config.claimsUpdateInterval || 0,\n      leeway: config.leeway || 60,\n      maxAge: config.maxAge || 86400,\n      useDPoP: config.useDPoP || false\n    }\n  }\n\n  /**\n   * Fetch remote configuration from Central API\n   * Allows dynamic discovery of OAuth server and other endpoints\n   */\n  private async fetchRemoteConfig(): Promise<void> {\n    try {\n      const configUrl = `${this.config.centralApiUrl}/.well-known/authway-config`\n      const response = await fetch(configUrl)\n\n      if (response.ok) {\n        const remoteConfig = await response.json()\n\n        // Update config with remote values\n        if (remoteConfig.oauth_url) {\n          this.config.oauthServerUrl = remoteConfig.oauth_url\n          this.config.domain = remoteConfig.oauth_url  // Backwards compatibility\n        }\n        if (remoteConfig.api_url) {\n          this.config.centralApiUrl = remoteConfig.api_url\n          this.config.authwayUrl = remoteConfig.api_url  // Backwards compatibility\n        }\n\n        console.log('✅ Authway config loaded:', {\n          oauth_url: this.config.oauthServerUrl,\n          api_url: this.config.centralApiUrl\n        })\n      }\n    } catch (err) {\n      // Silently fail - use default config\n      console.warn('Failed to fetch remote config, using defaults:', err)\n    }\n  }\n\n  // ==========================================\n  // OAuth Flow\n  // ==========================================\n\n  /**\n   * Redirect to Authway hosted login\n   */\n  async loginWithRedirect(options: RedirectLoginOptions = {}): Promise<void> {\n    const pkce = await generatePKCEChallenge()\n\n    // Store PKCE challenge, redirect URI, and app state in sessionStorage\n    this.sessionStorage.set('pkce', JSON.stringify(pkce))\n    this.sessionStorage.set('redirectUri', options.redirectUri || this.config.redirectUri)\n    if (options.appState) {\n      this.sessionStorage.set('appState', JSON.stringify(options.appState))\n    }\n\n    const authUrl = this.buildAuthorizationUrl(pkce, options)\n\n    if (typeof window !== 'undefined') {\n      window.location.assign(authUrl)\n    }\n  }\n\n  /**\n   * Handle OAuth callback\n   */\n  async handleRedirectCallback(url?: string): Promise<RedirectLoginResult> {\n    const params = parseCallbackUrl(url)\n\n    if (params.error) {\n      throw new AuthenticationError(\n        params.error_description || params.error,\n        params.error\n      )\n    }\n\n    if (!params.code || !params.state) {\n      throw new AuthenticationError('Missing code or state parameter')\n    }\n\n    // Verify state from sessionStorage\n    const storedPkce = this.sessionStorage.get('pkce')\n    if (!storedPkce) {\n      throw new AuthenticationError('No PKCE challenge found')\n    }\n\n    const pkce: PKCEChallenge = JSON.parse(storedPkce)\n    if (!verifyState(params.state, pkce.state)) {\n      throw new AuthenticationError('State mismatch')\n    }\n\n    // Get redirect URI from sessionStorage\n    const redirectUri = this.sessionStorage.get('redirectUri') || this.config.redirectUri\n\n    // Exchange code for tokens\n    const result = await this.exchangeCodeForTokens(params.code, pkce.codeVerifier, redirectUri)\n\n    // Get app state from sessionStorage\n    const appStateStr = this.sessionStorage.get('appState')\n    const appState = appStateStr ? JSON.parse(appStateStr) : undefined\n\n    // Clean up sessionStorage\n    this.sessionStorage.remove('pkce')\n    this.sessionStorage.remove('redirectUri')\n    this.sessionStorage.remove('appState')\n\n    // Save tokens\n    this.saveTokens(result)\n\n    return {\n      ...result,\n      appState\n    }\n  }\n\n  /**\n   * Login with password (custom UI)\n   */\n  async loginWithPassword(credentials: PasswordCredentials): Promise<AuthResult> {\n    const url = `${this.config.centralApiUrl}/api/v1/auth/login`\n\n    const response = await post<any>(url, {\n      email: credentials.email,\n      password: credentials.password,\n      tenant_id: credentials.tenantId || this.config.tenantId,\n      client_id: this.config.clientId,\n      scope: this.config.scope\n    })\n\n    const result: AuthResult = {\n      accessToken: response.access_token,\n      idToken: response.id_token,\n      refreshToken: response.refresh_token,\n      expiresIn: response.expires_in,\n      user: extractUser(response.id_token)\n    }\n\n    this.saveTokens(result)\n    return result\n  }\n\n  /**\n   * Login with popup - opens login UI in popup window\n   * User remains on the app, popup closes automatically after auth\n   */\n  async loginWithPopup(options: PopupLoginOptions = {}): Promise<AuthResult> {\n    const pkce = await generatePKCEChallenge()\n\n    // Store PKCE challenge in sessionStorage (for when popup redirects back)\n    this.sessionStorage.set('pkce_popup', JSON.stringify(pkce))\n\n    // Build authorization URL\n    const authUrl = this.buildAuthorizationUrl(pkce, options)\n\n    // Open popup window\n    const popup = window.open(\n      authUrl,\n      'authway-login',\n      'width=500,height=700,scrollbars=yes,location=no,toolbar=no,menubar=no'\n    )\n\n    if (!popup) {\n      this.sessionStorage.remove('pkce_popup')\n      throw new AuthenticationError('Popup was blocked. Please allow popups for this site.')\n    }\n\n    // Wait for popup to complete OAuth flow\n    return new Promise((resolve, reject) => {\n      let timeoutId: number | undefined\n      let intervalId: number | undefined\n\n      // Cleanup function\n      const cleanup = () => {\n        if (timeoutId) clearTimeout(timeoutId)\n        if (intervalId) clearInterval(intervalId)\n        window.removeEventListener('message', messageHandler)\n      }\n\n      // Timeout handler\n      timeoutId = window.setTimeout(() => {\n        cleanup()\n        try {\n          popup.close()\n        } catch (err) {\n          // Ignore COOP error on close\n        }\n        this.sessionStorage.remove('pkce_popup')\n        reject(new PopupTimeoutError('Login timeout', popup))\n      }, 300000) // 5 minutes\n\n      // Message handler for postMessage communication (COOP-safe)\n      const messageHandler = async (event: MessageEvent) => {\n        // Security: Verify origin\n        // Allow localhost for development\n        const isLocalhost = event.origin.includes('localhost') || event.origin.includes('127.0.0.1')\n        const isConfiguredOrigin = event.origin === window.location.origin\n\n        if (!isLocalhost && !isConfiguredOrigin) {\n          return // Ignore messages from unknown origins\n        }\n\n        // Check if this is an Authway callback message\n        if (event.data && event.data.type === 'authway-callback') {\n          cleanup()\n\n          try {\n            popup.close()\n          } catch (err) {\n            // Ignore COOP error\n          }\n\n          this.sessionStorage.remove('pkce_popup')\n\n          const { code, state, error, error_description } = event.data\n\n          // Handle errors\n          if (error) {\n            return reject(new AuthenticationError(\n              error_description || error,\n              error\n            ))\n          }\n\n          if (!code || !state) {\n            return reject(new AuthenticationError('Missing code or state parameter'))\n          }\n\n          // Verify state\n          if (!verifyState(state, pkce.state)) {\n            return reject(new AuthenticationError('State mismatch'))\n          }\n\n          try {\n            // Exchange code for tokens\n            const result = await this.exchangeCodeForTokens(\n              code,\n              pkce.codeVerifier,\n              options.redirectUri || this.config.redirectUri\n            )\n\n            // Save tokens\n            this.saveTokens(result)\n\n            resolve(result)\n          } catch (err) {\n            reject(err)\n          }\n        }\n      }\n\n      // Listen for postMessage from popup\n      window.addEventListener('message', messageHandler)\n\n      // Fallback: Check if popup is closed or localStorage fallback result\n      intervalId = window.setInterval(async () => {\n        // Check localStorage fallback (for COOP-blocked scenarios)\n        try {\n          const fallbackResult = localStorage.getItem('authway_popup_result')\n          if (fallbackResult) {\n            const data = JSON.parse(fallbackResult)\n            // Check if result is recent (within 30 seconds)\n            if (Date.now() - data.timestamp < 30000) {\n              localStorage.removeItem('authway_popup_result')\n\n              // Create a synthetic MessageEvent-like object\n              const syntheticEvent = {\n                data,\n                origin: window.location.origin\n              } as MessageEvent\n\n              messageHandler(syntheticEvent)\n              return\n            } else {\n              // Old result, remove it\n              localStorage.removeItem('authway_popup_result')\n            }\n          }\n        } catch (err) {\n          // Ignore localStorage errors\n        }\n\n        // Check if popup is closed\n        try {\n          if (popup.closed) {\n            cleanup()\n            this.sessionStorage.remove('pkce_popup')\n            reject(new PopupCancelledError('Popup was closed by user', popup))\n          }\n        } catch (err) {\n          // COOP policy blocks popup.closed access - continue\n        }\n      }, 500) // Check every 500ms for faster response\n    })\n  }\n\n  /**\n   * Logout\n   */\n  logout(options: LogoutOptions = {}): void {\n    // Local only logout\n    if (options.localOnly) {\n      this.clearTokens()\n      if (this.tokenRefreshTimer) {\n        clearTimeout(this.tokenRefreshTimer)\n        this.tokenRefreshTimer = undefined\n      }\n      return\n    }\n\n    // Get ID token before clearing (needed for logout URL)\n    const idToken = this.cache.idToken\n\n    // Clear tokens\n    this.clearTokens()\n\n    // Clear refresh timer\n    if (this.tokenRefreshTimer) {\n      clearTimeout(this.tokenRefreshTimer)\n      this.tokenRefreshTimer = undefined\n    }\n\n    // Redirect to logout endpoint\n    if (typeof window !== 'undefined') {\n      const logoutUrl = this.buildLogoutUrl(options, idToken)\n      window.location.assign(logoutUrl)\n    }\n  }\n\n  // ==========================================\n  // Token Management\n  // ==========================================\n\n  /**\n   * Get valid access token (auto-refresh if needed)\n   */\n  async getAccessToken(options: GetTokenOptions = {}): Promise<string> {\n    // Use cached token if valid\n    if (!options.ignoreCache && this.cache.accessToken && this.cache.expiresAt) {\n      // Check expiration using cached expiresAt (supports opaque tokens)\n      const now = Date.now()\n      const leewayMs = (this.config.leeway || 60) * 1000\n      if (this.cache.expiresAt > (now + leewayMs)) {\n        return this.cache.accessToken\n      }\n    }\n\n    // Try to refresh\n    if (this.cache.refreshToken) {\n      await this.refreshTokens()\n      if (this.cache.accessToken) {\n        return this.cache.accessToken\n      }\n    }\n\n    throw new LoginRequiredError()\n  }\n\n  /**\n   * Get access token with popup\n   * Opens a popup to get a new access token (useful when refresh token is not available)\n   * Similar to Auth0's getAccessTokenWithPopup()\n   */\n  async getAccessTokenWithPopup(options: PopupLoginOptions = {}): Promise<string> {\n    const result = await this.loginWithPopup(options)\n    return result.accessToken\n  }\n\n  /**\n   * Get ID token\n   */\n  async getIdToken(): Promise<string> {\n    if (!this.cache.idToken) {\n      throw new LoginRequiredError()\n    }\n\n    return this.cache.idToken\n  }\n\n  /**\n   * Refresh tokens\n   */\n  async refreshTokens(): Promise<void> {\n    if (!this.cache.refreshToken) {\n      throw new MissingRefreshTokenError()\n    }\n\n    const url = `${this.config.domain}/oauth2/token`\n\n    // Add DPoP header if enabled\n    const headers: Record<string, string> = {}\n    if (this.config.useDPoP && this.dpopKeyPair) {\n      const dpopProof = await createDPoPProof(\n        this.dpopKeyPair,\n        'POST',\n        url\n      )\n      headers['DPoP'] = dpopProof\n    }\n\n    const response = await postForm<any>(url, {\n      grant_type: 'refresh_token',\n      refresh_token: this.cache.refreshToken,\n      client_id: this.config.clientId\n    }, headers)\n\n    const result: AuthResult = {\n      accessToken: response.access_token,\n      idToken: response.id_token,\n      refreshToken: response.refresh_token || this.cache.refreshToken,\n      expiresIn: response.expires_in,\n      user: extractUser(response.id_token)\n    }\n\n    this.saveTokens(result)\n  }\n\n  // ==========================================\n  // User & Claims\n  // ==========================================\n\n  /**\n   * Get current user\n   */\n  async getUser(): Promise<User | null> {\n    if (!this.cache.idToken) {\n      return null\n    }\n\n    if (!this.cache.user) {\n      this.cache.user = extractUser(this.cache.idToken)\n    }\n\n    return this.cache.user\n  }\n\n  /**\n   * Get ID token claims\n   * Similar to Auth0's getIdTokenClaims()\n   *\n   * @returns The decoded ID token payload\n   */\n  async getIdTokenClaims(): Promise<any | null> {\n    if (!this.cache.idToken) {\n      return null\n    }\n\n    return decodeToken(this.cache.idToken)\n  }\n\n  /**\n   * Get user claims (combines system claims from ID token + dynamic claims from backend)\n   */\n  async getClaims(): Promise<Claims> {\n    const user = await this.getUser()\n    if (!user) {\n      return {}\n    }\n\n    // 1. Get ALL claims from ID token (system claims)\n    const idToken = await this.getIdToken()\n    const tokenClaims = decodeToken(idToken)\n\n    // Filter out JWT-specific fields, keep only user claims\n    const systemClaims: Claims = { ...tokenClaims }\n    delete systemClaims.iss\n    delete systemClaims.aud\n    delete systemClaims.exp\n    delete systemClaims.iat\n    delete systemClaims.auth_time\n    delete systemClaims.nonce\n    delete systemClaims.at_hash\n    delete systemClaims.c_hash\n    delete systemClaims.sid\n\n    // 2. Get dynamic claims from backend API\n    try {\n      const accessToken = await this.getAccessToken()\n      const url = `${this.config.centralApiUrl}/api/v1/claims`\n\n      const response = await fetch(url, {\n        headers: {\n          Authorization: `Bearer ${accessToken}`\n        }\n      })\n\n      if (response.ok) {\n        const data = await response.json()\n        const dynamicClaims = data.claims || {}\n\n        // 3. Merge: system claims + dynamic claims (dynamic overrides system if same key)\n        return {\n          ...systemClaims,\n          ...dynamicClaims\n        }\n      }\n    } catch (err) {\n      // If backend fails, return just system claims\n      console.warn('Failed to fetch dynamic claims from backend:', err)\n    }\n\n    // Fallback: return only system claims if backend fails\n    return systemClaims\n  }\n\n  /**\n   * Update dynamic claims\n   * Note: Claims updates require re-authentication to take effect\n   * This method will automatically redirect to re-authenticate\n   */\n  async updateClaims(claims: Partial<Claims>): Promise<void> {\n    if (!this.config.enableDynamicClaims) {\n      throw new Error('Dynamic claims not enabled')\n    }\n\n    const accessToken = await this.getAccessToken()\n    const url = `${this.config.centralApiUrl}/api/v1/claims`\n\n    // Backend requires client_id and redirect_uri for OAuth flow\n    const payload = {\n      claims,\n      client_id: this.config.clientId,\n      redirect_uri: typeof window !== 'undefined' ? window.location.origin : this.config.centralApiUrl\n    }\n\n    const response = await patch<{ success: boolean; auth_url: string; message: string }>(\n      url,\n      payload,\n      { Authorization: `Bearer ${accessToken}` }\n    )\n\n    // Claims update requires re-authentication\n    // Automatically start new login flow to get updated token\n    if (response.auth_url) {\n      // Store app state before redirect\n      const appState = { returnTo: window.location.pathname }\n      this.sessionStorage.set('appState', JSON.stringify(appState))\n\n      // Redirect to re-authenticate and get new token with updated claims\n      if (typeof window !== 'undefined') {\n        window.location.href = response.auth_url\n      }\n    }\n  }\n\n  /**\n   * Update user-level claims (NO re-authentication required)\n   * Use this for user preferences, metadata, custom data\n   */\n  async updateUserClaims(claims: Partial<Claims>): Promise<void> {\n    const accessToken = await this.getAccessToken()\n    const url = `${this.config.centralApiUrl}/api/v1/claims/user`\n\n    await patch(\n      url,\n      { claims },\n      { Authorization: `Bearer ${accessToken}` }\n    )\n  }\n\n  /**\n   * Get user-level claims (claim_type='user')\n   */\n  async getUserClaims(): Promise<Claims> {\n    const accessToken = await this.getAccessToken()\n    const url = `${this.config.centralApiUrl}/api/v1/claims/user`\n\n    const response = await fetch(url, {\n      headers: {\n        Authorization: `Bearer ${accessToken}`\n      }\n    })\n\n    if (!response.ok) {\n      throw new Error('Failed to get user claims')\n    }\n\n    const data = await response.json()\n    return data.claims || {}\n  }\n\n  // ==========================================\n  // Account Linking\n  // ==========================================\n\n  /**\n   * Get linked accounts (identities)\n   * Similar to Auth0's getUser() with identities field\n   */\n  async getLinkedAccounts(): Promise<Identity[]> {\n    const accessToken = await this.getAccessToken()\n    const url = `${this.config.centralApiUrl}/api/v1/user/identities`\n\n    const response = await fetch(url, {\n      headers: {\n        Authorization: `Bearer ${accessToken}`\n      }\n    })\n\n    if (!response.ok) {\n      throw new AuthenticationError('Failed to get linked accounts')\n    }\n\n    const data = await response.json()\n    return data.identities || []\n  }\n\n  /**\n   * Link a new account (identity)\n   * Opens a popup to authenticate with another provider and link it\n   * Similar to Auth0's linkWithPopup()\n   */\n  async linkAccount(options: LinkAccountOptions): Promise<Identity> {\n    const { provider, connection, redirectUri } = options\n    const accessToken = await this.getAccessToken()\n\n    // Generate PKCE challenge for the linking flow\n    const pkce = await generatePKCEChallenge()\n    this.sessionStorage.set('pkce_link', JSON.stringify(pkce))\n\n    // Build authorization URL for account linking\n    const params = new URLSearchParams({\n      client_id: this.config.clientId,\n      response_type: 'code',\n      redirect_uri: redirectUri || this.config.redirectUri,\n      scope: this.config.scope || DEFAULT_SCOPE,\n      state: pkce.state,\n      code_challenge: pkce.codeChallenge,\n      code_challenge_method: 'S256',\n      prompt: 'login', // Force re-authentication\n      // Special parameter to indicate this is a linking flow\n      link_account: 'true',\n      // Pass current access token to backend for linking\n      access_token: accessToken\n    })\n\n    if (connection) {\n      params.set('connection', connection)\n    }\n\n    const authUrl = `${this.config.domain}/oauth2/authorize?${params.toString()}`\n\n    // Open popup\n    const popup = window.open(\n      authUrl,\n      'authway-link-account',\n      'width=500,height=700,scrollbars=yes,location=no,toolbar=no,menubar=no'\n    )\n\n    if (!popup) {\n      this.sessionStorage.remove('pkce_link')\n      throw new AuthenticationError('Popup was blocked. Please allow popups for this site.')\n    }\n\n    // Wait for popup to complete\n    return new Promise((resolve, reject) => {\n      const checkInterval = 100\n      let timeoutCounter = 0\n      const maxTimeout = 300000 // 5 minutes\n\n      const timer = setInterval(async () => {\n        timeoutCounter += checkInterval\n\n        if (popup.closed) {\n          clearInterval(timer)\n          this.sessionStorage.remove('pkce_link')\n          return reject(new PopupCancelledError('Popup was closed by user', popup))\n        }\n\n        if (timeoutCounter >= maxTimeout) {\n          clearInterval(timer)\n          popup.close()\n          this.sessionStorage.remove('pkce_link')\n          return reject(new PopupTimeoutError('Account linking timeout', popup))\n        }\n\n        try {\n          const popupUrl = popup.location.href\n          const redirectUriToCheck = redirectUri || this.config.redirectUri\n\n          if (popupUrl.startsWith(redirectUriToCheck)) {\n            clearInterval(timer)\n            const params = parseCallbackUrl(popupUrl)\n            popup.close()\n            this.sessionStorage.remove('pkce_link')\n\n            if (params.error) {\n              return reject(new AuthenticationError(\n                params.error_description || params.error,\n                params.error\n              ))\n            }\n\n            if (!params.code || !params.state) {\n              return reject(new AuthenticationError('Missing code or state parameter'))\n            }\n\n            if (!verifyState(params.state, pkce.state)) {\n              return reject(new AuthenticationError('State mismatch'))\n            }\n\n            try {\n              // Exchange code for the linked identity info\n              const url = `${this.config.centralApiUrl}/api/v1/user/identities/link`\n              const response = await post<any>(url, {\n                code: params.code,\n                code_verifier: pkce.codeVerifier,\n                provider: provider\n              }, {\n                Authorization: `Bearer ${accessToken}`\n              })\n\n              resolve(response.identity)\n            } catch (err) {\n              reject(err)\n            }\n          }\n        } catch (err) {\n          // Can't access popup.location.href (cross-origin)\n          // Continue polling\n        }\n      }, checkInterval)\n    })\n  }\n\n  /**\n   * Unlink an account (identity)\n   * Similar to Auth0's unlinkUser()\n   */\n  async unlinkAccount(provider: string, userId: string): Promise<void> {\n    const accessToken = await this.getAccessToken()\n    const url = `${this.config.centralApiUrl}/api/v1/user/identities/${provider}/${userId}`\n\n    const response = await fetch(url, {\n      method: 'DELETE',\n      headers: {\n        Authorization: `Bearer ${accessToken}`\n      }\n    })\n\n    if (!response.ok) {\n      const data = await response.json().catch(() => ({}))\n      throw new AuthenticationError(\n        data.error_description || 'Failed to unlink account',\n        data.error || 'unlink_failed'\n      )\n    }\n  }\n\n  // ==========================================\n  // Session\n  // ==========================================\n\n  /**\n   * Check if authenticated\n   */\n  async isAuthenticated(): Promise<boolean> {\n    try {\n      await this.getAccessToken()\n      return true\n    } catch {\n      return false\n    }\n  }\n\n  /**\n   * Check session (silent authentication)\n   */\n  async checkSession(): Promise<AuthResult | null> {\n    // TODO: Implement silent authentication with iframe\n    return null\n  }\n\n  /**\n   * Get session state\n   */\n  getSessionState(): SessionState {\n    return {\n      isAuthenticated: !!this.cache.accessToken,\n      user: this.cache.user,\n      accessToken: this.cache.accessToken,\n      idToken: this.cache.idToken,\n      expiresAt: this.cache.expiresAt\n    }\n  }\n\n  // ==========================================\n  // Private Methods\n  // ==========================================\n\n  private buildAuthorizationUrl(pkce: PKCEChallenge, options: RedirectLoginOptions): string {\n    // Determine redirect URI with fallback\n    let redirectUri = options.redirectUri || this.config.redirectUri\n    if (!redirectUri && typeof window !== 'undefined') {\n      redirectUri = window.location.origin\n      console.warn(\n        '⚠️ Authway: No redirectUri configured for login. Using window.location.origin.\\n' +\n        'To fix: Set redirectUri in AuthwayConfig or pass redirectUri in login options.'\n      )\n    }\n\n    const params = {\n      client_id: this.config.clientId,\n      response_type: 'code',\n      redirect_uri: redirectUri,\n      scope: this.config.scope,\n      state: pkce.state,\n      nonce: pkce.nonce,\n      code_challenge: pkce.codeChallenge,\n      code_challenge_method: 'S256',\n      ...options\n    }\n\n    delete params.appState\n\n    return buildUrl(`${this.config.domain}/oauth2/auth`, params)\n  }\n\n  private buildLogoutUrl(options: LogoutOptions, idToken: string | null): string {\n    const params: any = {\n      client_id: this.config.clientId\n    }\n\n    // Add id_token_hint if available (required when using post_logout_redirect_uri)\n    if (idToken) {\n      params.id_token_hint = idToken\n    }\n\n    // Use returnTo if provided, otherwise default to redirectUri (client's origin)\n    // This ensures users return to the app home instead of an error page\n    const postLogoutUri = options.returnTo || this.config.redirectUri\n    if (postLogoutUri) {\n      params.post_logout_redirect_uri = postLogoutUri\n    } else {\n      // Fallback to window.location.origin to prevent user landing on auth server\n      const fallbackUri = typeof window !== 'undefined' ? window.location.origin : ''\n      if (fallbackUri) {\n        params.post_logout_redirect_uri = fallbackUri\n        console.warn(\n          '⚠️ Authway: No redirectUri configured. Using window.location.origin as logout redirect.\\n' +\n          'To fix: Set redirectUri in AuthwayConfig or pass returnTo in logout options.'\n        )\n      } else {\n        console.error(\n          '❌ Authway: No redirect URI available for logout. User may land on auth server.\\n' +\n          'To fix: Configure redirectUri in AuthwayConfig or call logout({ returnTo: \"your-url\" })'\n        )\n      }\n    }\n\n    if (options.federated) {\n      params.federated = 'true'\n    }\n\n    return buildUrl(`${this.config.domain}/oauth2/sessions/logout`, params)\n  }\n\n  private async exchangeCodeForTokens(code: string, codeVerifier: string, redirectUri?: string): Promise<AuthResult> {\n    const url = `${this.config.domain}/oauth2/token`\n\n    // Add DPoP header if enabled\n    const headers: Record<string, string> = {}\n    if (this.config.useDPoP && this.dpopKeyPair) {\n      const dpopProof = await createDPoPProof(\n        this.dpopKeyPair,\n        'POST',\n        url\n      )\n      headers['DPoP'] = dpopProof\n    }\n\n    const response = await postForm<any>(url, {\n      grant_type: 'authorization_code',\n      code,\n      code_verifier: codeVerifier,\n      client_id: this.config.clientId,\n      redirect_uri: redirectUri || this.config.redirectUri\n    }, headers)\n\n    return {\n      accessToken: response.access_token,\n      idToken: response.id_token,\n      refreshToken: response.refresh_token,\n      expiresIn: response.expires_in,\n      user: extractUser(response.id_token)\n    }\n  }\n\n  private saveTokens(result: AuthResult): void {\n    this.cache.accessToken = result.accessToken\n    this.cache.idToken = result.idToken\n    this.cache.refreshToken = result.refreshToken || null\n    this.cache.user = result.user\n\n    // Calculate expiration from expires_in (supports both JWT and opaque tokens)\n    if (result.expiresIn) {\n      this.cache.expiresAt = Date.now() + (result.expiresIn * 1000)\n    } else {\n      // Fallback: Try to get expiration from access_token (JWT only)\n      try {\n        this.cache.expiresAt = getTokenExpiration(result.accessToken)\n      } catch {\n        // If token is opaque, set default expiration (1 hour)\n        console.warn('Cannot decode access_token, using default expiration')\n        this.cache.expiresAt = Date.now() + (3600 * 1000)\n      }\n    }\n\n    // Persist to storage if using localStorage\n    if (this.config.cacheLocation === 'localstorage') {\n      this.storage.set('accessToken', result.accessToken)\n      this.storage.set('idToken', result.idToken)\n      this.storage.set('expiresAt', this.cache.expiresAt.toString())\n      if (result.refreshToken) {\n        this.storage.set('refreshToken', result.refreshToken)\n      }\n    }\n\n    // Schedule token refresh\n    this.scheduleTokenRefresh(result.expiresIn)\n  }\n\n  private clearTokens(): void {\n    this.cache.accessToken = null\n    this.cache.idToken = null\n    this.cache.refreshToken = null\n    this.cache.user = null\n    this.cache.expiresAt = null\n\n    this.storage.clear()\n  }\n\n  private loadFromStorage(): void {\n    if (this.config.cacheLocation === 'localstorage') {\n      const accessToken = this.storage.get('accessToken')\n      const idToken = this.storage.get('idToken')\n      const refreshToken = this.storage.get('refreshToken')\n      const expiresAt = this.storage.get('expiresAt')\n\n      if (accessToken && idToken) {\n        this.cache.accessToken = accessToken\n        this.cache.idToken = idToken\n        this.cache.refreshToken = refreshToken\n        this.cache.user = extractUser(idToken)\n\n        // Load expiration time from storage (supports opaque tokens)\n        if (expiresAt) {\n          this.cache.expiresAt = parseInt(expiresAt, 10)\n        } else {\n          // Fallback: Try to decode token (JWT only)\n          try {\n            this.cache.expiresAt = getTokenExpiration(accessToken)\n          } catch {\n            // If token is opaque and no expiresAt stored, set default (1 hour)\n            console.warn('Cannot determine token expiration, using default')\n            this.cache.expiresAt = Date.now() + (3600 * 1000)\n          }\n        }\n      }\n    }\n  }\n\n  private scheduleTokenRefresh(expiresIn: number): void {\n    if (this.tokenRefreshTimer) {\n      clearTimeout(this.tokenRefreshTimer)\n    }\n\n    // Refresh 1 minute before expiration\n    const refreshIn = (expiresIn - 60) * 1000\n\n    if (refreshIn > 0) {\n      this.tokenRefreshTimer = setTimeout(() => {\n        this.refreshTokens().catch(err => {\n          console.error('Token refresh failed:', err)\n        })\n      }, refreshIn) as any\n    }\n  }\n}\n","/**\n * Auto-executing popup callback handler\n *\n * This module automatically handles OAuth popup callbacks when imported.\n * Use this in your callback page instead of manually creating callback.html:\n *\n * Option 1: Import in your callback page (React/Next.js/Vue)\n * ```tsx\n * // app/callback/page.tsx or pages/callback.tsx\n * import '@authway/client/popup-callback'\n * ```\n *\n * Option 2: Add as a script tag\n * ```html\n * <script src=\"https://unpkg.com/@authway/client/dist/popup-callback.js\"></script>\n * ```\n *\n * This will:\n * 1. Detect if the page is running in a popup with OAuth params\n * 2. Send the auth result to the parent window via postMessage\n * 3. Close the popup automatically\n * 4. If not in popup mode, do nothing (let your app handle redirect flow)\n */\n\nimport { AuthwayClient } from './AuthwayClient'\n\n// Auto-execute on import (side-effect)\nif (typeof window !== 'undefined') {\n  // Run after DOM is ready to ensure all params are available\n  if (document.readyState === 'loading') {\n    document.addEventListener('DOMContentLoaded', () => {\n      AuthwayClient.handlePopupCallback()\n    })\n  } else {\n    AuthwayClient.handlePopupCallback()\n  }\n}\n\n/**\n * Manually handle popup callback\n * Returns true if this page is a popup callback and was handled\n */\nexport function handlePopupCallback(): boolean {\n  return AuthwayClient.handlePopupCallback()\n}\n\n/**\n * Check if current page is a popup callback\n * Useful for conditional rendering in callback pages\n */\nexport function isPopupCallback(): boolean {\n  if (typeof window === 'undefined') return false\n\n  const params = new URLSearchParams(window.location.search)\n  const hasOAuthParams = (params.has('code') && params.has('state')) || params.has('error')\n\n  if (!hasOAuthParams) return false\n\n  // Check if we're in a popup\n  try {\n    return !!(window.opener && !window.opener.closed)\n  } catch {\n    // COOP policy may block access - use alternative detection\n    return window.name === 'authway-login' ||\n           sessionStorage.getItem('authway_popup_context') === 'true'\n  }\n}\n"]}