import { ClientDiscovery, ClientMetadataResourceFetch, OAuthClientMetadata, SchemaClient, Scope } from "@better-auth/oauth-provider"; import * as _$better_auth0 from "better-auth"; import { GenericEndpointContext } from "@better-auth/core"; //#region src/types.d.ts type CimdMetadataProfile = "mcp-2026-07-28"; interface CimdClientCreatedEvent { /** Newly persisted discovery-owned OAuth client. */ client: SchemaClient; /** Validated Client ID Metadata Document that produced the client. */ clientMetadataDocument: OAuthClientMetadata; /** Better Auth endpoint context for the discovery request. */ context: GenericEndpointContext; } interface CimdClientRefreshedEvent { /** Discovery-owned OAuth client after metadata reconciliation. */ client: SchemaClient; /** Client state captured before metadata reconciliation. */ previousClient: SchemaClient; /** Validated Client ID Metadata Document used for reconciliation. */ clientMetadataDocument: OAuthClientMetadata; /** Better Auth endpoint context for the discovery request. */ context: GenericEndpointContext; } interface CimdMetadataFetchPolicy { /** * Minimum time before retrying a failed metadata fetch for one exact client * ID. Successful fetches are governed by HTTP freshness and the origin/global * fetch budgets. Numeric values are seconds. Set to `0` to disable failed-fetch * pacing. * * @default 1 */ minimumFetchInterval?: number | string; /** * Maximum metadata fetches in flight across the plugin instance. * * @default 16 */ maximumConcurrentFetches?: number; /** * Maximum metadata fetches in flight for one URL origin. * * @default 4 */ maximumConcurrentFetchesPerOrigin?: number; /** * Maximum fetch starts in a rolling 60-second window across the * plugin instance. * * @default 120 */ maximumFetchesPerMinute?: number; /** * Maximum fetch starts in a rolling 60-second window for one URL * origin. * * @default 30 */ maximumFetchesPerOriginPerMinute?: number; } /** * Options for the Client ID Metadata Document plugin. * * @see https://datatracker.ietf.org/doc/html/draft-ietf-oauth-client-id-metadata-document-02 */ interface CimdOptions { /** * Fetch transport for metadata documents and discovery-owned metadata * resources such as `jwks_uri`. * * The transport MUST resolve the hostname exactly once, reject RFC 6890 * special-use addresses, pin the approved address for the connection, and * refuse redirects. Those guarantees cannot be implemented by wrapping the * standard Fetch API after DNS resolution, so the application must provide * them at its runtime-specific network boundary. */ fetchClientMetadataResource: ClientMetadataResourceFetch; /** * Apply an additional protocol profile to otherwise generic draft-02 * metadata validation. * * The MCP 2026-07-28 profile requires `client_name` and `redirect_uris` * because that MCP revision normatively pins CIMD draft-00. */ metadataProfile?: CimdMetadataProfile; /** * Maximum and fallback cache freshness lifetime for a client's metadata * document. An expired entry is revalidated on the next client resolution; * the plugin does not perform periodic or background fetches. * * Accepts a number of seconds or a duration string (e.g. `"60m"`, * `"1d"`). * * @default "60m" */ metadataRevalidationInterval?: number | string; /** * Bounded request-amplification policy for metadata document fetches. * * A permitted fetch consumes its concurrency and rolling-window budget when * it starts. Same-client concurrent resolutions coalesce, while fresh-cache * hits consume no budget. Limits reject immediately rather than queueing. */ metadataFetchPolicy?: CimdMetadataFetchPolicy; /** * Maximum number of validated metadata documents retained by this plugin * instance. The least-recently-used entry is evicted when the bound is * reached. * * @default 1000 */ maxCacheEntries?: number; /** * Metadata fields whose URL values must share the same origin as the * `client_id` URL. Prevents a client from claiming URIs on a different * domain. * * Pass an empty array to disable origin binding (not recommended for * production). * * Redirect URIs are deliberately excluded by default: exact redirect URI * matching remains mandatory at authorization time, while native and * distributed clients commonly use a redirect origin different from their * metadata-document origin. * * @default ["post_logout_redirect_uris", "client_uri"] */ originBoundFields?: readonly string[]; /** * Pre-fetch gate called before a metadata document is requested. Return * `false` to reject the `client_id` URL. * * Use this for origin allowlists, per-host rate limiting, or integrating * with an external trust service. It is application policy, not a * substitute for the required transport's resolve-once and connection- * pinning guarantees; resolving here would introduce a TOCTOU boundary. * * @default always allow */ isMetadataDocumentUrlAllowed?: (clientIdUrl: string, context: GenericEndpointContext) => boolean | Promise; /** * Called after a client is created from a metadata document for the * first time. Use this to assign local trust, emit an audit event, or * perform other post-creation processing. Better Auth does not fetch or * render metadata-owned remote assets such as `logo_uri`. * * This is a best-effort notification. A rejected callback is logged and * does not roll back an otherwise valid registration. */ onClientCreated?: (event: CimdClientCreatedEvent) => void | Promise; /** * Called after a client is refreshed from a re-fetched metadata * document. Use this for change-detection logging or updating derived * fields. * * This is a best-effort notification. A rejected callback is logged and * does not roll back an otherwise valid refresh. */ onClientRefreshed?: (event: CimdClientRefreshedEvent) => void | Promise; } //#endregion //#region src/validate-metadata-document.d.ts type CimdMetadataValidationResult = { valid: true; metadata: OAuthClientMetadata; error?: never; warnings?: string[]; } | { valid: false; error: string; metadata?: never; warnings?: string[]; }; interface CimdMetadataValidationOptions { originBoundFields?: readonly string[]; metadataProfile?: CimdMetadataProfile; } /** * Detect a URL-formatted client_id (Client ID Metadata Document pattern). * * HTTPS URLs match. This is a routing predicate, not a security gate: it * performs no DNS resolution, so callers MUST also run * {@link validateClientIdUrl} (and a fetch-time policy) before fetching. */ declare function isCimdClientIdUrlCandidate(clientId: string): boolean; /** * Validate a client_id URL per Client ID Metadata Document draft-02 §3. * Returns null on success, an error string on failure. * * Loopback and every other non-public host (private, link-local, * cloud-metadata, IPv6 tunnels) are rejected. */ declare function validateClientIdUrl(url: string): string | null; /** * Validate a fetched Client ID Metadata Document per §4.1. * * @param clientIdUrl - The URL the document was fetched from. * @param raw - The parsed JSON body of the response. * @param options - Generic draft-02 validation options and an optional protocol profile. */ declare function validateCimdMetadata(clientIdUrl: string, raw: unknown, options?: CimdMetadataValidationOptions): CimdMetadataValidationResult; //#endregion //#region src/index.d.ts declare module "@better-auth/core" { interface BetterAuthPluginRegistry { cimd: { creator: typeof cimd; }; } } /** * Build a {@link ClientDiscovery} for Client ID Metadata Documents. * * Users who prefer explicit composition can contribute the result through * `oauthProvider({ extensions: [{ clientDiscovery }] })`; most users should * install the {@link cimd} plugin instead, which contributes this discovery * alongside whatever else is configured. */ declare function createCimdClientDiscovery(options: CimdOptions): ClientDiscovery; /** * Client ID Metadata Document plugin. * * Adds unauthenticated dynamic client discovery over HTTPS to an * `oauth-provider` instance. Clients identify themselves by providing * an HTTPS URL as their `client_id`; the plugin fetches and validates * the document at that URL, then creates a client record whose authentication * behavior is determined by `token_endpoint_auth_method`. * * See {@link https://datatracker.ietf.org/doc/html/draft-ietf-oauth-client-id-metadata-document-02 | Client ID Metadata Document draft-02} * and {@link https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization/client-registration#client-id-metadata-documents | the MCP authorization spec}. */ declare const cimd: (options: CimdOptions) => { id: "cimd"; version: string; init(ctx: _$better_auth0.AuthContext): void; }; //#endregion export { type CimdClientCreatedEvent, type CimdClientRefreshedEvent, type CimdMetadataFetchPolicy, type CimdMetadataProfile, type CimdMetadataValidationOptions, type CimdMetadataValidationResult, type CimdOptions, cimd, createCimdClientDiscovery, isCimdClientIdUrlCandidate, validateCimdMetadata, validateClientIdUrl };