{"version":3,"sources":["../src/pkce.ts","../src/paths.ts","../src/session.ts","../src/browser.ts"],"names":[],"mappings":"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","file":"browser.cjs","sourcesContent":["/**\n * PKCE (Proof Key for Code Exchange, RFC 7636) utilities for OAuth2/OIDC.\n *\n * Uses the native Web Crypto API (`crypto.getRandomValues`,\n * `crypto.subtle.digest`) — available in modern browsers and Node ≥ 18.\n *\n * The code verifier is the base64url encoding of 32 cryptographically\n * random bytes (256 bits of entropy), which yields a 43-character\n * `[A-Za-z0-9-_]` string — within RFC 7636's 43–128 character range and\n * well above the minimum recommended entropy. The challenge is the\n * base64url-encoded SHA-256 of the verifier (the `S256` method).\n */\n\n/** Number of random bytes for the verifier and state — 256 bits each. */\nconst ENTROPY_BYTES = 32;\n\nfunction randomBase64Url(byteLength: number): string {\n  const bytes = new Uint8Array(byteLength);\n  crypto.getRandomValues(bytes);\n  return base64UrlEncode(bytes.buffer);\n}\n\nasync function sha256(plain: string): Promise<ArrayBuffer> {\n  const encoder = new TextEncoder();\n  return crypto.subtle.digest(\"SHA-256\", encoder.encode(plain));\n}\n\nfunction base64UrlEncode(buffer: ArrayBuffer): string {\n  const bytes = new Uint8Array(buffer);\n  let binary = \"\";\n  for (const byte of bytes) {\n    binary += String.fromCharCode(byte);\n  }\n  return btoa(binary).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\n/**\n * Generate a PKCE code verifier + S256 challenge pair.\n *\n * `codeVerifier` carries 256 bits of entropy; `codeChallenge` is its\n * base64url-encoded SHA-256 digest. Send `code_challenge` +\n * `code_challenge_method=S256` on the authorize request, and\n * `code_verifier` on the token exchange.\n */\nexport async function generatePKCEChallenge(): Promise<{\n  codeVerifier: string;\n  codeChallenge: string;\n}> {\n  const codeVerifier = randomBase64Url(ENTROPY_BYTES);\n  const hash = await sha256(codeVerifier);\n  const codeChallenge = base64UrlEncode(hash);\n  return { codeVerifier, codeChallenge };\n}\n\n/** Generate a high-entropy (256-bit) `state` parameter for CSRF protection. */\nexport function generateState(): string {\n  return randomBase64Url(ENTROPY_BYTES);\n}\n","/**\n * The single source of truth for Hanzo IAM OIDC endpoint paths.\n *\n * Hanzo IAM is a Casdoor-derived OIDC provider served per-brand from a\n * configurable origin (`serverUrl`): hanzo → https://iam.hanzo.ai,\n * lux → https://lux.id, zoo → https://zoo.id, bootnode → https://id.bootno.de.\n *\n * These are the ONLY paths. There is no legacy `/oauth/*` and no\n * `/api/login/*`. Every module in this SDK references `OIDC_PATHS` —\n * no path string is written anywhere else.\n *\n * CRITICAL GOTCHA: IAM serves a 200 `text/html` SPA catch-all for ANY\n * unregistered path. A client that hits a wrong path therefore gets a\n * 200 HTML body, not a 404 — silent breakage. So clients MUST hit these\n * exact paths, and a discovery round-trip must never be allowed to\n * resolve to a different path. The hard-coded fallbacks here are these\n * same values, so a failed discovery degrades to correct paths.\n */\n\n/** OIDC endpoint paths, relative to the brand `serverUrl`. */\nexport const OIDC_PATHS = {\n  /** OIDC discovery document. */\n  discovery: \"/.well-known/openid-configuration\",\n  /** Authorization endpoint (RFC 6749 §3.1). */\n  authorize: \"/v1/iam/oauth/authorize\",\n  /** Token endpoint (RFC 6749 §3.2). */\n  token: \"/v1/iam/oauth/token\",\n  /** UserInfo endpoint (OIDC Core §5.3). */\n  userinfo: \"/v1/iam/oauth/userinfo\",\n  /** JWKS endpoint (RFC 7517). */\n  jwks: \"/v1/iam/.well-known/jwks\",\n  /** RP-initiated logout endpoint (OIDC RP-Initiated Logout). */\n  logout: \"/v1/iam/oauth/logout\",\n} as const;\n\nexport type OidcPathKey = keyof typeof OIDC_PATHS;\n\n/**\n * Hanzo-IAM application paths that are NOT part of the OIDC spec — the\n * auth-method discovery endpoint and the onboarding state machine the\n * embedded views drive. Mounted under the same `/v1/iam` prefix.\n */\nexport const IAM_PATHS = {\n  /** Live list of enabled auth methods for the embedded login views. */\n  authMethods: \"/v1/iam/auth/methods\",\n  /** Onboarding state-machine base (steps append `/identity`, etc.). */\n  onboarding: \"/v1/iam/onboarding\",\n  /**\n   * Casdoor credential-login endpoint the embedded `<Login>` views POST to.\n   * `type=code` (a client `redirectUri` is present) mints an authorization\n   * code returned in `data`; `type=login` establishes the session cookie.\n   * This is what the deployed IAM actually authenticates against — the OIDC\n   * token endpoint's password/OTP grants are NOT enabled per-client.\n   */\n  login: \"/v1/iam/login\",\n  /** Send an email/SMS verification code (passwordless login). */\n  sendCode: \"/v1/iam/send-verification-code\",\n  /** Account registration. */\n  signup: \"/v1/iam/signup\",\n} as const;\n\nexport type IamPathKey = keyof typeof IAM_PATHS;\n\n/**\n * The canonical `serverUrl` origin for each Hanzo IAM brand. White-label\n * is host-based: one IAM deployment serves every brand and selects the\n * tenant by the origin it is reached on. This is the SINGLE place the\n * brand→origin mapping lives — adapters take a `brand` and resolve here\n * rather than each app hard-coding a hostname.\n */\nexport const BRAND_SERVER_URLS = {\n  hanzo: \"https://iam.hanzo.ai\",\n  lux: \"https://lux.id\",\n  zoo: \"https://zoo.id\",\n  bootnode: \"https://id.bootno.de\",\n  pars: \"https://pars.id\",\n} as const;\n\n/** A known Hanzo IAM brand key. */\nexport type IamBrand = keyof typeof BRAND_SERVER_URLS;\n\n/**\n * Resolve a brand to its canonical IAM `serverUrl`.\n *\n * @example\n * serverUrlForBrand(\"lux\") // → \"https://lux.id\"\n */\nexport function serverUrlForBrand(brand: IamBrand): string {\n  return BRAND_SERVER_URLS[brand];\n}\n\n/** Strip trailing slashes from a server origin so paths concat cleanly. */\nexport function trimServerUrl(serverUrl: string): string {\n  return serverUrl.replace(/\\/+$/, \"\");\n}\n\n/**\n * Build an absolute IAM endpoint URL from a server origin and a path key.\n *\n * @example\n * iamUrl(\"https://iam.hanzo.ai\", \"token\") // → \"https://iam.hanzo.ai/v1/iam/oauth/token\"\n */\nexport function iamUrl(serverUrl: string, key: OidcPathKey): string {\n  return `${trimServerUrl(serverUrl)}${OIDC_PATHS[key]}`;\n}\n","/**\n * The promoted, app-facing functional auth surface for Hanzo IAM.\n *\n * This is the ONE thing an app imports. It is a thin, configured singleton\n * over the {@link IAM} browser engine — mechanism stays in `browser.ts`,\n * this module just gives it a module-level config so apps write\n *\n *   import { configureIam, startLogin, handleCallback, getSession } from '@hanzo/iam/browser'\n *\n * instead of hand-rolling a local `iam-auth.ts` copy. It is the SDK promotion\n * of `commerce/app/site/app/lib/iam-auth.ts`.\n *\n * Three orthogonal verbs, parameterized — never a branch per provider:\n *\n *   startLogin({ provider?, redirect? })   ONE Authorization-Code + PKCE flow.\n *                                          `provider` is the ONLY knob: omit it\n *                                          for the IAM login page, or name a\n *                                          social/web3 provider to delegate the\n *                                          social hop to IAM's shared org-level\n *                                          OAuth client. The app NEVER registers\n *                                          a per-app Google/GitHub client.\n *   handleCallback()                       ONE token exchange (PKCE verifier +\n *                                          state/CSRF check). No path literals —\n *                                          endpoints come from OIDC discovery\n *                                          (falling back to OIDC_PATHS).\n *   getSession() / getUser() / logout()    ONE session model.\n *\n * `provider` rides the authorize request as `&provider=<name>` on\n * `/v1/iam/oauth/authorize`. IAM performs the social hop with its shared\n * client (the provider hop's redirect_uri is IAM's own callback) and returns\n * the code to the APP's own `redirect_uri`. PKCE-S256 always. No `/api/`.\n */\n\nimport { IAM, type IAMConfig, type IAMUser, type IAMToken } from \"./browser.js\";\n\n// ---------------------------------------------------------------------------\n// Module-level configured singleton\n// ---------------------------------------------------------------------------\n\nlet instance: IAM | null = null;\nlet activeConfig: IamSessionConfig | null = null;\n\n/**\n * App-facing config. `issuer` is the brand IAM origin (e.g. \"https://hanzo.id\");\n * `clientId` is `<org>-<app>`. `redirect` defaults to the current origin +\n * `/auth/callback` — the framework's exact callback. Everything else (token,\n * userinfo, jwks, logout endpoints) is resolved from OIDC discovery.\n */\nexport interface IamSessionConfig {\n  /** Brand IAM origin, e.g. \"https://hanzo.id\". Maps to IAM `serverUrl`. */\n  issuer: string;\n  /** OAuth client id (`<org>-<app>`). */\n  clientId: string;\n  /** App OAuth callback URI. Default: `${origin}/auth/callback`. */\n  redirect?: string;\n  /** OAuth scopes. Default: \"openid profile email\". */\n  scope?: string;\n  /** Token storage. Default: sessionStorage. */\n  storage?: Storage;\n  /** Same-origin proxy base for token/userinfo (keeps cross-origin off the browser). */\n  proxyBaseUrl?: string;\n}\n\n/** Default app callback path appended to the current origin. */\nconst DEFAULT_CALLBACK_PATH = \"/auth/callback\";\n\nfunction defaultRedirect(): string {\n  const origin = typeof window !== \"undefined\" ? window.location.origin : \"\";\n  return `${origin}${DEFAULT_CALLBACK_PATH}`;\n}\n\nfunction toIAMConfig(c: IamSessionConfig): IAMConfig {\n  return {\n    serverUrl: c.issuer,\n    clientId: c.clientId,\n    redirectUri: c.redirect ?? defaultRedirect(),\n    scope: c.scope,\n    storage: c.storage,\n    proxyBaseUrl: c.proxyBaseUrl,\n  };\n}\n\n/**\n * Configure the module-level IAM singleton. Call once at app startup. Returns\n * the underlying {@link IAM} engine for advanced use. Idempotent per config.\n */\nexport function configureIam(config: IamSessionConfig): IAM {\n  activeConfig = config;\n  instance = new IAM(toIAMConfig(config));\n  return instance;\n}\n\nfunction engine(): IAM {\n  if (!instance) {\n    throw new Error(\n      \"@hanzo/iam: call configureIam({ issuer, clientId }) before startLogin/handleCallback.\",\n    );\n  }\n  return instance;\n}\n\n// ---------------------------------------------------------------------------\n// startLogin — ONE flow, provider is the only knob\n// ---------------------------------------------------------------------------\n\nexport interface StartLoginOptions {\n  /**\n   * Social/web3 provider hint (e.g. \"google\", \"github\", \"web3\"). Omit for the\n   * IAM login page. The ONLY knob that selects the method — delegated to IAM's\n   * shared org-level OAuth client, never a per-app registration.\n   */\n  provider?: string;\n  /** Where to land after a successful login. Stashed across the round-trip. */\n  redirect?: string;\n}\n\nconst KEY_POST_LOGIN_REDIRECT = \"hanzo_iam_post_login_redirect\";\n\n/**\n * Start the OIDC Authorization-Code + PKCE-S256 login by redirecting to\n * `/v1/iam/oauth/authorize`. `provider` (if given) rides as `&provider=<name>`.\n * Stashes the post-login `redirect` so {@link handleCallback} can return it.\n */\nexport async function startLogin(opts: StartLoginOptions = {}): Promise<void> {\n  if (opts.redirect && typeof sessionStorage !== \"undefined\") {\n    sessionStorage.setItem(KEY_POST_LOGIN_REDIRECT, opts.redirect);\n  }\n  const additionalParams = opts.provider ? { provider: opts.provider } : undefined;\n  await engine().signinRedirect({ additionalParams });\n}\n\n/**\n * Build the authorize URL WITHOUT redirecting (for `<a href>` or tests).\n * Same PKCE + provider semantics as {@link startLogin}.\n */\nexport async function getLoginUrl(opts: StartLoginOptions = {}): Promise<string> {\n  const additionalParams = opts.provider ? { provider: opts.provider } : undefined;\n  return engine().getSigninUrl({ additionalParams });\n}\n\n// ---------------------------------------------------------------------------\n// handleCallback — ONE token exchange\n// ---------------------------------------------------------------------------\n\n/**\n * Complete the login on the app's callback route: verify state + PKCE verifier,\n * exchange the code at the discovered token endpoint, store tokens. Returns the\n * stashed post-login redirect (or \"/\" if none).\n */\nexport async function handleCallback(callbackUrl?: string): Promise<{ token: IAMToken; redirect: string }> {\n  const token = await engine().handleCallback(callbackUrl);\n  let redirect = \"/\";\n  if (typeof sessionStorage !== \"undefined\") {\n    redirect = sessionStorage.getItem(KEY_POST_LOGIN_REDIRECT) ?? \"/\";\n    sessionStorage.removeItem(KEY_POST_LOGIN_REDIRECT);\n  }\n  return { token, redirect };\n}\n\n// ---------------------------------------------------------------------------\n// Session model — getSession / getUser / logout\n// ---------------------------------------------------------------------------\n\nexport interface IamSession {\n  /** Whether a valid (unexpired) access token is present. */\n  authenticated: boolean;\n  /** Current access token (null when unauthenticated). */\n  accessToken: string | null;\n}\n\n/** Synchronous session snapshot from local token storage. */\nexport function getSession(): IamSession {\n  const sdk = engine();\n  const accessToken = sdk.getAccessToken();\n  const authenticated = !!accessToken && !sdk.isTokenExpired();\n  return { authenticated, accessToken: authenticated ? accessToken : null };\n}\n\n/** Fetch the current user from the userinfo endpoint (null when unauthenticated). */\nexport function getUser(): Promise<IAMUser | null> {\n  return engine().getUser();\n}\n\n/** RP-initiated logout + local token clear. */\nexport function logout(): Promise<void> {\n  if (typeof sessionStorage !== \"undefined\") {\n    sessionStorage.removeItem(KEY_POST_LOGIN_REDIRECT);\n  }\n  return engine().logout();\n}\n\n/** Escape hatch: the underlying configured {@link IAM} engine. */\nexport function getIam(): IAM {\n  return engine();\n}\n\n/** The currently active session config (null before `configureIam`). */\nexport function getIamConfig(): IamSessionConfig | null {\n  return activeConfig;\n}\n","/**\n * Browser-side OAuth2/OIDC PKCE flow for Hanzo IAM.\n *\n * Standards core: RFC 6749 (OAuth2), RFC 7636 (PKCE), OIDC. The default\n * flow is a single redirect-to-authorize where the IAM server owns the\n * credential interaction. For first-party apps that render their OWN\n * branded login on their own domain, the embedded credential methods\n * (`loginWithPassword` / `loginWithCode`) collect the credential in-app and\n * mint a PKCE-bound authorization code via the IAM login endpoint — the\n * SAME RFC 7636 code+PKCE exchange completes it through `handleCallback`.\n * (Not ROPC: no password ever hits the token endpoint.)\n *\n *   IAM#signinRedirect()    — start PKCE redirect to the authorize endpoint\n *   IAM#handleCallback()    — exchange code at the token endpoint (PKCE)\n *   IAM#loginWithPassword() — first-party embedded login → PKCE-bound code\n *   IAM#loginWithCode()     — embedded passwordless code login → PKCE code\n *   IAM#sendLoginCode()     — send an email/SMS verification code\n *   IAM#refreshAccessToken()— refresh grant\n *   IAM#signinPopup()       — same flow in a popup window\n *   IAM#signinSilent()      — prompt=none iframe attempt\n *   IAM#getUserInfo()       — userinfo endpoint\n *   IAM#logout()            — RP-initiated logout\n *\n * Every endpoint resolves through `OIDC_PATHS` (see ./paths). Live OIDC\n * discovery is preferred when reachable; the hard-coded fallback uses\n * the exact same canonical paths so a CORS/network failure degrades to\n * correct URLs, never to the IAM HTML SPA catch-all.\n */\n\nimport type { Config, TokenResponse, OidcDiscovery } from \"./types.js\";\nimport { generatePKCEChallenge, generateState } from \"./pkce.js\";\nimport { OIDC_PATHS, IAM_PATHS, iamUrl, trimServerUrl } from \"./paths.js\";\n\n// ---------------------------------------------------------------------------\n// Storage keys\n// ---------------------------------------------------------------------------\n\nconst STORAGE_PREFIX = \"hanzo_iam_\";\nconst KEY_STATE = `${STORAGE_PREFIX}state`;\nconst KEY_CODE_VERIFIER = `${STORAGE_PREFIX}code_verifier`;\nconst KEY_ACCESS_TOKEN = `${STORAGE_PREFIX}access_token`;\nconst KEY_REFRESH_TOKEN = `${STORAGE_PREFIX}refresh_token`;\nconst KEY_ID_TOKEN = `${STORAGE_PREFIX}id_token`;\nconst KEY_EXPIRES_AT = `${STORAGE_PREFIX}expires_at`;\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport type IAMConfig = Config & {\n  /** OAuth2 redirect URI (e.g. \"https://app.hanzo.bot/auth/callback\"). */\n  redirectUri: string;\n  /** OAuth2 scopes (default: \"openid profile email\"). */\n  scope?: string;\n  /** Storage to use for tokens (default: sessionStorage). */\n  storage?: Storage;\n  /**\n   * Optional proxy base URL for the token + userinfo endpoints.\n   * When set, token exchange POSTs hit `${proxyBaseUrl}/v1/iam/oauth/token`\n   * and userinfo GETs hit `${proxyBaseUrl}/v1/iam/oauth/userinfo` instead\n   * of the IAM origin directly. Use this to keep cross-origin requests\n   * off the browser (gateway proxies same-origin to IAM).\n   */\n  proxyBaseUrl?: string;\n  /**\n   * IAM organization (e.g. \"hanzo\"). Required only for the first-party\n   * embedded credential login (`loginWithPassword` / `loginWithCode`).\n   */\n  organization?: string;\n  /** IAM application name. Defaults to `clientId` (they match for Hanzo apps). */\n  application?: string;\n};\n\n// ---------------------------------------------------------------------------\n// Browser IAM SDK\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve the storage used for the short-lived PKCE transaction (state +\n * code_verifier). These two values are written before the full-page redirect\n * to IAM and read back at the callback — they MUST survive that round-trip.\n *\n * sessionStorage does NOT reliably survive it: Safari/WebKit ITP can drop it,\n * the instant SSO bounce (already signed in at IAM → immediate 302 back) and\n * in-app webviews can land the callback in a fresh context, and multi-tab\n * logins don't share it. The symptom is \"Missing PKCE code verifier\" at the\n * callback even though signinRedirect() ran. localStorage survives all of\n * these on the same origin; the values are one-shot and removed immediately\n * after the exchange, so there is no lingering-secret tradeoff.\n *\n * Falls back to the token storage when localStorage is unavailable (SSR,\n * privacy mode that throws on access).\n */\nfunction resolveTxStorage(fallback: Storage): Storage {\n  try {\n    if (typeof localStorage !== \"undefined\") {\n      const probe = \"hanzo_iam_probe\";\n      localStorage.setItem(probe, \"1\");\n      localStorage.removeItem(probe);\n      return localStorage;\n    }\n  } catch {\n    /* localStorage unavailable (privacy mode) — fall back */\n  }\n  return fallback;\n}\n\nexport class IAM {\n  private readonly config: IAMConfig;\n  private readonly storage: Storage;\n  /** Storage for the one-shot PKCE transaction (state + verifier). Defaults to\n   * localStorage so it survives the OAuth redirect; see resolveTxStorage. */\n  private readonly txStorage: Storage;\n  private discoveryCache: OidcDiscovery | null = null;\n\n  constructor(config: IAMConfig) {\n    this.config = config;\n    this.storage = config.storage ?? sessionStorage;\n    this.txStorage = resolveTxStorage(this.storage);\n  }\n\n  // -----------------------------------------------------------------------\n  // OIDC Discovery\n  // -----------------------------------------------------------------------\n\n  private async getDiscovery(): Promise<OidcDiscovery> {\n    if (this.discoveryCache) return this.discoveryCache;\n\n    const baseUrl = trimServerUrl(this.config.serverUrl);\n\n    // Prefer live OIDC discovery. If it fails (e.g. CORS when the IAM\n    // server doesn't send Access-Control-Allow-Origin), construct a\n    // fallback from the canonical OIDC_PATHS — the SAME paths discovery\n    // would return, so a failed round-trip degrades to correct URLs,\n    // never to the IAM HTML SPA catch-all.\n    try {\n      const res = await fetch(`${baseUrl}${OIDC_PATHS.discovery}`, {\n        headers: { Accept: \"application/json\" },\n      });\n      if (res.ok) {\n        this.discoveryCache = (await res.json()) as OidcDiscovery;\n        return this.discoveryCache;\n      }\n    } catch {\n      // CORS or network error — fall through to constructed discovery\n    }\n\n    this.discoveryCache = {\n      issuer: baseUrl,\n      authorization_endpoint: iamUrl(baseUrl, \"authorize\"),\n      token_endpoint: iamUrl(baseUrl, \"token\"),\n      userinfo_endpoint: iamUrl(baseUrl, \"userinfo\"),\n      jwks_uri: iamUrl(baseUrl, \"jwks\"),\n      response_types_supported: [\"code\"],\n      grant_types_supported: [\"authorization_code\", \"refresh_token\"],\n      scopes_supported: [\"openid\", \"email\", \"profile\"],\n    };\n    return this.discoveryCache;\n  }\n\n  // -----------------------------------------------------------------------\n  // Token endpoint URL (proxy-aware)\n  // -----------------------------------------------------------------------\n\n  private async tokenEndpoint(): Promise<string> {\n    if (this.config.proxyBaseUrl) {\n      return iamUrl(this.config.proxyBaseUrl, \"token\");\n    }\n    const discovery = await this.getDiscovery();\n    return discovery.token_endpoint;\n  }\n\n  private async userinfoEndpoint(): Promise<string> {\n    if (this.config.proxyBaseUrl) {\n      return iamUrl(this.config.proxyBaseUrl, \"userinfo\");\n    }\n    const discovery = await this.getDiscovery();\n    return discovery.userinfo_endpoint;\n  }\n\n  // -----------------------------------------------------------------------\n  // Authorize URL builder\n  // -----------------------------------------------------------------------\n\n  private async buildAuthorizeUrl(extra?: {\n    additionalParams?: Record<string, string>;\n    prompt?: string;\n  }): Promise<{ url: URL; codeVerifier: string; state: string }> {\n    const discovery = await this.getDiscovery();\n    const { codeVerifier, codeChallenge } = await generatePKCEChallenge();\n    const state = generateState();\n\n    this.txStorage.setItem(KEY_STATE, state);\n    this.txStorage.setItem(KEY_CODE_VERIFIER, codeVerifier);\n\n    const url = new URL(discovery.authorization_endpoint);\n    url.searchParams.set(\"client_id\", this.config.clientId);\n    url.searchParams.set(\"response_type\", \"code\");\n    url.searchParams.set(\"redirect_uri\", this.config.redirectUri);\n    url.searchParams.set(\"scope\", this.config.scope ?? \"openid profile email\");\n    url.searchParams.set(\"state\", state);\n    url.searchParams.set(\"code_challenge\", codeChallenge);\n    url.searchParams.set(\"code_challenge_method\", \"S256\");\n\n    if (extra?.prompt) url.searchParams.set(\"prompt\", extra.prompt);\n    if (extra?.additionalParams) {\n      for (const [k, v] of Object.entries(extra.additionalParams)) {\n        url.searchParams.set(k, v);\n      }\n    }\n    return { url, codeVerifier, state };\n  }\n\n  // -----------------------------------------------------------------------\n  // Login redirect (PKCE)\n  // -----------------------------------------------------------------------\n\n  /**\n   * Start the OAuth2 PKCE login flow by redirecting to /oauth/authorize.\n   * Generates PKCE challenge + state, stores them in session storage,\n   * then sets `window.location.href`.\n   */\n  async signinRedirect(params?: { additionalParams?: Record<string, string> }): Promise<void> {\n    const { url } = await this.buildAuthorizeUrl(params);\n    window.location.href = url.toString();\n  }\n\n  /**\n   * Build the authorize URL without redirecting — useful for `<a href>`\n   * (e.g. social login buttons with `provider` in additionalParams).\n   */\n  async getSigninUrl(params?: { additionalParams?: Record<string, string> }): Promise<string> {\n    const { url } = await this.buildAuthorizeUrl(params);\n    return url.toString();\n  }\n\n  // -----------------------------------------------------------------------\n  // First-party embedded credential login (PKCE-bound, no IAM-hosted UI)\n  // -----------------------------------------------------------------------\n\n  /**\n   * Generate + persist a PKCE verifier and state for an embedded credential\n   * login, returning the challenge to bind into the minted code. Uses the\n   * SAME storage keys as `signinRedirect`, so `handleCallback` completes the\n   * exact same RFC 7636 exchange regardless of how sign-in started.\n   */\n  private async beginCredential(): Promise<{ codeChallenge: string; state: string }> {\n    const { codeVerifier, codeChallenge } = await generatePKCEChallenge();\n    const state = generateState();\n    this.txStorage.setItem(KEY_STATE, state);\n    this.txStorage.setItem(KEY_CODE_VERIFIER, codeVerifier);\n    return { codeChallenge, state };\n  }\n\n  /**\n   * POST the IAM login endpoint with a PKCE `code_challenge` so the returned\n   * authorization code is challenge-bound. Returns the app-callback URL\n   * carrying `code` + `state`; the caller navigates there and\n   * `handleCallback()` performs the standard PKCE token exchange. Throws on\n   * an IAM error. No password ever reaches the token endpoint.\n   */\n  private async credentialLogin(fields: Record<string, unknown>): Promise<string> {\n    const { codeChallenge, state } = await this.beginCredential();\n    const base = this.config.proxyBaseUrl ?? this.config.serverUrl;\n    const url = new URL(`${trimServerUrl(base)}${IAM_PATHS.login}`);\n    url.searchParams.set(\"clientId\", this.config.clientId);\n    url.searchParams.set(\"responseType\", \"code\");\n    url.searchParams.set(\"redirectUri\", this.config.redirectUri);\n    url.searchParams.set(\"scope\", this.config.scope ?? \"openid profile email\");\n    url.searchParams.set(\"state\", state);\n    url.searchParams.set(\"type\", \"code\");\n    url.searchParams.set(\"code_challenge\", codeChallenge);\n    url.searchParams.set(\"code_challenge_method\", \"S256\");\n\n    const res = await fetch(url.toString(), {\n      method: \"POST\",\n      headers: { \"Content-Type\": \"application/json\", Accept: \"application/json\" },\n      credentials: \"include\",\n      body: JSON.stringify({\n        type: \"code\",\n        application: this.config.application ?? this.config.clientId,\n        organization: this.config.organization,\n        autoSignin: true,\n        ...fields,\n      }),\n    });\n    const parsed = (await res.json().catch(() => ({}))) as Record<string, unknown>;\n    if (!res.ok || parsed.status === \"error\") {\n      throw new Error(typeof parsed.msg === \"string\" ? parsed.msg : `sign-in failed (${res.status})`);\n    }\n    const code = parsed.data;\n    if (typeof code !== \"string\" || code.length === 0) {\n      throw new Error(\"IAM did not return an authorization code\");\n    }\n    const sep = this.config.redirectUri.includes(\"?\") ? \"&\" : \"?\";\n    return `${this.config.redirectUri}${sep}code=${encodeURIComponent(code)}&state=${encodeURIComponent(state)}`;\n  }\n\n  /** Embedded password login → returns the app-callback URL to navigate to. */\n  loginWithPassword(username: string, password: string): Promise<string> {\n    return this.credentialLogin({ username, password, signinMethod: \"Password\" });\n  }\n\n  /** Embedded passwordless code login → returns the app-callback URL. */\n  loginWithCode(destination: string, code: string): Promise<string> {\n    const isEmail = destination.includes(\"@\");\n    return this.credentialLogin({\n      username: destination,\n      code,\n      signinMethod: \"Verification code\",\n      ...(isEmail ? { email: destination } : { phone: destination }),\n    });\n  }\n\n  /** Send a passwordless email/SMS verification code for `loginWithCode`. */\n  async sendLoginCode(destination: string): Promise<void> {\n    const isEmail = destination.includes(\"@\");\n    const base = this.config.proxyBaseUrl ?? this.config.serverUrl;\n    const url = new URL(`${trimServerUrl(base)}${IAM_PATHS.sendCode}`);\n    url.searchParams.set(\"clientId\", this.config.clientId);\n    if (this.config.organization) url.searchParams.set(\"organization\", this.config.organization);\n    const res = await fetch(url.toString(), {\n      method: \"POST\",\n      headers: { \"Content-Type\": \"application/json\", Accept: \"application/json\" },\n      body: JSON.stringify({\n        applicationId: `admin/${this.config.application ?? this.config.clientId}`,\n        organization: this.config.organization,\n        dest: destination,\n        type: isEmail ? \"email\" : \"phone\",\n        method: \"login\",\n        checkUser: destination,\n      }),\n    });\n    const parsed = (await res.json().catch(() => ({}))) as Record<string, unknown>;\n    if (!res.ok || parsed.status === \"error\") {\n      throw new Error(typeof parsed.msg === \"string\" ? parsed.msg : `could not send code (${res.status})`);\n    }\n  }\n\n  // -----------------------------------------------------------------------\n  // Callback handling\n  // -----------------------------------------------------------------------\n\n  /**\n   * Handle the OAuth2 callback after the IAM redirect. Validates state,\n   * exchanges the authorization code for tokens with PKCE, and stores\n   * the result.\n   *\n   * Call this on your callback route (e.g. /auth/callback).\n   */\n  async handleCallback(callbackUrl?: string): Promise<IAMToken> {\n    const url = new URL(callbackUrl ?? window.location.href);\n    const error = url.searchParams.get(\"error\");\n\n    if (error) {\n      const desc = url.searchParams.get(\"error_description\") ?? error;\n      throw new Error(`OAuth error: ${desc}`);\n    }\n\n    const state = url.searchParams.get(\"state\");\n    // The transaction lives in txStorage (localStorage); the this.storage read\n    // is a transition fallback for a login started by an older build that wrote\n    // sessionStorage. Once deployed everywhere, only txStorage is ever hit.\n    const savedState =\n      this.txStorage.getItem(KEY_STATE) ?? this.storage.getItem(KEY_STATE);\n    if (savedState && state !== savedState) {\n      throw new Error(\"OAuth state mismatch — possible CSRF attack\");\n    }\n\n    const code = url.searchParams.get(\"code\");\n    if (!code) {\n      throw new Error(\"Missing authorization code in callback URL\");\n    }\n\n    const codeVerifier =\n      this.txStorage.getItem(KEY_CODE_VERIFIER) ??\n      this.storage.getItem(KEY_CODE_VERIFIER);\n    if (!codeVerifier) {\n      throw new Error(\"Missing PKCE code verifier — start sign-in via signinRedirect() or the embedded credential login.\");\n    }\n\n    // One-shot — clean up state (both stores) before the network call.\n    this.txStorage.removeItem(KEY_STATE);\n    this.txStorage.removeItem(KEY_CODE_VERIFIER);\n    this.storage.removeItem(KEY_STATE);\n    this.storage.removeItem(KEY_CODE_VERIFIER);\n\n    const body = new URLSearchParams({\n      grant_type: \"authorization_code\",\n      client_id: this.config.clientId,\n      code,\n      redirect_uri: this.config.redirectUri,\n      code_verifier: codeVerifier,\n    });\n\n    const tokenUrl = await this.tokenEndpoint();\n    const res = await fetch(tokenUrl, {\n      method: \"POST\",\n      headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n      body: body.toString(),\n    });\n\n    if (!res.ok) {\n      const text = await res.text().catch(() => \"\");\n      throw new Error(`Token exchange failed (${res.status}): ${text}`);\n    }\n\n    const tokens = (await res.json()) as TokenResponse;\n    this.storeTokens(tokens);\n    return toIAMToken(tokens);\n  }\n\n  // -----------------------------------------------------------------------\n  // Token refresh\n  // -----------------------------------------------------------------------\n\n  /** Refresh the access token using the stored refresh token. */\n  async refreshAccessToken(): Promise<IAMToken> {\n    const refreshToken = this.storage.getItem(KEY_REFRESH_TOKEN);\n    if (!refreshToken) {\n      throw new Error(\"No refresh token available\");\n    }\n\n    const body = new URLSearchParams({\n      grant_type: \"refresh_token\",\n      client_id: this.config.clientId,\n      refresh_token: refreshToken,\n    });\n\n    const tokenUrl = await this.tokenEndpoint();\n    const res = await fetch(tokenUrl, {\n      method: \"POST\",\n      headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n      body: body.toString(),\n    });\n\n    if (!res.ok) {\n      const text = await res.text().catch(() => \"\");\n      throw new Error(`Token refresh failed (${res.status}): ${text}`);\n    }\n\n    const tokens = (await res.json()) as TokenResponse;\n    this.storeTokens(tokens);\n    return toIAMToken(tokens);\n  }\n\n  // -----------------------------------------------------------------------\n  // Popup signin\n  // -----------------------------------------------------------------------\n\n  /**\n   * Open the IAM login page in a popup window. Resolves when the popup\n   * completes the OAuth flow and returns tokens.\n   */\n  async signinPopup(params?: {\n    width?: number;\n    height?: number;\n    additionalParams?: Record<string, string>;\n  }): Promise<IAMToken> {\n    const { url } = await this.buildAuthorizeUrl({\n      additionalParams: params?.additionalParams,\n    });\n\n    const width = params?.width ?? 600;\n    const height = params?.height ?? 700;\n    const left = window.screenX + (window.outerWidth - width) / 2;\n    const top = window.screenY + (window.outerHeight - height) / 2;\n\n    return new Promise<IAMToken>((resolve, reject) => {\n      const popup = window.open(\n        url.toString(),\n        \"hanzo_iam_login\",\n        `width=${width},height=${height},left=${left},top=${top},menubar=no,toolbar=no`,\n      );\n\n      if (!popup) {\n        reject(new Error(\"Failed to open login popup — blocked by browser?\"));\n        return;\n      }\n\n      const interval = setInterval(() => {\n        try {\n          if (popup.closed) {\n            clearInterval(interval);\n            reject(new Error(\"Login popup was closed before completing\"));\n            return;\n          }\n          // Check if popup navigated to our redirect URI\n          const popupUrl = popup.location.href;\n          if (popupUrl.startsWith(this.config.redirectUri)) {\n            clearInterval(interval);\n            popup.close();\n            this.handleCallback(popupUrl).then(resolve, reject);\n          }\n        } catch {\n          // Cross-origin — popup is still on IAM domain, keep waiting\n        }\n      }, 200);\n    });\n  }\n\n  // -----------------------------------------------------------------------\n  // Silent signin (iframe)\n  // -----------------------------------------------------------------------\n\n  /**\n   * Attempt silent authentication via a hidden iframe (`prompt=none`).\n   * Returns null if silent auth fails (user needs to log in interactively).\n   */\n  async signinSilent(timeoutMs = 5000): Promise<IAMToken | null> {\n    const { url } = await this.buildAuthorizeUrl({ prompt: \"none\" });\n\n    return new Promise<IAMToken | null>((resolve) => {\n      const iframe = document.createElement(\"iframe\");\n      iframe.style.display = \"none\";\n\n      const timeout = setTimeout(() => {\n        cleanup();\n        resolve(null);\n      }, timeoutMs);\n\n      const cleanup = () => {\n        clearTimeout(timeout);\n        iframe.remove();\n        this.txStorage.removeItem(KEY_STATE);\n        this.txStorage.removeItem(KEY_CODE_VERIFIER);\n        this.storage.removeItem(KEY_STATE);\n        this.storage.removeItem(KEY_CODE_VERIFIER);\n      };\n\n      iframe.addEventListener(\"load\", () => {\n        try {\n          const iframeUrl = iframe.contentWindow?.location.href;\n          if (iframeUrl && iframeUrl.startsWith(this.config.redirectUri)) {\n            cleanup();\n            this.handleCallback(iframeUrl).then(\n              (tokens) => resolve(tokens),\n              () => resolve(null),\n            );\n          }\n        } catch {\n          // Cross-origin or error — silent auth failed\n          cleanup();\n          resolve(null);\n        }\n      });\n\n      iframe.src = url.toString();\n      document.body.appendChild(iframe);\n    });\n  }\n\n  // -----------------------------------------------------------------------\n  // Token management\n  // -----------------------------------------------------------------------\n\n  private storeTokens(tokens: TokenResponse): void {\n    this.storage.setItem(KEY_ACCESS_TOKEN, tokens.access_token);\n    if (tokens.refresh_token) {\n      this.storage.setItem(KEY_REFRESH_TOKEN, tokens.refresh_token);\n    }\n    if (tokens.id_token) {\n      this.storage.setItem(KEY_ID_TOKEN, tokens.id_token);\n    }\n    if (tokens.expires_in) {\n      const expiresAt = Date.now() + tokens.expires_in * 1000;\n      this.storage.setItem(KEY_EXPIRES_AT, String(expiresAt));\n    }\n  }\n\n  /** Get the stored access token (may be expired). */\n  getAccessToken(): string | null {\n    return this.storage.getItem(KEY_ACCESS_TOKEN);\n  }\n\n  /** Get the stored refresh token. */\n  getRefreshToken(): string | null {\n    return this.storage.getItem(KEY_REFRESH_TOKEN);\n  }\n\n  /** Get the stored ID token. */\n  getIdToken(): string | null {\n    return this.storage.getItem(KEY_ID_TOKEN);\n  }\n\n  /** Check if the stored access token is expired. */\n  isTokenExpired(): boolean {\n    const expiresAt = this.storage.getItem(KEY_EXPIRES_AT);\n    if (!expiresAt) return true;\n    return Date.now() >= Number(expiresAt);\n  }\n\n  /**\n   * Get a valid access token — refreshes automatically if expired.\n   * Returns null if no token and no refresh token available.\n   */\n  async getValidAccessToken(): Promise<string | null> {\n    const token = this.getAccessToken();\n    if (token && !this.isTokenExpired()) {\n      return token;\n    }\n    if (this.getRefreshToken()) {\n      try {\n        const tokens = await this.refreshAccessToken();\n        return tokens.accessToken;\n      } catch {\n        return null;\n      }\n    }\n    return null;\n  }\n\n  /** Clear all stored tokens (local logout). */\n  clearTokens(): void {\n    this.storage.removeItem(KEY_ACCESS_TOKEN);\n    this.storage.removeItem(KEY_REFRESH_TOKEN);\n    this.storage.removeItem(KEY_ID_TOKEN);\n    this.storage.removeItem(KEY_EXPIRES_AT);\n    this.storage.removeItem(KEY_STATE);\n    this.storage.removeItem(KEY_CODE_VERIFIER);\n    this.txStorage.removeItem(KEY_STATE);\n    this.txStorage.removeItem(KEY_CODE_VERIFIER);\n  }\n\n  // -----------------------------------------------------------------------\n  // RP-initiated logout\n  // -----------------------------------------------------------------------\n\n  /**\n   * RP-initiated logout (OIDC). Best-effort POST to the logout endpoint\n   * to terminate the server-side session, then clears local tokens.\n   */\n  async logout(): Promise<void> {\n    const token = this.storage.getItem(KEY_ACCESS_TOKEN);\n    try {\n      await fetch(iamUrl(this.config.serverUrl, \"logout\"), {\n        method: \"POST\",\n        headers: token ? { Authorization: `Bearer ${token}` } : {},\n      });\n    } catch {\n      // best-effort — local cleanup is what matters\n    }\n    this.clearTokens();\n  }\n\n  // -----------------------------------------------------------------------\n  // User info\n  // -----------------------------------------------------------------------\n\n  /** Fetch user info from /oauth/userinfo using the stored access token. */\n  async getUserInfo(): Promise<Record<string, unknown>> {\n    const token = await this.getValidAccessToken();\n    if (!token) {\n      throw new Error(\"No valid access token — user must log in\");\n    }\n    const url = await this.userinfoEndpoint();\n    const res = await fetch(url, {\n      headers: { Authorization: `Bearer ${token}` },\n    });\n    if (!res.ok) {\n      throw new Error(`Userinfo fetch failed (${res.status})`);\n    }\n    return (await res.json()) as Record<string, unknown>;\n  }\n\n  /**\n   * Fetch the current user, shaped into the canonical `IAMUser` form\n   * (camelCase, no `_` keys). Returns null when no token is present.\n   */\n  async getUser(): Promise<IAMUser | null> {\n    const token = await this.getValidAccessToken();\n    if (!token) return null;\n    const u = (await this.getUserInfo()) as Record<string, unknown>;\n    return {\n      sub: (u.sub as string) ?? \"\",\n      email: u.email as string | undefined,\n      name: u.name as string | undefined,\n      givenName: u.given_name as string | undefined,\n      familyName: u.family_name as string | undefined,\n      phoneNumber: u.phone_number as string | undefined,\n      emailVerified: u.email_verified as boolean | undefined,\n      picture: u.picture as string | undefined,\n      owner: u.owner as string | undefined,\n    };\n  }\n}\n\n/**\n * Canonical user shape returned by `IAM#getUser()`. Maps the OIDC userinfo\n * response (snake_case) to camelCase.\n */\nexport type IAMUser = {\n  sub: string;\n  email?: string;\n  name?: string;\n  givenName?: string;\n  familyName?: string;\n  phoneNumber?: string;\n  emailVerified?: boolean;\n  picture?: string;\n  owner?: string;\n};\n\n/**\n * Canonical token shape (camelCase, no `_` keys) for app code.\n */\nexport type IAMToken = {\n  accessToken: string;\n  refreshToken?: string;\n  idToken?: string;\n  expiresIn?: number;\n  tokenType?: string;\n  scope?: string;\n};\n\n/** Convert the raw OAuth2 token response into the canonical `IAMToken`. */\nexport function toIAMToken(t: TokenResponse): IAMToken {\n  return {\n    accessToken: t.access_token,\n    refreshToken: t.refresh_token,\n    idToken: t.id_token,\n    expiresIn: t.expires_in,\n    tokenType: t.token_type,\n    scope: t.scope,\n  };\n}\n\n// ---------------------------------------------------------------------------\n// Promoted functional surface — the ONE thing apps import.\n//\n// `configureIam` + `startLogin({provider?})` + `handleCallback` + session\n// verbs over the configured singleton. See ./session.ts. Re-exported here so\n// `import { startLogin } from \"@hanzo/iam/browser\"` just works.\n// ---------------------------------------------------------------------------\n\nexport {\n  configureIam,\n  startLogin,\n  getLoginUrl,\n  handleCallback,\n  getSession,\n  getUser,\n  logout,\n  getIam,\n  getIamConfig,\n  type IamSessionConfig,\n  type StartLoginOptions,\n  type IamSession,\n} from \"./session.js\";\n"]}