/** * RFC 7523 §3 Client-Assertion Verification (private_key_jwt) * * Verifies the `client_assertion` JWT a headless agent presents to the token * endpoint for the client_credentials grant (#159/#160). EdDSA/Ed25519 only * (RFC 8037), verified with `node:crypto` — no new dependency; the plugin's * `jsonwebtoken` cannot verify EdDSA. Everything fails closed: any parse, * header, key, signature, or claim problem yields `{ valid: false, reason }`, * never a throw, so the grant handler can map it straight to an OAuth * `invalid_client` error and an audit reason. * * Verification contract (see the #159 design review): * - header `alg` is exactly `EdDSA`; `typ`, when present, is `JWT`; any `crit` * is rejected (we implement no extensions). * - key selected from the client's registered JWK Set: `kid` present → must * match exactly one registered key; `kid` absent → the set must hold exactly * one key. Keys must be public OKP/Ed25519 (a private `d` is rejected). * - `iss` = `sub` = the authenticating client_id (all three, exactly). * - `aud` equals the resolved token-endpoint URL — a string, or a * single-element array (RFC 7519 allows an array; more than one audience is * rejected as ambiguous). * - `exp` required, in the future, and no more than `maxExpiresInSeconds` * (default 60) out; `iat` required and not in the future; `nbf`, when * present, must have passed. All checks allow `clockToleranceSeconds` * (default 5) of skew. * - `jti` required (non-empty string, ≤ 256 chars). Replay is NOT enforced * here — callers must run the returned `jti` through MCPAssertionJtiStore. */ /** RFC 7523 §2.2 value for `client_assertion_type`. */ export declare const CLIENT_ASSERTION_TYPE_JWT_BEARER = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"; /** Claims of a successfully verified assertion. */ export interface ClientAssertionClaims { iss: string; sub: string; /** The single verified audience (unwrapped if presented as an array). */ aud: string; exp: number; iat: number; jti: string; } export type ClientAssertionResult = { valid: true; claims: ClientAssertionClaims; } | { valid: false; reason: string; }; export interface VerifyClientAssertionParams { /** The `client_assertion` value — a compact-serialized JWT. */ assertion: string; /** The client_id being authenticated; must equal `iss` and `sub`. */ clientId: string; /** Resolved token-endpoint URL; must equal `aud` exactly. */ tokenEndpoint: string; /** The client's registered public JWK Set keys (OKP/Ed25519). */ jwks: Record[]; /** Maximum allowed `exp - now`. Default 60 (issue req 1). */ maxExpiresInSeconds?: number; /** Clock-skew allowance for `exp`/`iat`/`nbf`. Default 5. */ clockToleranceSeconds?: number; } /** * Verify a client assertion end-to-end (structure → header → key → signature * → claims). Signature is checked before claims so a claims-shaped error can * never be probed without possession of the private key. */ export declare function verifyClientAssertion(params: VerifyClientAssertionParams): ClientAssertionResult;