@cboxdk/id-js 0.19.0 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/CHANGELOG.md +213 -0
  2. package/README.md +51 -3
  3. package/RELEASE-CANDIDATE.md +11 -0
  4. package/dist/agent.cjs +613 -0
  5. package/dist/agent.cjs.map +1 -0
  6. package/dist/agent.d.cts +400 -0
  7. package/dist/agent.d.ts +400 -0
  8. package/dist/agent.js +527 -0
  9. package/dist/agent.js.map +1 -0
  10. package/dist/api-keys-BE3R3q_A.d.ts +105 -0
  11. package/dist/api-keys-C8-Q4eFA.d.cts +105 -0
  12. package/dist/chunk-EVZ6RB3K.js +98 -0
  13. package/dist/chunk-EVZ6RB3K.js.map +1 -0
  14. package/dist/{chunk-YGLMLIKL.js → chunk-T5LCQOLS.js} +4 -22
  15. package/dist/chunk-T5LCQOLS.js.map +1 -0
  16. package/dist/chunk-VGQASHTI.js +22 -0
  17. package/dist/chunk-VGQASHTI.js.map +1 -0
  18. package/dist/decisions-C84Fzah4.d.ts +23 -0
  19. package/dist/decisions-DNd9UXwi.d.cts +23 -0
  20. package/dist/index.cjs +127 -14
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.d.cts +1 -0
  23. package/dist/index.d.ts +1 -0
  24. package/dist/index.js +27 -6
  25. package/dist/index.js.map +1 -1
  26. package/dist/management.cjs +352 -19
  27. package/dist/management.cjs.map +1 -1
  28. package/dist/management.d.cts +994 -42
  29. package/dist/management.d.ts +994 -42
  30. package/dist/management.js +352 -19
  31. package/dist/management.js.map +1 -1
  32. package/dist/nextjs.d.cts +1 -1
  33. package/dist/nextjs.d.ts +1 -1
  34. package/dist/nextjs.js +2 -1
  35. package/dist/nextjs.js.map +1 -1
  36. package/dist/server.cjs +103 -9
  37. package/dist/server.cjs.map +1 -1
  38. package/dist/server.d.cts +3 -105
  39. package/dist/server.d.ts +3 -105
  40. package/dist/server.js +1 -0
  41. package/package.json +16 -3
  42. package/dist/chunk-YGLMLIKL.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/agent/errors.ts","../src/agent/http.ts","../src/agent/client-auth.ts","../src/agent/register.ts","../src/agent/grants.ts","../src/agent/binding.ts"],"names":["alg"],"mappings":"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","file":"agent.js","sourcesContent":["import { AuthenticationError, CboxIdError } from '../errors.js';\n\n/**\n * A CIBA, device-grant or registration request was refused with an OAuth error.\n *\n * Extends {@link AuthenticationError}, so `error`, `errorDescription`, `status` and\n * `retryAfter` read the same as on every other back-channel failure in this SDK, and a\n * caller already catching `AuthenticationError` keeps working. Branch on the subclass (or\n * on `error`), never on the message.\n *\n * The REQUEST is never part of the error: these calls carry client assertions, secrets and\n * device codes, and production CLIs log what they throw.\n */\nexport class AgentGrantError extends AuthenticationError {}\n\n/** The person declined (`access_denied`). Final — do not poll again. */\nexport class AccessDeniedError extends AgentGrantError {}\n\n/**\n * The `auth_req_id` or `device_code` expired before anyone approved it (`expired_token`).\n * Also thrown locally when the wait outlives the request's `expires_in`. Start again.\n */\nexport class ExpiredTokenError extends AgentGrantError {}\n\n/** The `auth_req_id`, `device_code` or refresh token is not valid (`invalid_grant`). */\nexport class InvalidGrantError extends AgentGrantError {}\n\n/**\n * The `resource` (RFC 8707) is not one this client may ask for, the poll named a\n * different resource than the request that started it, or the resource lets\n * self-registered clients use CIBA only with `private_key_jwt` and this one is keyless\n * (`invalid_target`).\n */\nexport class InvalidTargetError extends AgentGrantError {}\n\n/**\n * Client authentication failed (`invalid_client`): an unknown `client_id`, a bad secret, an\n * assertion signed by a key the server does not hold, or a replayed `jti`.\n */\nexport class InvalidClientError extends AgentGrantError {}\n\n/** The `login_hint` names nobody the server can reach (`unknown_user_id`). */\nexport class UnknownUserIdError extends AgentGrantError {}\n\n/**\n * The `binding_message` is missing where the server requires one (self-registered clients),\n * or too long to show beside Approve (`invalid_binding_message`).\n */\nexport class InvalidBindingMessageError extends AgentGrantError {}\n\n/**\n * The server asked us to slow down (`slow_down`, or HTTP 429). `retryAfter` carries the\n * `Retry-After` seconds when the server sent them. The wait helpers absorb this themselves;\n * it is thrown only from a call that does not loop (registration, starting a flow).\n */\nexport class SlowDownError extends AgentGrantError {}\n\n/** The caller aborted the wait (its `AbortSignal` fired). */\nexport class GrantCancelledError extends CboxIdError {}\n\nconst BY_CODE: Record<string, typeof AgentGrantError> = {\n access_denied: AccessDeniedError,\n expired_token: ExpiredTokenError,\n invalid_grant: InvalidGrantError,\n invalid_target: InvalidTargetError,\n invalid_client: InvalidClientError,\n unknown_user_id: UnknownUserIdError,\n invalid_binding_message: InvalidBindingMessageError,\n slow_down: SlowDownError,\n};\n\n/** A parsed `{ error, error_description }` body plus the bits of the response that matter. */\nexport interface OAuthFailure {\n error: string | undefined;\n errorDescription: string | undefined;\n status: number;\n retryAfter: number | undefined;\n}\n\n/**\n * Read an OAuth error body without ever echoing it. A 502 from a proxy is HTML, and an\n * error page that reflects the request would put a client assertion into a log line — so\n * only the server's own `error` code (or the status) reaches the message.\n */\nexport async function readOAuthFailure(response: Response): Promise<OAuthFailure> {\n const text = await response.text().catch(() => '');\n let error: string | undefined;\n let errorDescription: string | undefined;\n\n try {\n const parsed: unknown = JSON.parse(text);\n\n if (typeof parsed === 'object' && parsed !== null) {\n const record = parsed as Record<string, unknown>;\n error = typeof record['error'] === 'string' ? record['error'] : undefined;\n errorDescription = typeof record['error_description'] === 'string' ? record['error_description'] : undefined;\n }\n } catch {\n // Not JSON: the status alone is what there is to report.\n }\n\n // A 429 IS slow_down, whatever (or whether) the body says — the limiter in front of the\n // endpoint may answer before the OAuth layer does.\n if (response.status === 429 && error === undefined) {\n error = 'slow_down';\n }\n\n // Seconds only. The HTTP-date form is legal but guessing at clock skew is worse than\n // falling back to the +5s rule.\n const header = response.headers.get('retry-after');\n const retryAfter = header !== null && /^\\d+$/.test(header.trim()) ? Number(header.trim()) : undefined;\n\n return { error, errorDescription, status: response.status, retryAfter };\n}\n\n/** The typed error for a failure: a subclass for the codes callers branch on, else the base. */\nexport function grantError(failure: OAuthFailure, fallback: string): AgentGrantError {\n const Klass = (failure.error !== undefined ? BY_CODE[failure.error] : undefined) ?? AgentGrantError;\n const detail = failure.error ?? `HTTP ${failure.status}`;\n\n return new Klass(`${fallback}: ${detail}`, failure.error, failure.errorDescription, failure.status, failure.retryAfter);\n}\n","import { assertSecureIssuer } from '../issuer.js';\nimport { AuthenticationError, ConfigurationError } from '../errors.js';\nimport { GrantCancelledError } from './errors.js';\n\n/**\n * RFC 8414 authorization server metadata, as Cbox ID publishes it at\n * `{issuer}/.well-known/oauth-authorization-server`. Only the members this module reads are\n * typed; the rest pass through.\n */\nexport interface AuthorizationServerMetadata {\n issuer: string;\n token_endpoint: string;\n registration_endpoint?: string;\n backchannel_authentication_endpoint?: string;\n device_authorization_endpoint?: string;\n backchannel_token_delivery_modes_supported?: string[];\n backchannel_user_code_parameter_supported?: boolean;\n grant_types_supported?: string[];\n token_endpoint_auth_methods_supported?: string[];\n token_endpoint_auth_signing_alg_values_supported?: string[];\n [member: string]: unknown;\n}\n\n/** Transport options every call in this module takes. */\nexport interface AgentRequestOptions {\n /** A `fetch` to use instead of the global one (tests, proxies, instrumentation). */\n fetch?: typeof fetch;\n /** Per-request timeout in milliseconds. Default 10 000. */\n timeoutMs?: number;\n /** Abort the call (and, for the wait helpers, the whole wait). */\n signal?: AbortSignal;\n}\n\n/** Where to find the server: its issuer, and optionally metadata you already discovered. */\nexport interface AgentServerOptions extends AgentRequestOptions {\n /** The Cbox ID issuer, e.g. `https://acme.cboxid.com`. Must be https (loopback excepted). */\n issuer: string;\n /**\n * Metadata from {@link discoverAuthorizationServer}. Pass it to skip a discovery round\n * trip per call; omitted, each call discovers it (the wait helpers discover once).\n */\n metadata?: AuthorizationServerMetadata;\n}\n\n/**\n * Fetch and check the authorization server metadata (RFC 8414).\n *\n * The document's `issuer` must equal the one asked for (§3.3) — otherwise a host answering\n * with another tenant's metadata would receive this client's assertions and codes.\n */\nexport async function discoverAuthorizationServer(\n issuer: string,\n options: AgentRequestOptions = {},\n): Promise<AuthorizationServerMetadata> {\n if (!issuer) {\n throw new ConfigurationError('An `issuer` is required.');\n }\n assertSecureIssuer(issuer);\n\n const url = `${trimSlash(issuer)}/.well-known/oauth-authorization-server`;\n const response = await send(url, { method: 'GET', headers: { accept: 'application/json' } }, options);\n\n if (!response.ok) {\n throw new AuthenticationError(`Discovery request failed with status ${response.status}.`, undefined, undefined, response.status);\n }\n\n let doc: unknown;\n try {\n doc = await response.json();\n } catch {\n throw new AuthenticationError('The authorization server metadata was not JSON.');\n }\n\n if (typeof doc !== 'object' || doc === null) {\n throw new AuthenticationError('The authorization server metadata was not an object.');\n }\n\n const metadata = doc as AuthorizationServerMetadata;\n\n if (typeof metadata.issuer !== 'string' || trimSlash(metadata.issuer) !== trimSlash(issuer)) {\n throw new AuthenticationError(`The authorization server metadata is for a different issuer (${String(metadata.issuer)}).`);\n }\n if (typeof metadata.token_endpoint !== 'string' || metadata.token_endpoint === '') {\n throw new AuthenticationError('The authorization server metadata has no token_endpoint.');\n }\n\n return metadata;\n}\n\n/** Metadata from the options, or discovered. */\nexport function resolveMetadata(options: AgentServerOptions): Promise<AuthorizationServerMetadata> {\n return options.metadata !== undefined\n ? Promise.resolve(options.metadata)\n : discoverAuthorizationServer(options.issuer, options);\n}\n\n/** A named endpoint, or a ConfigurationError saying the server does not offer it. */\nexport function requireEndpoint(\n metadata: AuthorizationServerMetadata,\n name: 'registration_endpoint' | 'backchannel_authentication_endpoint' | 'device_authorization_endpoint' | 'token_endpoint',\n what: string,\n): string {\n const value = metadata[name];\n if (typeof value !== 'string' || value === '') {\n throw new ConfigurationError(`This Cbox ID instance does not advertise a ${name}, so it does not support ${what}.`);\n }\n return value;\n}\n\n/**\n * `fetch` with a timeout and the caller's signal combined. A caller abort becomes\n * {@link GrantCancelledError}; a timeout or network failure an {@link AuthenticationError}.\n */\nexport async function send(url: string, init: RequestInit, options: AgentRequestOptions): Promise<Response> {\n const fetchImpl = options.fetch ?? globalThis.fetch;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), options.timeoutMs ?? 10_000);\n const onAbort = (): void => controller.abort();\n\n if (options.signal?.aborted === true) {\n clearTimeout(timer);\n throw new GrantCancelledError('The request was cancelled.');\n }\n options.signal?.addEventListener('abort', onAbort, { once: true });\n\n try {\n return await fetchImpl(url, { ...init, signal: controller.signal });\n } catch (error) {\n // Re-read through a widened type: the early return above narrowed `aborted` to false,\n // but the signal may have fired while the request was in flight.\n if ((options.signal as AbortSignal | undefined)?.aborted === true) {\n throw new GrantCancelledError('The request was cancelled.');\n }\n if (controller.signal.aborted) {\n throw new AuthenticationError(`The request to ${new URL(url).origin} timed out.`);\n }\n throw new AuthenticationError(`The request to ${new URL(url).origin} failed: ${String(error)}`);\n } finally {\n clearTimeout(timer);\n options.signal?.removeEventListener('abort', onAbort);\n }\n}\n\nexport function trimSlash(value: string): string {\n return value.replace(/\\/+$/, '');\n}\n","import { calculateJwkThumbprint, exportJWK, generateKeyPair, importJWK, SignJWT, type JWK } from 'jose';\nimport { ConfigurationError } from '../errors.js';\nimport { randomToken } from '../pkce.js';\n\n/** The client-assertion algorithms this module signs with. Cbox ID accepts both. */\nexport type ClientKeyAlgorithm = 'ES256' | 'RS256';\n\n/** A signing key pair for `private_key_jwt`, from {@link generateClientKeyPair}. */\nexport interface ClientKeyPair {\n alg: ClientKeyAlgorithm;\n /** The RFC 7638 thumbprint of the public key, used as `kid`. */\n kid: string;\n /** The public JWK (with `kid`, `alg`, `use: 'sig'`) — what registration sends in `jwks`. */\n publicJwk: JWK;\n /**\n * The private JWK. PERSIST THIS, and only this, somewhere the user alone can read\n * (mode 0600, the OS keychain). It is the client's credential: whoever holds it is the\n * client. Never log it, never commit it.\n */\n privateJwk: JWK;\n /** The private key as a WebCrypto `CryptoKey`, ready to sign with. */\n privateKey: CryptoKey;\n}\n\n/**\n * How the client authenticates at the backchannel, device and token endpoints.\n *\n * - `private_key_jwt` (RFC 7523): a short-lived assertion signed with your private key.\n * The right choice for a self-registered agent or CLI: nothing secret ever crosses the\n * wire, and the server stores only the public key.\n * - `client_secret_basic` / `client_secret_post`: a console-issued secret.\n * - `none`: a public client names itself by `client_id` only. Fine for the device grant.\n * For CIBA, Cbox ID accepts a keyless self-registered client only when the resource\n * allows it (`dynamic_public_backchannel`); otherwise the answer is `invalid_target`.\n * Prefer `private_key_jwt` for CIBA: a public `client_id` proves nothing, and CIBA has no front\n * channel to bind the flow to.\n */\nexport type ClientAuth =\n | {\n method: 'private_key_jwt';\n clientId: string;\n /** A `CryptoKey`, or the private JWK you persisted from {@link generateClientKeyPair}. */\n privateKey: CryptoKey | JWK;\n /** Inferred from the key when omitted. */\n alg?: ClientKeyAlgorithm;\n /** Sent as the assertion's `kid`. Taken from a JWK's own `kid` when omitted. */\n kid?: string;\n }\n | { method: 'client_secret_basic' | 'client_secret_post'; clientId: string; clientSecret: string }\n | { method: 'none'; clientId: string };\n\n/**\n * A fresh signing key pair for `private_key_jwt`, generated with WebCrypto (via `jose`), so\n * it runs on Node, Deno, Bun and edge runtimes. ES256 by default — small keys, small\n * signatures. The private key is extractable on purpose: the caller must persist it.\n */\nexport async function generateClientKeyPair(alg: ClientKeyAlgorithm = 'ES256'): Promise<ClientKeyPair> {\n const { publicKey, privateKey } = await generateKeyPair(alg, { extractable: true });\n const publicBare = await exportJWK(publicKey);\n const kid = await calculateJwkThumbprint(publicBare, 'sha256');\n\n const publicJwk: JWK = { ...publicBare, kid, alg, use: 'sig' };\n const privateJwk: JWK = { ...(await exportJWK(privateKey)), kid, alg, use: 'sig' };\n\n return { alg, kid, publicJwk, privateJwk, privateKey };\n}\n\n/**\n * A signed RFC 7523 client assertion: `iss` = `sub` = client id, `aud` = the token\n * endpoint, a random `jti` (the server remembers it, so each assertion is single-use),\n * `iat` now and `exp` at most 60 seconds later.\n */\nexport async function createClientAssertion(\n auth: Extract<ClientAuth, { method: 'private_key_jwt' }>,\n audience: string,\n options: { now?: () => number; lifetimeSeconds?: number } = {},\n): Promise<string> {\n const lifetime = Math.min(Math.max(options.lifetimeSeconds ?? 60, 1), 60);\n const nowSeconds = Math.floor((options.now ?? Date.now)() / 1000);\n const { key, alg, kid } = await signingKey(auth);\n\n const header: { alg: string; kid?: string } = { alg };\n if (kid !== undefined) {\n header.kid = kid;\n }\n\n return new SignJWT({})\n .setProtectedHeader(header)\n .setIssuer(auth.clientId)\n .setSubject(auth.clientId)\n .setAudience(audience)\n .setJti(randomToken(16))\n .setIssuedAt(nowSeconds)\n .setExpirationTime(nowSeconds + lifetime)\n .sign(key);\n}\n\n/**\n * Put client authentication on a request: fields in the form body, and/or an\n * `Authorization` header. `audience` is the token endpoint, the one value Cbox ID accepts\n * on assertions to all of its endpoints.\n */\nexport async function applyClientAuth(\n auth: ClientAuth,\n body: URLSearchParams,\n headers: Record<string, string>,\n audience: string,\n): Promise<void> {\n if (!auth.clientId) {\n throw new ConfigurationError('A `clientId` is required.');\n }\n\n switch (auth.method) {\n case 'private_key_jwt':\n body.set('client_id', auth.clientId);\n body.set('client_assertion_type', 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer');\n body.set('client_assertion', await createClientAssertion(auth, audience));\n return;\n case 'client_secret_basic':\n if (!auth.clientSecret) {\n throw new ConfigurationError('`client_secret_basic` needs a `clientSecret`.');\n }\n // RFC 6749 §2.3.1: both halves are form-encoded before they are joined.\n headers['authorization'] = `Basic ${btoa(`${formEncode(auth.clientId)}:${formEncode(auth.clientSecret)}`)}`;\n return;\n case 'client_secret_post':\n if (!auth.clientSecret) {\n throw new ConfigurationError('`client_secret_post` needs a `clientSecret`.');\n }\n body.set('client_id', auth.clientId);\n body.set('client_secret', auth.clientSecret);\n return;\n case 'none':\n body.set('client_id', auth.clientId);\n return;\n }\n}\n\nasync function signingKey(\n auth: Extract<ClientAuth, { method: 'private_key_jwt' }>,\n): Promise<{ key: CryptoKey | Uint8Array; alg: ClientKeyAlgorithm; kid: string | undefined }> {\n const source = auth.privateKey;\n\n if (isCryptoKey(source)) {\n const alg = auth.alg ?? algFromCryptoKey(source);\n return { key: source, alg, kid: auth.kid };\n }\n\n if (typeof source !== 'object' || source === null || typeof source.d !== 'string') {\n throw new ConfigurationError('`privateKey` must be a CryptoKey or a private JWK (with `d`).');\n }\n\n const alg = auth.alg ?? algFromJwk(source);\n const key = await importJWK(source, alg);\n\n return { key, alg, kid: auth.kid ?? (typeof source.kid === 'string' ? source.kid : undefined) };\n}\n\nfunction isCryptoKey(value: unknown): value is CryptoKey {\n return typeof CryptoKey !== 'undefined' && value instanceof CryptoKey;\n}\n\nfunction algFromCryptoKey(key: CryptoKey): ClientKeyAlgorithm {\n if (key.algorithm.name === 'ECDSA') {\n return 'ES256';\n }\n if (key.algorithm.name === 'RSASSA-PKCS1-v1_5') {\n return 'RS256';\n }\n throw new ConfigurationError(`Unsupported client key algorithm ${key.algorithm.name}; use ES256 or RS256.`);\n}\n\nfunction algFromJwk(jwk: JWK): ClientKeyAlgorithm {\n if (jwk.alg === 'ES256' || jwk.alg === 'RS256') {\n return jwk.alg as ClientKeyAlgorithm;\n }\n if (jwk.alg === undefined && jwk.kty === 'EC' && jwk.crv === 'P-256') {\n return 'ES256';\n }\n if (jwk.alg === undefined && jwk.kty === 'RSA') {\n return 'RS256';\n }\n throw new ConfigurationError('The private JWK is not an ES256 (P-256) or RS256 key.');\n}\n\nfunction formEncode(value: string): string {\n return encodeURIComponent(value).replace(/%20/g, '+');\n}\n","import { AuthenticationError, ConfigurationError } from '../errors.js';\nimport { generateClientKeyPair, type ClientAuth, type ClientKeyAlgorithm, type ClientKeyPair } from './client-auth.js';\nimport { grantError, readOAuthFailure } from './errors.js';\nimport { requireEndpoint, resolveMetadata, send, type AgentServerOptions } from './http.js';\n\n/** The CIBA grant type (OpenID CIBA Core). */\nexport const CIBA_GRANT_TYPE = 'urn:openid:params:grant-type:ciba';\n/** The device authorization grant type (RFC 8628). */\nexport const DEVICE_CODE_GRANT_TYPE = 'urn:ietf:params:oauth:grant-type:device_code';\n\nexport interface RegisterAgentClientOptions extends AgentServerOptions {\n /** Shown to the person approving, so make it recognisable: \"Cbox Brain CLI on ada-mbp\". */\n clientName: string;\n /** e.g. `[CIBA_GRANT_TYPE, 'refresh_token']` or `[DEVICE_CODE_GRANT_TYPE, 'refresh_token']`. */\n grantTypes: string[];\n /** The scope ceiling to register. A space-separated string or a list. */\n scope?: string | string[];\n /**\n * `private_key_jwt` (default): a key pair is generated (or `keyPair` used) and the\n * public half registered inline as `jwks`. `none`: a public client — the device grant,\n * or CIBA where the resource allows keyless clients. `private_key_jwt` is recommended for CIBA.\n */\n tokenEndpointAuthMethod?: 'private_key_jwt' | 'none';\n /** Algorithm for the generated key pair. Default ES256. */\n alg?: ClientKeyAlgorithm;\n /** Register an existing key pair instead of generating one. */\n keyPair?: ClientKeyPair;\n /** RFC 7591 §3 initial access token, when the instance requires one to register. */\n initialAccessToken?: string;\n /** Further RFC 7591 client metadata, sent as-is (e.g. `software_id`, `client_uri`). */\n extraMetadata?: Record<string, unknown>;\n}\n\nexport interface RegisteredAgentClient {\n clientId: string;\n /** Present only if the server issued one; a `private_key_jwt` or `none` client has none. */\n clientSecret: string | null;\n /** RFC 7592 credential for reading/updating/deleting the registration. Persist it if you need that. */\n registrationAccessToken: string | null;\n registrationClientUri: string | null;\n tokenEndpointAuthMethod: string;\n grantTypes: string[];\n scope: string | null;\n /** The key pair registered, for `private_key_jwt`. Persist `keyPair.privateJwk`. */\n keyPair: ClientKeyPair | null;\n /** Ready to hand to {@link startBackchannel} / {@link startDeviceAuthorization}. */\n auth: ClientAuth;\n /** The full registration response. */\n raw: Record<string, unknown>;\n}\n\n/**\n * Register this agent or CLI as an OAuth client (RFC 7591 dynamic client registration).\n *\n * Do it once per installation and persist the result: `clientId` and, for\n * `private_key_jwt`, `keyPair.privateJwk`. Re-registering on every run fills the\n * environment's app list with copies.\n *\n * @throws ConfigurationError when the instance has dynamic registration switched off.\n * @throws AgentGrantError (e.g. `invalid_client_metadata`) when the server refuses.\n */\nexport async function registerAgentClient(options: RegisterAgentClientOptions): Promise<RegisteredAgentClient> {\n if (!options.clientName) {\n throw new ConfigurationError('`clientName` is required.');\n }\n if (options.grantTypes.length === 0) {\n throw new ConfigurationError('`grantTypes` must name at least one grant.');\n }\n\n const metadata = await resolveMetadata(options);\n const endpoint = requireEndpoint(metadata, 'registration_endpoint', 'dynamic client registration');\n const method = options.tokenEndpointAuthMethod ?? 'private_key_jwt';\n\n const keyPair = method === 'private_key_jwt'\n ? options.keyPair ?? (await generateClientKeyPair(options.alg ?? 'ES256'))\n : null;\n\n const document: Record<string, unknown> = {\n ...options.extraMetadata,\n client_name: options.clientName,\n grant_types: options.grantTypes,\n token_endpoint_auth_method: method,\n // Neither CIBA nor the device grant has a redirect; say so rather than let the server\n // assume an authorization-code client.\n redirect_uris: [],\n response_types: [],\n };\n\n if (options.scope !== undefined) {\n document['scope'] = scopeString(options.scope);\n }\n if (keyPair !== null) {\n document['jwks'] = { keys: [keyPair.publicJwk] };\n }\n\n const headers: Record<string, string> = { 'content-type': 'application/json', accept: 'application/json' };\n if (options.initialAccessToken) {\n headers['authorization'] = `Bearer ${options.initialAccessToken}`;\n }\n\n const response = await send(endpoint, { method: 'POST', headers, body: JSON.stringify(document) }, options);\n\n if (!response.ok) {\n throw grantError(await readOAuthFailure(response), 'Client registration failed');\n }\n\n const raw = (await response.json().catch(() => null)) as Record<string, unknown> | null;\n const clientId = raw?.['client_id'];\n\n if (raw === null || typeof clientId !== 'string' || clientId === '') {\n throw new AuthenticationError('The registration response carried no client_id.');\n }\n\n const clientSecret = typeof raw['client_secret'] === 'string' ? raw['client_secret'] : null;\n const registeredMethod = typeof raw['token_endpoint_auth_method'] === 'string' ? raw['token_endpoint_auth_method'] : method;\n\n let auth: ClientAuth;\n if (keyPair !== null) {\n auth = { method: 'private_key_jwt', clientId, privateKey: keyPair.privateKey, alg: keyPair.alg, kid: keyPair.kid };\n } else if (clientSecret !== null) {\n auth = { method: 'client_secret_basic', clientId, clientSecret };\n } else {\n auth = { method: 'none', clientId };\n }\n\n return {\n clientId,\n clientSecret,\n registrationAccessToken: typeof raw['registration_access_token'] === 'string' ? raw['registration_access_token'] : null,\n registrationClientUri: typeof raw['registration_client_uri'] === 'string' ? raw['registration_client_uri'] : null,\n tokenEndpointAuthMethod: registeredMethod,\n grantTypes: Array.isArray(raw['grant_types']) ? raw['grant_types'].filter((g): g is string => typeof g === 'string') : options.grantTypes,\n scope: typeof raw['scope'] === 'string' ? raw['scope'] : null,\n keyPair,\n auth,\n raw,\n };\n}\n\nexport function scopeString(scope: string | string[]): string {\n return (typeof scope === 'string' ? scope.split(/\\s+/) : scope).filter((s) => s !== '').join(' ');\n}\n","import { AuthenticationError, ConfigurationError } from '../errors.js';\nimport { applyClientAuth, type ClientAuth } from './client-auth.js';\nimport { ExpiredTokenError, GrantCancelledError, grantError, readOAuthFailure } from './errors.js';\nimport {\n requireEndpoint,\n resolveMetadata,\n send,\n type AgentServerOptions,\n type AuthorizationServerMetadata,\n} from './http.js';\nimport { CIBA_GRANT_TYPE, DEVICE_CODE_GRANT_TYPE, scopeString } from './register.js';\n\n/** Tokens from a completed CIBA or device grant. */\nexport interface AgentTokens {\n accessToken: string;\n tokenType: string;\n /** Seconds, when the server said. */\n expiresIn: number | null;\n refreshToken: string | null;\n /**\n * The id_token, when `openid` was granted — returned as-is, NOT verified here. Verify it\n * with `CboxIdClient` (or `jose` against the JWKS) before trusting anything in it.\n */\n idToken: string | null;\n scope: string | null;\n /** The full token response. */\n raw: Record<string, unknown>;\n}\n\n/** One poll's outcome. Final failures are thrown, not returned. */\nexport type PollResult =\n | { status: 'complete'; tokens: AgentTokens }\n | { status: 'pending' }\n /** Slow down: add 5 s to the interval, and wait at least `retryAfter` seconds if given. */\n | { status: 'slow_down'; retryAfter: number | null };\n\n/** Options shared by the wait helpers. */\nexport interface WaitOptions {\n /** Replace the timer — tests pass a fake that records the waits. Must honour `signal`. */\n sleep?: (ms: number, signal?: AbortSignal) => Promise<void>;\n /** Clock in epoch milliseconds. Default `Date.now`. */\n now?: () => number;\n}\n\ninterface ClientOptions extends AgentServerOptions {\n /** How the client authenticates. See {@link ClientAuth}. */\n client: ClientAuth;\n}\n\n// ---------------------------------------------------------------------------------------\n// CIBA (poll mode)\n// ---------------------------------------------------------------------------------------\n\nexport interface StartBackchannelOptions extends ClientOptions {\n /** Who should approve: a Cbox ID user id, or a confirmed email address. */\n loginHint: string;\n /** Space-separated string or list. Bounded by the client's registered scopes. */\n scope: string | string[];\n /**\n * Shown beside Approve. Put a {@link createBindingCode} code in it and print the same\n * code locally. Required by Cbox ID for self-registered clients; at most 255 characters.\n */\n bindingMessage: string;\n /**\n * RFC 8707 resource indicator(s) — the API the token is for. Optional in the type, but\n * REQUIRED by Cbox ID for self-registered clients.\n * Its settings also decide whether a keyless (`none`) client may use CIBA at all.\n */\n resource?: string | string[];\n /** Seconds the request may wait for approval (the server may shorten it). */\n requestedExpiry?: number;\n /** Echoed into the id_token, so you can bind it to this request. */\n nonce?: string;\n}\n\n/** A started CIBA request. Persistable as JSON. */\nexport interface BackchannelAuthorization {\n authReqId: string;\n expiresIn: number;\n /** Seconds between polls. */\n interval: number;\n /** Epoch ms after which polling is pointless. */\n expiresAt: number;\n /** The resource(s) the request named, re-sent on every poll (the server checks they match). */\n resource: string[];\n}\n\n/**\n * Start a CIBA request (OpenID CIBA Core §7, poll mode): Cbox ID shows `bindingMessage` to\n * the person named by `loginHint` and waits for Approve.\n *\n * `backchannel_user_code_parameter` is not supported by Cbox ID, so no user code is sent.\n *\n * @throws InvalidClientError, UnknownUserIdError, InvalidBindingMessageError,\n * InvalidTargetError, SlowDownError, AgentGrantError.\n */\nexport async function startBackchannel(options: StartBackchannelOptions): Promise<BackchannelAuthorization> {\n const now = Date.now();\n const metadata = await resolveMetadata(options);\n const endpoint = requireEndpoint(metadata, 'backchannel_authentication_endpoint', 'CIBA');\n\n if (!options.loginHint) {\n throw new ConfigurationError('`loginHint` is required.');\n }\n\n const resource = resourceList(options.resource);\n const body = new URLSearchParams({ login_hint: options.loginHint, scope: scopeString(options.scope) });\n\n if (options.bindingMessage !== '') {\n body.set('binding_message', options.bindingMessage);\n }\n for (const r of resource) {\n body.append('resource', r);\n }\n if (options.requestedExpiry !== undefined) {\n body.set('requested_expiry', String(options.requestedExpiry));\n }\n if (options.nonce !== undefined && options.nonce !== '') {\n body.set('nonce', options.nonce);\n }\n\n const payload = await postForm(endpoint, body, options, metadata, 'Backchannel authentication request failed');\n const authReqId = payload['auth_req_id'];\n\n if (typeof authReqId !== 'string' || authReqId === '') {\n throw new AuthenticationError('The backchannel authentication response carried no auth_req_id.');\n }\n\n const expiresIn = positiveNumber(payload['expires_in']) ?? 120;\n\n return {\n authReqId,\n expiresIn,\n // CIBA Core §7.3: absent means 5 seconds.\n interval: positiveNumber(payload['interval']) ?? 5,\n expiresAt: now + expiresIn * 1000,\n resource,\n };\n}\n\nexport interface PollBackchannelOptions extends ClientOptions {\n authorization: Pick<BackchannelAuthorization, 'authReqId' | 'resource'>;\n}\n\n/**\n * Poll the token endpoint once for a CIBA request.\n *\n * @throws AccessDeniedError, ExpiredTokenError, InvalidGrantError, InvalidTargetError,\n * InvalidClientError, AgentGrantError.\n */\nexport async function pollBackchannel(options: PollBackchannelOptions): Promise<PollResult> {\n const body = new URLSearchParams({ grant_type: CIBA_GRANT_TYPE, auth_req_id: options.authorization.authReqId });\n return pollToken(body, options.authorization.resource, options, 'Backchannel token request failed');\n}\n\n/**\n * Poll until the person approves, and return the tokens.\n *\n * Waits `interval` seconds before each poll; on `slow_down` (or a 429) adds five seconds\n * for good and waits at least `Retry-After`; keeps going on `authorization_pending`; stops\n * on anything final. Throws {@link ExpiredTokenError} once `expiresAt` passes and\n * {@link GrantCancelledError} when `signal` fires — wire it to Ctrl-C.\n */\nexport async function waitForBackchannelToken(\n options: PollBackchannelOptions & WaitOptions & { authorization: BackchannelAuthorization },\n): Promise<AgentTokens> {\n const metadata = await resolveMetadata(options);\n const authorization = options.authorization;\n\n return waitLoop(authorization, options, () => pollBackchannel({ ...options, metadata }), 'backchannel request');\n}\n\n// ---------------------------------------------------------------------------------------\n// Device authorization grant (RFC 8628)\n// ---------------------------------------------------------------------------------------\n\nexport interface StartDeviceAuthorizationOptions extends ClientOptions {\n scope?: string | string[];\n /** RFC 8707 resource indicator(s). */\n resource?: string | string[];\n}\n\n/** A started device authorization. Persistable as JSON. */\nexport interface DeviceGrantAuthorization {\n deviceCode: string;\n /** Show this to the person. */\n userCode: string;\n /** Where they enter it. */\n verificationUri: string;\n /** The same page with the code filled in — good for a QR code or `open`. */\n verificationUriComplete: string | null;\n expiresIn: number;\n interval: number;\n expiresAt: number;\n resource: string[];\n}\n\n/**\n * Start the device authorization grant: you get a `userCode` to show and a\n * `verificationUri` for the person to open on any device.\n *\n * @throws InvalidClientError, InvalidTargetError, SlowDownError, AgentGrantError.\n */\nexport async function startDeviceAuthorization(options: StartDeviceAuthorizationOptions): Promise<DeviceGrantAuthorization> {\n const now = Date.now();\n const metadata = await resolveMetadata(options);\n const endpoint = requireEndpoint(metadata, 'device_authorization_endpoint', 'the device grant');\n const resource = resourceList(options.resource);\n const body = new URLSearchParams();\n\n if (options.scope !== undefined) {\n body.set('scope', scopeString(options.scope));\n }\n for (const r of resource) {\n body.append('resource', r);\n }\n\n const payload = await postForm(endpoint, body, options, metadata, 'Device authorization request failed');\n const deviceCode = payload['device_code'];\n const userCode = payload['user_code'];\n const verificationUri = payload['verification_uri'];\n\n if (typeof deviceCode !== 'string' || typeof userCode !== 'string' || typeof verificationUri !== 'string') {\n throw new AuthenticationError('The device authorization response was incomplete.');\n }\n\n const expiresIn = positiveNumber(payload['expires_in']) ?? 600;\n\n return {\n deviceCode,\n userCode,\n verificationUri,\n verificationUriComplete: typeof payload['verification_uri_complete'] === 'string' ? payload['verification_uri_complete'] : null,\n expiresIn,\n // RFC 8628 §3.2: absent means 5 seconds.\n interval: positiveNumber(payload['interval']) ?? 5,\n expiresAt: now + expiresIn * 1000,\n resource,\n };\n}\n\nexport interface PollDeviceAuthorizationOptions extends ClientOptions {\n authorization: Pick<DeviceGrantAuthorization, 'deviceCode' | 'resource'>;\n}\n\n/** Poll the token endpoint once for a device authorization. */\nexport async function pollDeviceAuthorization(options: PollDeviceAuthorizationOptions): Promise<PollResult> {\n const body = new URLSearchParams({ grant_type: DEVICE_CODE_GRANT_TYPE, device_code: options.authorization.deviceCode });\n return pollToken(body, options.authorization.resource, options, 'Device token request failed');\n}\n\n/** Poll until the person approves the device code. Same rules as {@link waitForBackchannelToken}. */\nexport async function waitForDeviceToken(\n options: PollDeviceAuthorizationOptions & WaitOptions & { authorization: DeviceGrantAuthorization },\n): Promise<AgentTokens> {\n const metadata = await resolveMetadata(options);\n\n return waitLoop(options.authorization, options, () => pollDeviceAuthorization({ ...options, metadata }), 'device code');\n}\n\n// ---------------------------------------------------------------------------------------\n// Refresh\n// ---------------------------------------------------------------------------------------\n\nexport interface RefreshAgentTokensOptions extends ClientOptions {\n refreshToken: string;\n /** Narrow the scope (never widen it). */\n scope?: string | string[];\n /** RFC 8707 resource indicator(s) for the new access token. */\n resource?: string | string[];\n}\n\n/**\n * Exchange a refresh token, authenticating the same way the grant did (including\n * `private_key_jwt`). Cbox ID rotates refresh tokens and revokes the family on reuse, so\n * ALWAYS persist the returned `refreshToken` and discard the old one.\n *\n * @throws InvalidGrantError when the refresh token is no longer valid — sign in again.\n */\nexport async function refreshAgentTokens(options: RefreshAgentTokensOptions): Promise<AgentTokens> {\n if (!options.refreshToken) {\n throw new ConfigurationError('`refreshToken` is required.');\n }\n\n const body = new URLSearchParams({ grant_type: 'refresh_token', refresh_token: options.refreshToken });\n if (options.scope !== undefined) {\n body.set('scope', scopeString(options.scope));\n }\n\n // `polling: false`: pending and slow_down mean nothing on a refresh, so they are thrown\n // like any other refusal (a 429 as SlowDownError with its Retry-After).\n const result = await pollToken(body, resourceList(options.resource), options, 'Token refresh failed', false);\n\n return (result as Extract<PollResult, { status: 'complete' }>).tokens;\n}\n\n// ---------------------------------------------------------------------------------------\n// Shared\n// ---------------------------------------------------------------------------------------\n\nasync function waitLoop(\n authorization: { interval: number; expiresAt: number },\n options: WaitOptions & { signal?: AbortSignal },\n poll: () => Promise<PollResult>,\n what: string,\n): Promise<AgentTokens> {\n const sleep = options.sleep ?? defaultSleep;\n const now = options.now ?? Date.now;\n let intervalMs = Math.max(authorization.interval, 0) * 1000;\n let nextWaitMs = intervalMs;\n\n for (;;) {\n throwIfAborted(options.signal);\n\n if (now() >= authorization.expiresAt) {\n throw new ExpiredTokenError(`The ${what} expired before it was approved. Start again.`, 'expired_token');\n }\n\n await sleep(nextWaitMs, options.signal);\n // A custom sleep may not honour the signal; check again before spending a request.\n throwIfAborted(options.signal);\n\n if (now() >= authorization.expiresAt) {\n throw new ExpiredTokenError(`The ${what} expired before it was approved. Start again.`, 'expired_token');\n }\n\n const result = await poll();\n\n if (result.status === 'complete') {\n return result.tokens;\n }\n\n if (result.status === 'slow_down') {\n // Permanently, not for one round (RFC 8628 §3.5, CIBA Core §11): returning to the\n // refused rate earns the same answer forever.\n intervalMs += 5000;\n nextWaitMs = Math.max(intervalMs, (result.retryAfter ?? 0) * 1000);\n continue;\n }\n\n nextWaitMs = intervalMs;\n }\n}\n\nasync function pollToken(\n body: URLSearchParams,\n resource: readonly string[],\n options: ClientOptions,\n fallback: string,\n polling = true,\n): Promise<PollResult> {\n const metadata = await resolveMetadata(options);\n const endpoint = requireEndpoint(metadata, 'token_endpoint', 'token requests');\n\n // The same resource(s) the request started with; Cbox ID refuses a mismatch with\n // invalid_target.\n for (const r of resource) {\n body.append('resource', r);\n }\n\n const headers: Record<string, string> = { 'content-type': 'application/x-www-form-urlencoded', accept: 'application/json' };\n await applyClientAuth(options.client, body, headers, metadata.token_endpoint);\n\n const response = await send(endpoint, { method: 'POST', headers, body }, options);\n\n if (response.ok) {\n return { status: 'complete', tokens: await tokensFrom(response) };\n }\n\n const failure = await readOAuthFailure(response);\n\n if (polling && failure.error === 'authorization_pending') {\n return { status: 'pending' };\n }\n if (polling && failure.error === 'slow_down') {\n return { status: 'slow_down', retryAfter: failure.retryAfter ?? null };\n }\n\n throw grantError(failure, fallback);\n}\n\nasync function postForm(\n endpoint: string,\n body: URLSearchParams,\n options: ClientOptions,\n metadata: AuthorizationServerMetadata,\n fallback: string,\n): Promise<Record<string, unknown>> {\n const headers: Record<string, string> = { 'content-type': 'application/x-www-form-urlencoded', accept: 'application/json' };\n await applyClientAuth(options.client, body, headers, metadata.token_endpoint);\n\n const response = await send(endpoint, { method: 'POST', headers, body }, options);\n\n if (!response.ok) {\n throw grantError(await readOAuthFailure(response), fallback);\n }\n\n const payload: unknown = await response.json().catch(() => null);\n if (typeof payload !== 'object' || payload === null) {\n throw new AuthenticationError(`${fallback}: the response was not a JSON object.`);\n }\n return payload as Record<string, unknown>;\n}\n\nasync function tokensFrom(response: Response): Promise<AgentTokens> {\n const raw = (await response.json().catch(() => null)) as Record<string, unknown> | null;\n const accessToken = raw?.['access_token'];\n\n if (raw === null || typeof accessToken !== 'string' || accessToken === '') {\n throw new AuthenticationError('The token response carried no access_token.');\n }\n\n return {\n accessToken,\n tokenType: typeof raw['token_type'] === 'string' ? raw['token_type'] : 'Bearer',\n expiresIn: typeof raw['expires_in'] === 'number' ? raw['expires_in'] : null,\n refreshToken: typeof raw['refresh_token'] === 'string' ? raw['refresh_token'] : null,\n idToken: typeof raw['id_token'] === 'string' ? raw['id_token'] : null,\n scope: typeof raw['scope'] === 'string' ? raw['scope'] : null,\n raw,\n };\n}\n\nfunction resourceList(resource: string | string[] | undefined): string[] {\n if (resource === undefined) {\n return [];\n }\n const list = typeof resource === 'string' ? [resource] : [...resource];\n for (const r of list) {\n // RFC 8707 §2: an absolute URI without a fragment.\n let url: URL;\n try {\n url = new URL(r);\n } catch {\n throw new ConfigurationError(`\\`resource\\` must be an absolute URI (got ${r}).`);\n }\n if (url.hash !== '') {\n throw new ConfigurationError('`resource` must not contain a fragment.');\n }\n }\n return list;\n}\n\nfunction positiveNumber(value: unknown): number | null {\n return typeof value === 'number' && Number.isFinite(value) && value >= 0 ? value : null;\n}\n\nfunction throwIfAborted(signal: AbortSignal | undefined): void {\n if (signal?.aborted === true) {\n throw new GrantCancelledError('The wait for approval was cancelled.');\n }\n}\n\n/** An interruptible timer: the abort is wired to the timer, so Ctrl-C does not wait out an interval. */\nfunction defaultSleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted === true) {\n reject(new GrantCancelledError('The wait for approval was cancelled.'));\n return;\n }\n const onAbort = (): void => {\n clearTimeout(timer);\n reject(new GrantCancelledError('The wait for approval was cancelled.'));\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n","import { ConfigurationError } from '../errors.js';\n\n/**\n * Uppercase letters and digits a person cannot confuse when reading them off one screen\n * and matching them on another: no 0/O, 1/I/L, 5/S, 2/Z, 8/B.\n */\nexport const BINDING_CODE_ALPHABET = 'ACDEFGHJKMNPQRTUVWXY34679';\n\n/**\n * A short random code for a CIBA `binding_message`, e.g. `K7QM`.\n *\n * Show it in your terminal and put it in the binding message; Cbox ID shows the message\n * beside Approve, and the person approves only when the two match. That is what stops a\n * prompt somebody else triggered from being approved by reflex. Cbox ID requires a\n * binding message from self-registered clients.\n *\n * Uniform over the alphabet (rejection sampling, WebCrypto randomness).\n */\nexport function createBindingCode(length = 4): string {\n if (!Number.isInteger(length) || length < 1 || length > 32) {\n throw new ConfigurationError('A binding code length must be an integer from 1 to 32.');\n }\n\n const size = BINDING_CODE_ALPHABET.length;\n // The largest multiple of `size` that fits in a byte; bytes at or above it are dropped so\n // every character is equally likely.\n const limit = 256 - (256 % size);\n let code = '';\n\n while (code.length < length) {\n for (const byte of crypto.getRandomValues(new Uint8Array(length * 2))) {\n if (byte < limit && code.length < length) {\n code += BINDING_CODE_ALPHABET[byte % size];\n }\n }\n }\n\n return code;\n}\n"]}
@@ -0,0 +1,105 @@
1
+ import { O as OrganizationRole } from './types-CC1bz68x.js';
2
+
3
+ /**
4
+ * A customer API key Cbox ID vouches for: live, bound to YOUR app, and held by an active
5
+ * member of `org`.
6
+ *
7
+ * The field names are the endpoint's own, so the claim helpers read it like a token —
8
+ * `hasPermission(answer, 'invoices:create')`, `organization(answer)?.role`. (A type
9
+ * alias rather than an interface for that reason: only an alias is assignable to the
10
+ * helpers' record type.)
11
+ */
12
+ type ActiveApiKey = {
13
+ active: true;
14
+ /** The key's id — log this, never the key. */
15
+ key_id: string;
16
+ /** The person who holds the key (their subject id). */
17
+ sub: string;
18
+ /** The organization the key acts in. */
19
+ org: string;
20
+ /** The holder's membership tier in `org`; null for a tier this SDK does not know. */
21
+ org_role: OrganizationRole | null;
22
+ /**
23
+ * What the key may do, already re-capped by Cbox ID: the key's own list intersected
24
+ * with what the holder holds for your app right now. A demoted holder's key loses the
25
+ * permission on the next verification, not at the next reissue.
26
+ */
27
+ permissions: string[];
28
+ /** Your app's client id — always, or the answer is refused. */
29
+ client_id: string;
30
+ /** ISO 8601 UTC expiry, or null for a key that does not expire. */
31
+ expires_at: string | null;
32
+ };
33
+ /**
34
+ * Every refusal: unknown, malformed, revoked, expired, another app's key, a holder who
35
+ * left. Cbox ID never says which, so the endpoint cannot be used to probe keys — and
36
+ * neither does this.
37
+ */
38
+ interface InactiveApiKey {
39
+ active: false;
40
+ }
41
+ /** What {@link ApiKeyVerifier.verifyApiKey} returns. Narrow on `active`. */
42
+ type ApiKeyVerification = ActiveApiKey | InactiveApiKey;
43
+ /** Configuration for an {@link ApiKeyVerifier}. */
44
+ interface ApiKeyVerifierConfig {
45
+ /** Base URL (issuer) of the Cbox ID instance. */
46
+ issuer: string;
47
+ /** Your app's OAuth client id — the app the keys were issued for. */
48
+ clientId: string;
49
+ /** Your app's client secret. Verification is a confidential-client call. */
50
+ clientSecret: string;
51
+ /** Timeout (ms) for the verification request. Defaults to `10000`. */
52
+ timeoutMs?: number;
53
+ /**
54
+ * Cache an ACTIVE answer for this long (ms), so a burst of requests with one key costs
55
+ * one round-trip. Off (`0`) by default and at most {@link MAX_API_KEY_CACHE_TTL_MS}:
56
+ * while an answer is cached, a revoked key keeps working, and a demoted holder keeps
57
+ * the permissions they lost. Never cached past the key's `expires_at`. Refusals are
58
+ * never cached, so a key issued a moment ago works on its first request.
59
+ */
60
+ cacheTtlMs?: number;
61
+ }
62
+ /** The longest {@link ApiKeyVerifierConfig.cacheTtlMs} allowed: one minute. */
63
+ declare const MAX_API_KEY_CACHE_TTL_MS = 60000;
64
+ /**
65
+ * Verifies customer API keys presented to your API: `POST {issuer}/oauth/api-keys/verify`,
66
+ * authenticated with your app's own client credentials.
67
+ *
68
+ * SERVER-SIDE ONLY. It holds your client secret, so it lives in the
69
+ * `@cboxdk/id-js/server` entry and the Next.js adapter, never in the main entry that a
70
+ * browser bundle pulls in — and it refuses to be constructed in a browser at all.
71
+ *
72
+ * ```ts
73
+ * import { ApiKeyVerifier } from '@cboxdk/id-js/server';
74
+ * import { hasPermission } from '@cboxdk/id-js';
75
+ *
76
+ * const keys = new ApiKeyVerifier({ issuer, clientId, clientSecret, cacheTtlMs: 10_000 });
77
+ *
78
+ * const answer = await keys.verifyApiKey(request.headers.get('x-api-key') ?? '');
79
+ * if (!answer.active) return unauthorized();
80
+ * if (!hasPermission(answer, 'invoices:create')) return forbidden();
81
+ * ```
82
+ */
83
+ declare class ApiKeyVerifier {
84
+ private readonly config;
85
+ private readonly endpoint;
86
+ private readonly timeoutMs;
87
+ private readonly cacheTtlMs;
88
+ private readonly cache;
89
+ constructor(config: ApiKeyVerifierConfig);
90
+ /**
91
+ * Ask Cbox ID whether `key` is good for this app, and what it may do.
92
+ *
93
+ * Resolves `{ active: false }` for every kind of bad key, without a request for an empty
94
+ * one. Throws `AuthenticationError` when the call itself fails (wrong client
95
+ * credentials, an unreachable instance) or when the answer cannot be trusted — one that
96
+ * names another app's `client_id`, or does not have the promised shape. Both mean "do
97
+ * not let this request in"; the difference is that a throw is something to look at.
98
+ */
99
+ verifyApiKey(key: string): Promise<ApiKeyVerification>;
100
+ private request;
101
+ private parse;
102
+ private remember;
103
+ }
104
+
105
+ export { type ActiveApiKey as A, type InactiveApiKey as I, MAX_API_KEY_CACHE_TTL_MS as M, type ApiKeyVerification as a, ApiKeyVerifier as b, type ApiKeyVerifierConfig as c };
@@ -0,0 +1,105 @@
1
+ import { O as OrganizationRole } from './types-CC1bz68x.cjs';
2
+
3
+ /**
4
+ * A customer API key Cbox ID vouches for: live, bound to YOUR app, and held by an active
5
+ * member of `org`.
6
+ *
7
+ * The field names are the endpoint's own, so the claim helpers read it like a token —
8
+ * `hasPermission(answer, 'invoices:create')`, `organization(answer)?.role`. (A type
9
+ * alias rather than an interface for that reason: only an alias is assignable to the
10
+ * helpers' record type.)
11
+ */
12
+ type ActiveApiKey = {
13
+ active: true;
14
+ /** The key's id — log this, never the key. */
15
+ key_id: string;
16
+ /** The person who holds the key (their subject id). */
17
+ sub: string;
18
+ /** The organization the key acts in. */
19
+ org: string;
20
+ /** The holder's membership tier in `org`; null for a tier this SDK does not know. */
21
+ org_role: OrganizationRole | null;
22
+ /**
23
+ * What the key may do, already re-capped by Cbox ID: the key's own list intersected
24
+ * with what the holder holds for your app right now. A demoted holder's key loses the
25
+ * permission on the next verification, not at the next reissue.
26
+ */
27
+ permissions: string[];
28
+ /** Your app's client id — always, or the answer is refused. */
29
+ client_id: string;
30
+ /** ISO 8601 UTC expiry, or null for a key that does not expire. */
31
+ expires_at: string | null;
32
+ };
33
+ /**
34
+ * Every refusal: unknown, malformed, revoked, expired, another app's key, a holder who
35
+ * left. Cbox ID never says which, so the endpoint cannot be used to probe keys — and
36
+ * neither does this.
37
+ */
38
+ interface InactiveApiKey {
39
+ active: false;
40
+ }
41
+ /** What {@link ApiKeyVerifier.verifyApiKey} returns. Narrow on `active`. */
42
+ type ApiKeyVerification = ActiveApiKey | InactiveApiKey;
43
+ /** Configuration for an {@link ApiKeyVerifier}. */
44
+ interface ApiKeyVerifierConfig {
45
+ /** Base URL (issuer) of the Cbox ID instance. */
46
+ issuer: string;
47
+ /** Your app's OAuth client id — the app the keys were issued for. */
48
+ clientId: string;
49
+ /** Your app's client secret. Verification is a confidential-client call. */
50
+ clientSecret: string;
51
+ /** Timeout (ms) for the verification request. Defaults to `10000`. */
52
+ timeoutMs?: number;
53
+ /**
54
+ * Cache an ACTIVE answer for this long (ms), so a burst of requests with one key costs
55
+ * one round-trip. Off (`0`) by default and at most {@link MAX_API_KEY_CACHE_TTL_MS}:
56
+ * while an answer is cached, a revoked key keeps working, and a demoted holder keeps
57
+ * the permissions they lost. Never cached past the key's `expires_at`. Refusals are
58
+ * never cached, so a key issued a moment ago works on its first request.
59
+ */
60
+ cacheTtlMs?: number;
61
+ }
62
+ /** The longest {@link ApiKeyVerifierConfig.cacheTtlMs} allowed: one minute. */
63
+ declare const MAX_API_KEY_CACHE_TTL_MS = 60000;
64
+ /**
65
+ * Verifies customer API keys presented to your API: `POST {issuer}/oauth/api-keys/verify`,
66
+ * authenticated with your app's own client credentials.
67
+ *
68
+ * SERVER-SIDE ONLY. It holds your client secret, so it lives in the
69
+ * `@cboxdk/id-js/server` entry and the Next.js adapter, never in the main entry that a
70
+ * browser bundle pulls in — and it refuses to be constructed in a browser at all.
71
+ *
72
+ * ```ts
73
+ * import { ApiKeyVerifier } from '@cboxdk/id-js/server';
74
+ * import { hasPermission } from '@cboxdk/id-js';
75
+ *
76
+ * const keys = new ApiKeyVerifier({ issuer, clientId, clientSecret, cacheTtlMs: 10_000 });
77
+ *
78
+ * const answer = await keys.verifyApiKey(request.headers.get('x-api-key') ?? '');
79
+ * if (!answer.active) return unauthorized();
80
+ * if (!hasPermission(answer, 'invoices:create')) return forbidden();
81
+ * ```
82
+ */
83
+ declare class ApiKeyVerifier {
84
+ private readonly config;
85
+ private readonly endpoint;
86
+ private readonly timeoutMs;
87
+ private readonly cacheTtlMs;
88
+ private readonly cache;
89
+ constructor(config: ApiKeyVerifierConfig);
90
+ /**
91
+ * Ask Cbox ID whether `key` is good for this app, and what it may do.
92
+ *
93
+ * Resolves `{ active: false }` for every kind of bad key, without a request for an empty
94
+ * one. Throws `AuthenticationError` when the call itself fails (wrong client
95
+ * credentials, an unreachable instance) or when the answer cannot be trusted — one that
96
+ * names another app's `client_id`, or does not have the promised shape. Both mean "do
97
+ * not let this request in"; the difference is that a throw is something to look at.
98
+ */
99
+ verifyApiKey(key: string): Promise<ApiKeyVerification>;
100
+ private request;
101
+ private parse;
102
+ private remember;
103
+ }
104
+
105
+ export { type ActiveApiKey as A, type InactiveApiKey as I, MAX_API_KEY_CACHE_TTL_MS as M, type ApiKeyVerification as a, ApiKeyVerifier as b, type ApiKeyVerifierConfig as c };
@@ -0,0 +1,98 @@
1
+ import { assertSecureIssuer } from './chunk-QQW63PGU.js';
2
+ import { ConfigurationError, AuthenticationError } from './chunk-SEUD4TE4.js';
3
+
4
+ // src/decisions.ts
5
+ var PermissionDecision = class {
6
+ constructor(subject, organization, clientId, organizationRole, organizationActive, permissions) {
7
+ this.subject = subject;
8
+ this.organization = organization;
9
+ this.clientId = clientId;
10
+ this.organizationRole = organizationRole;
11
+ this.organizationActive = organizationActive;
12
+ this.permissions = permissions;
13
+ }
14
+ subject;
15
+ organization;
16
+ clientId;
17
+ organizationRole;
18
+ organizationActive;
19
+ permissions;
20
+ allows(permission) {
21
+ return this.organizationActive && this.permissions[permission] === true;
22
+ }
23
+ allowed() {
24
+ const values = Object.values(this.permissions);
25
+ return this.organizationActive && values.length > 0 && values.every((value) => value === true);
26
+ }
27
+ };
28
+ async function checkPermissions(config, accessToken, subject, organization, permissions) {
29
+ assertSecureIssuer(config.issuer);
30
+ const issuer = new URL(config.issuer);
31
+ if (issuer.username || issuer.password || issuer.search || issuer.hash || !config.clientId || !subject || organization === "" || !accessToken || accessToken.length > 32768 || /[\x00-\x20\x7f]/.test(accessToken) || !permissions.length || permissions.length > 50 || permissions.some((permission) => !permission.trim() || new TextEncoder().encode(permission).length > 255)) {
32
+ throw new ConfigurationError("Permission decision request is not configured or valid.");
33
+ }
34
+ const requested = [...new Set(permissions)];
35
+ try {
36
+ const response = await fetch(`${config.issuer.replace(/\/$/, "")}/oauth/decisions`, {
37
+ method: "POST",
38
+ redirect: "error",
39
+ cache: "no-store",
40
+ signal: AbortSignal.timeout(Math.max(1, config.timeoutMs ?? 1e4)),
41
+ headers: { authorization: `Bearer ${accessToken}`, accept: "application/json", "content-type": "application/json" },
42
+ body: JSON.stringify({ subject, org: organization, permission: requested })
43
+ });
44
+ if (response.status !== 200) {
45
+ await response.body?.cancel();
46
+ throw new AuthenticationError("Permission decision could not be verified.", void 0, void 0, response.status);
47
+ }
48
+ const reader = response.body?.getReader();
49
+ if (!reader) throw new AuthenticationError("Permission decision response is invalid.");
50
+ let size = 0;
51
+ let raw = "";
52
+ const decoder = new TextDecoder();
53
+ try {
54
+ for (; ; ) {
55
+ const { value, done } = await reader.read();
56
+ if (done) break;
57
+ size += value.byteLength;
58
+ if (size > 65536) throw new AuthenticationError("Permission decision response exceeded its limit.");
59
+ raw += decoder.decode(value, { stream: true });
60
+ }
61
+ raw += decoder.decode();
62
+ } finally {
63
+ await reader.cancel();
64
+ reader.releaseLock();
65
+ }
66
+ const data = JSON.parse(raw);
67
+ if (!record(data) || !record(data.subject) || data.mode !== "rbac" || data.subject.type !== "user" || data.subject.id !== subject || data.organization !== organization || data.client_id !== config.clientId || typeof data.organization_active !== "boolean" || typeof data.allowed !== "boolean" || !(data.org_role === null || typeof data.org_role === "string" && ["owner", "admin", "developer", "member", "viewer"].includes(data.org_role)) || !Array.isArray(data.results) || data.results.length !== requested.length) {
68
+ throw new AuthenticationError("Permission decision response binding is invalid.");
69
+ }
70
+ const checks = /* @__PURE__ */ Object.create(null);
71
+ for (const result of data.results) {
72
+ if (!record(result) || typeof result.permission !== "string" || typeof result.allowed !== "boolean" || !requested.includes(result.permission) || Object.hasOwn(checks, result.permission)) {
73
+ throw new AuthenticationError("Permission decision result is invalid.");
74
+ }
75
+ checks[result.permission] = result.allowed;
76
+ }
77
+ const decision = new PermissionDecision(
78
+ subject,
79
+ organization,
80
+ config.clientId,
81
+ data.org_role,
82
+ data.organization_active,
83
+ Object.freeze(checks)
84
+ );
85
+ if (data.allowed !== decision.allowed()) throw new AuthenticationError("Permission decision result is inconsistent.");
86
+ return decision;
87
+ } catch (error) {
88
+ if (error instanceof AuthenticationError) throw error;
89
+ throw new AuthenticationError("Permission decision could not be verified.");
90
+ }
91
+ }
92
+ function record(value) {
93
+ return value !== null && typeof value === "object" && !Array.isArray(value);
94
+ }
95
+
96
+ export { PermissionDecision, checkPermissions };
97
+ //# sourceMappingURL=chunk-EVZ6RB3K.js.map
98
+ //# sourceMappingURL=chunk-EVZ6RB3K.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/decisions.ts"],"names":[],"mappings":"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","file":"chunk-EVZ6RB3K.js","sourcesContent":["import { AuthenticationError, ConfigurationError } from './errors.js';\nimport { assertSecureIssuer } from './issuer.js';\nimport type { OrganizationRole } from './claims.js';\n\nexport interface PermissionDecisionConfig {\n issuer: string;\n clientId: string;\n timeoutMs?: number;\n}\n\n/** A current server decision; shared membership tiers are not app grants. */\nexport class PermissionDecision {\n constructor(\n readonly subject: string,\n readonly organization: string | null,\n readonly clientId: string,\n readonly organizationRole: OrganizationRole | null,\n readonly organizationActive: boolean,\n readonly permissions: Readonly<Record<string, boolean>>,\n ) {}\n\n allows(permission: string): boolean {\n return this.organizationActive && this.permissions[permission] === true;\n }\n\n allowed(): boolean {\n const values = Object.values(this.permissions);\n return this.organizationActive && values.length > 0 && values.every(value => value === true);\n }\n}\n\n/** No positive cache: check each request and again when queued work starts. */\nexport async function checkPermissions(\n config: PermissionDecisionConfig,\n accessToken: string,\n subject: string,\n organization: string | null,\n permissions: readonly string[],\n): Promise<PermissionDecision> {\n assertSecureIssuer(config.issuer);\n const issuer = new URL(config.issuer);\n if (issuer.username || issuer.password || issuer.search || issuer.hash || !config.clientId\n || !subject || organization === '' || !accessToken || accessToken.length > 32768\n || /[\\x00-\\x20\\x7f]/.test(accessToken) || !permissions.length || permissions.length > 50\n || permissions.some(permission => !permission.trim() || new TextEncoder().encode(permission).length > 255)) {\n throw new ConfigurationError('Permission decision request is not configured or valid.');\n }\n const requested = [...new Set(permissions)];\n try {\n const response = await fetch(`${config.issuer.replace(/\\/$/, '')}/oauth/decisions`, {\n method: 'POST', redirect: 'error', cache: 'no-store',\n signal: AbortSignal.timeout(Math.max(1, config.timeoutMs ?? 10_000)),\n headers: { authorization: `Bearer ${accessToken}`, accept: 'application/json', 'content-type': 'application/json' },\n body: JSON.stringify({ subject, org: organization, permission: requested }),\n });\n if (response.status !== 200) {\n await response.body?.cancel();\n throw new AuthenticationError('Permission decision could not be verified.', undefined, undefined, response.status);\n }\n const reader = response.body?.getReader();\n if (!reader) throw new AuthenticationError('Permission decision response is invalid.');\n let size = 0;\n let raw = '';\n const decoder = new TextDecoder();\n try {\n for (;;) {\n const { value, done } = await reader.read();\n if (done) break;\n size += value.byteLength;\n if (size > 65536) throw new AuthenticationError('Permission decision response exceeded its limit.');\n raw += decoder.decode(value, { stream: true });\n }\n raw += decoder.decode();\n } finally {\n await reader.cancel();\n reader.releaseLock();\n }\n const data: unknown = JSON.parse(raw);\n if (!record(data) || !record(data.subject) || data.mode !== 'rbac'\n || data.subject.type !== 'user' || data.subject.id !== subject\n || data.organization !== organization || data.client_id !== config.clientId\n || typeof data.organization_active !== 'boolean' || typeof data.allowed !== 'boolean'\n || !(data.org_role === null || (typeof data.org_role === 'string'\n && ['owner', 'admin', 'developer', 'member', 'viewer'].includes(data.org_role)))\n || !Array.isArray(data.results) || data.results.length !== requested.length) {\n throw new AuthenticationError('Permission decision response binding is invalid.');\n }\n const checks: Record<string, boolean> = Object.create(null) as Record<string, boolean>;\n for (const result of data.results as unknown[]) {\n if (!record(result) || typeof result.permission !== 'string' || typeof result.allowed !== 'boolean'\n || !requested.includes(result.permission) || Object.hasOwn(checks, result.permission)) {\n throw new AuthenticationError('Permission decision result is invalid.');\n }\n checks[result.permission] = result.allowed;\n }\n const decision = new PermissionDecision(subject, organization, config.clientId,\n data.org_role as OrganizationRole | null, data.organization_active, Object.freeze(checks));\n if (data.allowed !== decision.allowed()) throw new AuthenticationError('Permission decision result is inconsistent.');\n return decision;\n } catch (error) {\n if (error instanceof AuthenticationError) throw error;\n throw new AuthenticationError('Permission decision could not be verified.');\n }\n}\n\nfunction record(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n"]}
@@ -1,26 +1,8 @@
1
+ import { createVerifier, randomToken, challenge } from './chunk-VGQASHTI.js';
1
2
  import { assertSecureIssuer } from './chunk-QQW63PGU.js';
2
3
  import { CboxIdError, AuthenticationError, ConfigurationError, InvalidStateError, oauthError } from './chunk-SEUD4TE4.js';
3
4
  import { createRemoteJWKSet, jwtVerify } from 'jose';
4
5
 
5
- // src/pkce.ts
6
- function base64url(bytes) {
7
- let binary = "";
8
- for (const byte of bytes) {
9
- binary += String.fromCharCode(byte);
10
- }
11
- return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
12
- }
13
- function randomToken(bytes = 32) {
14
- return base64url(crypto.getRandomValues(new Uint8Array(bytes)));
15
- }
16
- function createVerifier() {
17
- return randomToken(32);
18
- }
19
- async function challenge(verifier) {
20
- const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier));
21
- return base64url(new Uint8Array(digest));
22
- }
23
-
24
6
  // src/claims.ts
25
7
  var ORGANIZATION_ROLES = /* @__PURE__ */ new Set([
26
8
  "owner",
@@ -1141,6 +1123,6 @@ function sleep(ms, signal) {
1141
1123
  });
1142
1124
  }
1143
1125
 
1144
- export { CboxIdClient, Discovery, FEATURE_FLAGS_SCOPE, PipeLeaseDeniedError, PipeLeaseError, PipeNotConnectedError, PipeReauthorizationRequiredError, PipeTemporarilyUnavailableError, VaultClient, actor, challenge, createVerifier, featureFlags, hasFeature, hasPermission, hasRole, isSupportSession, organization, permissions, pipeConnectUrl, randomToken, roles, sessionId, verifyStandardWebhook, verifyWebhook, withConnectReturn };
1145
- //# sourceMappingURL=chunk-YGLMLIKL.js.map
1146
- //# sourceMappingURL=chunk-YGLMLIKL.js.map
1126
+ export { CboxIdClient, Discovery, FEATURE_FLAGS_SCOPE, PipeLeaseDeniedError, PipeLeaseError, PipeNotConnectedError, PipeReauthorizationRequiredError, PipeTemporarilyUnavailableError, VaultClient, actor, featureFlags, hasFeature, hasPermission, hasRole, isSupportSession, organization, permissions, pipeConnectUrl, roles, sessionId, verifyStandardWebhook, verifyWebhook, withConnectReturn };
1127
+ //# sourceMappingURL=chunk-T5LCQOLS.js.map
1128
+ //# sourceMappingURL=chunk-T5LCQOLS.js.map