Web Authorization Protocol (oauth) P. C. Williams Internet-Draft Barefoot Coders Intended status: Standards Track 30 October 2026 Expires: 3 May 2027 Cryptographic Proof-of-Intent (PoI) Core Protocol for Human-in-the-Loop (HITL) Step-Up Authorization draft-williams-oauth-poi-core-00 Abstract Autonomous software agents and orchestrated workflows increasingly invoke high-consequence operations on Resource Servers (such as financial originations or clinical prescriptions) on behalf of human users. Existing bearer tokens and transport-level Proof-of- Possession mechanisms cannot cryptographically distinguish between parameters autonomously synthesized by an intermediary agent and parameters explicitly reviewed, approved, or modified by an authorized human. Furthermore, redirect-based authorization flows impose prohibitive user experience friction for high-frequency Human- in-the-Loop (HITL) interactions. This document specifies the Proof-of-Intent (PoI) Core Protocol, a stateless, single-hop cryptographic framework building on JSON Web Signature (JWS, RFC 7515), Proof-of-Possession Key Semantics for JWTs (RFC 7800), JSON Web Token Best Current Practices (RFC 8725), JSON Canonicalization Scheme (JCS, RFC 8785), OAuth 2.0 Rich Authorization Requests (RAR, RFC 9396), OAuth 2.0 Step-Up Authentication Challenge Protocol (RFC 9470), and W3C WebAuthn. PoI Core defines: (1) short- lived, client-generated Ephemeral Intent Keys certified at login and rotated via Proof-of-Possession key chaining; (2) Resource Server- signed Intent Challenge Objects binding canonical action parameters to human-readable display facts; (3) multi-tier assurance attestations spanning zero-friction session keys to hardware security tokens; and (4) stateless verification and countersigned audit receipts for single-hop APPROVE, REJECT, and within-authority SUPERCEDE decisions. Multi-hop chained escalations, asynchronous intent escrowing, and concurrent multi-approver conflict resolution are specified in the companion extension document, draft-williams-oauth-poi-chained-state- 00. Status of This Memo This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79. Williams Expires 3 May 2027 [Page 1] Internet-Draft Proof-of-Intent (PoI) Core October 2026 Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet- Drafts is at https://datatracker.ietf.org/drafts/current/. Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress." This Internet-Draft will expire on 3 May 2027. Copyright Notice Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved. This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/ license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License. Table of Contents 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 1.1. Problem Statement . . . . . . . . . . . . . . . . . . . . 4 1.2. Design Goals and Scope of PoI Core . . . . . . . . . . . 4 2. Conventions and Terminology . . . . . . . . . . . . . . . . . 5 2.1. Requirements Language . . . . . . . . . . . . . . . . . . 5 2.2. Terminology . . . . . . . . . . . . . . . . . . . . . . . 5 2.3. Parameterized Media Type Conventions (application/ poi+jwt;kind=...) . . . . . . . . . . . . . . . . . . . . 6 3. Protocol Architecture and Overview . . . . . . . . . . . . . 7 3.1. Architectural Topology . . . . . . . . . . . . . . . . . 7 3.2. Orthogonality to Policy Enforcement . . . . . . . . . . . 8 4. Ephemeral Intent Key (EIK) Lifecycle . . . . . . . . . . . . 8 4.1. Client-Side Non-Extractable Key Generation and Separation from Transport DPoP . . . . . . . . . . . . . . . . . . . 8 4.2. Key Certification Token (KCT) via RFC 7800 . . . . . . . 9 4.3. Proof-of-Possession (PoP) Key Chaining Rotation and RFC 8693 Binding . . . . . . . . . . . . . . . . . . . . . . 11 5. Resource Server Intent Challenge . . . . . . . . . . . . . . 12 5.1. HTTP 403 Step-Up Challenge Signaling (PoI-Challenge) . . 12 5.2. Intent Challenge Object (ICO) Format . . . . . . . . . . 12 Williams Expires 3 May 2027 [Page 2] Internet-Draft Proof-of-Intent (PoI) Core October 2026 5.3. Canonical Parameter Hashing and Numeric Precision via RFC 8785 (JCS) . . . . . . . . . . . . . . . . . . . . . . . 13 6. Proof-of-Intent Envelope (PoIE) Core Profile . . . . . . . . 14 6.1. Two-Node Core Envelope ([R0, R1]) and Header Size Considerations . . . . . . . . . . . . . . . . . . . . . 14 6.2. Decision Semantics: APPROVE, REJECT, and SUPERCEDE . . . 14 6.3. Assurance Tiers and Attestation Bindings . . . . . . . . 15 6.3.1. Tier 1: Ephemeral Session PoP (urn:ietf:params:oauth:poi:tier:session-pop) . . . . 15 6.3.2. Tier 2: Platform Biometric / User Verification (urn:ietf:params:oauth:poi:tier:webauthn-uv) . . . . 15 6.3.3. Tier 3: Cross-Platform Hardware Token (urn:ietf:params:oauth:poi:tier:webauthn-hw) . . . . 16 7. Stateless Verification and Countersigned Intent Receipts (CIR) . . . . . . . . . . . . . . . . . . . . . . . . . . 16 7.1. Normative Core Verification Algorithm . . . . . . . . . . 16 7.2. Countersigned Intent Receipt (CIR) . . . . . . . . . . . 17 8. Error Handling and Failure Modes . . . . . . . . . . . . . . 18 8.1. Error Response Signaling (PoI-Challenge and RFC 9457) . . 18 8.2. Cryptographic Signature, Audience, and Key Binding Errors . . . . . . . . . . . . . . . . . . . . . . . . . 19 8.3. Temporal and Validity Window Errors (nbf, exp, auth_time, Replay) . . . . . . . . . . . . . . . . . . . . . . . . . 20 8.4. Envelope Integrity and Step-Up Errors . . . . . . . . . . 21 8.5. Summary Matrix of PoI Core Error Codes . . . . . . . . . 22 9. Security Considerations . . . . . . . . . . . . . . . . . . . 23 9.1. Confused Deputy and Post-Approval Agent Bypass . . . . . 23 9.2. Key Smuggling, Cross-Origin Vault Isolation, and WebAuthn Permissions Policy . . . . . . . . . . . . . . . . . . . 24 9.3. Backdated Forgery After Key Expiry . . . . . . . . . . . 24 10. Privacy Considerations . . . . . . . . . . . . . . . . . . . 24 11. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 25 11.1. Media Type Registrations (application/poi+jwt and application/poi-envelope+json) . . . . . . . . . . . . . 25 11.1.1. application/poi+jwt . . . . . . . . . . . . . . . . 25 11.1.2. application/poi-envelope+json . . . . . . . . . . . 25 11.2. HTTP Header Field Registrations (PoI-Challenge and PoI-Envelope) . . . . . . . . . . . . . . . . . . . . . 26 11.3. OAuth URI Registrations (Token Type, Assurance Tiers, Error Codes) . . . . . . . . . . . . . . . . . . . . . . 26 11.4. JWT Claim Registrations . . . . . . . . . . . . . . . . 27 12. References . . . . . . . . . . . . . . . . . . . . . . . . . 27 12.1. Normative References . . . . . . . . . . . . . . . . . . 27 12.2. Informative References . . . . . . . . . . . . . . . . . 29 Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 30 1. Introduction Williams Expires 3 May 2027 [Page 3] Internet-Draft Proof-of-Intent (PoI) Core October 2026 1.1. Problem Statement In architectures employing autonomous AI agents or automated workflow orchestrators, an intermediary software agent acts on behalf of an authenticated human user to invoke tools and APIs hosted by downstream Resource Servers (RS). While OAuth 2.0 ([RFC6749]) and Demonstrating Proof-of-Possession (DPoP, [RFC9449]) authenticate the client or session, they do not provide cryptographic proof of *human intent* over the specific application-layer parameters of an individual transaction. This creates three immediate vulnerabilities for synchronous Human- in-the-Loop (HITL) interactions: 1. *The Confused Deputy Problem:* A prompt-injected or malfunctioning agent possessing a valid session token can invoke a privileged Resource Server endpoint with unauthorized parameters. 2. *Semantic UI Misrepresentation (MITM / Spoofing):* If an agent constructs the HITL approval prompt while transmitting raw database identifiers (e.g., UUIDs or drug codes) to the Resource Server, the human may be tricked into signing parameters that do not match the human-readable description displayed on screen. 3. *The OAuth Redirect Tax:* Existing transaction authorization specifications such as Rich Authorization Requests (RAR, [RFC9396]) paired with Step-Up Authentication ([RFC9470]) require an Authorization Server round-trip or out-of-band push notification per transaction, causing severe cognitive and UX friction during high-frequency HITL operations. 1.2. Design Goals and Scope of PoI Core This document specifies *PoI Core*, the stateless foundation of the Proof-of-Intent protocol family. PoI Core is designed for Resource Servers that want to verify human intent over a proposed transaction ([R0, R1]) without maintaining multi-step workflow state tables: * *Zero Additional Cognitive Overhead at Baseline:* During session login, the client generates a non-extractable asymmetric keypair certified by the Authorization Server with nbf and exp bounds via [RFC7800]. Baseline (Tier 1) HITL approvals require only a single user interaction in the client interface with zero Authorization Server round-trips. Williams Expires 3 May 2027 [Page 4] Internet-Draft Proof-of-Intent (PoI) Core October 2026 * *Extensible Multi-Tier Assurance:* Resource Servers dynamically specify the required assurance tier based on action consequence -- stepping up from Tier 1 (Session PoP Key) to Tier 2 (Platform Biometric via [WebAuthn]) or Tier 3 (Cross-Platform Hardware Token via [WebAuthn]). * *Single-Hop Authoritative Edits (SUPERCEDE):* If a human operator adjusts parameters proposed by an agent within their own scope of authority, the client submits a two-node envelope (R0 -> R1) that immediately supercedes R0 and asserts the new parameters in R1. * *Companion Chained State Specification:* Multi-party organizational escalations (R0 -> R1 -> R2), asynchronous intent escrowing, and concurrent multi-approver race resolution are defined in [POI-CHAINED]. 2. Conventions and Terminology 2.1. Requirements Language The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here. 2.2. Terminology * *Ephemeral Intent Key (EIK):* A short-lived asymmetric keypair generated inside the client's Signing Vault with non-extractable private key material, used exclusively to sign Tier 1 HITL assertions. * *Key Certification Token (KCT):* A JSON Web Token ([RFC7519]) signed by the Authorization Server containing an [RFC7800] cnf claim that binds the user's identity (sub), authentication timestamp (auth_time), and validity window (nbf, exp) to the public portion of an EIK. * *Signing Vault:* A logically isolated client execution context (e.g., a cross-origin isolated iframe or native secure enclave) responsible for holding the EIK private handle, verifying Resource Server challenge signatures, rendering ground-truth display facts, and producing signed assertions. Williams Expires 3 May 2027 [Page 5] Internet-Draft Proof-of-Intent (PoI) Core October 2026 * *Intent Challenge Object (ICO):* A signed JWS ([RFC7515]) issued by a Resource Server when an action requires HITL authorization. The ICO binds the canonical hash of the proposed parameters, the resolved human-readable display_facts, and the required assurance tier. * *Proof-of-Intent Envelope (PoIE):* A JSON structure carrying an ordered, hash-linked array of nodes. In PoI Core, the envelope contains two nodes: the Resource Server's proposal (R0) and the human's terminal decision (R1: APPROVE, REJECT, or within- authority SUPERCEDE). * *Countersigned Intent Receipt (CIR):* A signed timestamped receipt produced by the Resource Server (or transparency service) upon verifying a PoIE within its active key window, enabling offline audit verification after the EIK has expired. 2.3. Parameterized Media Type Conventions (application/ poi+jwt;kind=...) To enforce explicit JWT typing per [RFC8725] Section 3.11 without proliferating separate media type registrations, this specification defines a single parameterized JWT media type, application/poi+jwt (per [RFC6838] Section 4.3), with a required parameter kind: Williams Expires 3 May 2027 [Page 6] Internet-Draft Proof-of-Intent (PoI) Core October 2026 +=========+===================+=====================+=============+ |kind |HTTP Content-Type |JWS typ Header |Artifact | |Parameter|Header |Parameter |Description | +=========+===================+=====================+=============+ |kct |application/ |"poi+jwt;kind=kct" |Key | | |poi+jwt;kind=kct | |Certification| | | | |Token | | | | |(Section 4.2)| +---------+-------------------+---------------------+-------------+ |roll |application/ |"poi+jwt;kind=roll" |PoP Key | | |poi+jwt;kind=roll | |Rollover | | | | |Request | | | | |(Section 4.3)| +---------+-------------------+---------------------+-------------+ |chal |application/ |"poi+jwt;kind=chal" |Intent | | |poi+jwt;kind=chal | |Challenge | | | | |Object | | | | |(Section 5.2)| +---------+-------------------+---------------------+-------------+ |assert |application/ |"poi+jwt;kind=assert"|Tier 1 Human | | |poi+jwt;kind=assert| |Assertion JWS| | | | |(Section | | | | |6.3.1) | +---------+-------------------+---------------------+-------------+ |rcpt |application/ |"poi+jwt;kind=rcpt" |Countersigned| | |poi+jwt;kind=rcpt | |Intent | | | | |Receipt | | | | |(Section 7.2)| +---------+-------------------+---------------------+-------------+ Table 1 In accordance with [RFC7515] Section 4.1.9, senders SHOULD omit the "application/" prefix in the JWS typ header parameter (e.g., "typ": "poi+jwt;kind=chal"), and verifiers MUST treat "poi+jwt;kind=" and "application/poi+jwt;kind=" (case-insensitively with optional whitespace after ;) as equivalent. Verifiers MUST reject any token whose kind parameter does not match the expected artifact type for that protocol step. 3. Protocol Architecture and Overview 3.1. Architectural Topology Williams Expires 3 May 2027 [Page 7] Internet-Draft Proof-of-Intent (PoI) Core October 2026 +-----------------+ (1) Auth + Pub(EIK) +-----------------+ | | ---------------------------> | | | Client Signing | <--------------------------- | Authorization | | Vault(Frontend) | (2) Signed KCT | Server(IdP) | | | [nbf, exp, cnf: Pub(EIK)] | | +-----------------+ +-----------------+ ^ | | (5)Verify | (6) Signed PoIE | ICO & | ([R0, R1]) | Render v +-----------------+ (3) Propose Action +-----------------+ | | ---------------------------> | | | AI Orchestrator/| <--------------------------- | Resource Server | | Intermediary | (4) HTTP 403 + ICO (R0) | (Loan / Rx Svc) | | | ---------------------------> | | +-----------------+ (7) Submit PoIE [R0, R1]+-----------------+ (or direct Vault->RS) | v +-----------------+ |Orthogonal Policy| |Engine/Audit Log | +-----------------+ 3.2. Orthogonality to Policy Enforcement The PoI protocol intentionally separates *cryptographic proof of human intent* from *organizational policy enforcement*: 1. *PoI Verification Layer:* Determines exclusively whether the assertion R1 over proposal R0 was produced by the claimed subject, within a valid key window ([nbf, exp]), for the target audience (aud), at the required assurance tier, over the exact canonical parameter hash. 2. *Orthogonal Policy Layer:* Consumes the verified PoIE output to evaluate organization-specific authorization rules (e.g., dollar thresholds, clinical prescribing authority, role permissions). 4. Ephemeral Intent Key (EIK) Lifecycle 4.1. Client-Side Non-Extractable Key Generation and Separation from Transport DPoP The Signing Vault MUST generate the EIK asymmetric keypair locally. To guarantee baseline interoperability across implementations: * Implementations of this specification MUST support ES256 (ECDSA using P-256 and SHA-256) and SHOULD support EdDSA (Ed25519) ([RFC7518]). Williams Expires 3 May 2027 [Page 8] Internet-Draft Proof-of-Intent (PoI) Core October 2026 Normative key isolation rules: 1. The private key MUST NOT be generated by or transmitted to the Authorization Server or any backend service. 2. In browser environments utilizing the Web Cryptography API, the keypair MUST be generated with extractable: false and key usages restricted to ["sign"]. 3. The private key handle SHOULD be retained strictly in volatile memory (RAM) inside a cross-origin isolated Signing Vault context and MUST NOT be serialized to persistent storage. 4. *Separation from Transport DPoP Keys ([RFC9449]):* Clients that use DPoP ([RFC9449]) for transport- level access token binding MUST NOT reuse their transport DPoP keypair as the Ephemeral Intent Key (EIK). Transport DPoP keys sign automated background HTTP requests (such as polling or telemetry) without human presence, whereas the EIK MUST only be invoked inside the Signing Vault upon an explicit human user gesture. 4.2. Key Certification Token (KCT) via RFC 7800 During user authentication, the client submits the EIK public key as a JSON Web Key (JWK, [RFC7517]) to the Authorization Server. Upon successful authentication, the Authorization Server issues a Key Certification Token (KCT). A KCT is a signed JWT ([RFC7519]) with the following normative requirements: * *JWS Protected Header:* - alg: Asymmetric signature algorithm (ES256 MTI). none and symmetric MAC algorithms (HS256) MUST NOT be used. - typ: MUST be "poi+jwt;kind=kct" (or "application/ poi+jwt;kind=kct"). - kid: Key identifier of the Authorization Server's signing key. * *JWT Payload Claims:* - iss (REQUIRED): Issuer URI of the Authorization Server. - sub (REQUIRED): Subject identifier of the authenticated human user. - aud (OPTIONAL): Audience URI(s) identifying the Resource Server trust domain(s) authorized to rely on this KCT. - session_id (REQUIRED): Unique identifier for the logical authentication session. Williams Expires 3 May 2027 [Page 9] Internet-Draft Proof-of-Intent (PoI) Core October 2026 - auth_time (REQUIRED): NumericDate (as defined in [RFC7519]) when the user last performed interactive primary/multi-factor authentication. - iat (REQUIRED): NumericDate when this KCT was issued. - nbf (REQUIRED): NumericDate before which this EIK MUST NOT be accepted for signing. - exp (REQUIRED): NumericDate after which this EIK MUST NOT be accepted for signing. The lifetime (exp - nbf) SHOULD NOT exceed 1800 seconds (30 minutes). - cnf (REQUIRED): Confirmation claim per [RFC7800], containing a jwk member representing the client's EIK public key (which MUST NOT contain private key parameters). - prev_jkt (OPTIONAL): Base64url-encoded JWK Thumbprint ([RFC7638]) of the immediately preceding EIK in the same session, present when the KCT was issued via PoP Key Rotation (Section 4.3). _Non-normative example of a KCT payload:_ { "iss": "https://idp.example.org", "sub": "user:dr-jane-doe-992", "aud": "https://api.example.org", "session_id": "sess_88192a", "auth_time": 1793388000, "iat": 1793389800, "nbf": 1793389800, "exp": 1793391000, "prev_jkt": "NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs", "cnf": { "jwk": { "kty": "EC", "crv": "P-256", "x": "f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU", "y": "x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0" } } } Williams Expires 3 May 2027 [Page 10] Internet-Draft Proof-of-Intent (PoI) Core October 2026 4.3. Proof-of-Possession (PoP) Key Chaining Rotation and RFC 8693 Binding To support sessions longer than a single KCT validity window without relying on smuggle-prone bearer refresh tokens, the Signing Vault rotates keys using *PoP Key Chaining*: 1. Prior to the exp time of the active key K_n, the Signing Vault generates a fresh non-extractable keypair K_(n+1). 2. The Signing Vault constructs a Key Rollover Request JWS (typ: "poi+jwt;kind=roll") signed using the private key of K_n: * The JWS Protected Header MUST include kcert containing the compact serialization of the currently active KCT for K_n. * The JWS Payload MUST include iss (matching kcert.sub), aud (matching the Authorization Server's issuer or token endpoint URI), iat, a unique nonce, and new_cnf.jwk containing the public JWK of K_(n+1). 3. *OAuth 2.0 Token Exchange ([RFC8693]) Transport Binding:* The client MAY submit the poi+jwt;kind=roll JWS to the Authorization Server's standard Token Endpoint using the [RFC8693] grant type: * grant_type: urn:ietf:params:oauth:grant-type:token-exchange * subject_token: * subject_token_type: urn:ietf:params:oauth:token-type:poi-roll * requested_token_type: urn:ietf:params:oauth:token-type:poi-kct 4. The Authorization Server MUST verify that: * The attached kcert signature is valid and its [nbf, exp] window encompasses the current server time. * The poi+jwt;kind=roll signature verifies against kcert.cnf.jwk, and aud matches the Authorization Server. * The session identified by kcert.session_id has not been revoked and has not exceeded the maximum session lifetime since kcert.auth_time. 5. Upon verification, the Authorization Server issues a new KCT for K_(n+1) preserving the original auth_time and setting prev_jkt to the [RFC7638] thumbprint of K_n. Williams Expires 3 May 2027 [Page 11] Internet-Draft Proof-of-Intent (PoI) Core October 2026 6. Upon receiving the new KCT, the Signing Vault MUST immediately destroy the in-memory handle for K_n. 5. Resource Server Intent Challenge 5.1. HTTP 403 Step-Up Challenge Signaling (PoI-Challenge) Because HTTP requests to a Resource Server typically already carry an Authorization: Bearer or Authorization: DPoP header for transport authentication ([RFC9110] Section 11.6.1), PoI avoids overloading the HTTP Authentication Scheme namespace. When a client or intermediary agent invokes a Resource Server endpoint that requires HITL Proof-of-Intent, the Resource Server MUST respond with an HTTP 403 Forbidden status code, a *PoI-Challenge* response header containing challenge metadata parameters, and a response body of media type application/poi+jwt;kind=chal: HTTP/1.1 403 Forbidden PoI-Challenge: error="intent_proof_required", intent_id="intent_rx_7721", required_tier="urn:ietf:params:oauth:poi:tier:session-pop" Content-Type: application/poi+jwt;kind=chal 5.2. Intent Challenge Object (ICO) Format The response body is an Intent Challenge Object (ICO) -- a JWS (typ: "poi+jwt;kind=chal") signed by the Resource Server: * *JWS Protected Header:* - alg: Asymmetric signature algorithm of the Resource Server (ES256 MTI). - typ: MUST be "poi+jwt;kind=chal" (or "application/ poi+jwt;kind=chal"). - kid: Key identifier of the Resource Server. * *ICO Payload Claims:* - iss (REQUIRED): Resource Server identifier URI. - challenge_id (REQUIRED): Cryptographically random unique identifier (nonce) for this challenge instance. Williams Expires 3 May 2027 [Page 12] Internet-Draft Proof-of-Intent (PoI) Core October 2026 - intent_id (REQUIRED): Identifier of the logical transaction. - iat, nbf, exp (REQUIRED): Validity window of the challenge. exp - nbf SHOULD NOT exceed 300 seconds (5 minutes). - required_tier (REQUIRED): URN specifying the minimum cryptographic assurance tier required by the Resource Server (Section 6.3). - authorization_details (REQUIRED): An object conforming to [RFC9396] Rich Authorization Requests, extended with the following mandatory PoI members: o type: Action type URI or string. o actor: Identifier of the proposing agent or client. o raw_params: JSON object containing the machine-executable parameters proposed for the transaction. o raw_params_hash: SHA-256 digest of the canonicalized raw_params (Section 5.3). o display_facts: Ground-truth, human-readable representation resolved by the Resource Server from raw_params (e.g., resolving opaque patient/account IDs into human names and descriptions). 5.3. Canonical Parameter Hashing and Numeric Precision via RFC 8785 (JCS) Whenever a parameter object (raw_params or asserted_params) or assertion payload is hashed in this specification: 1. The JSON object MUST first be serialized into its canonical UTF-8 byte representation using the *JSON Canonicalization Scheme (JCS)* ([RFC8785]). 2. A SHA-256 digest ([RFC6234]) MUST be computed over the canonical UTF-8 bytes. 3. The digest MUST be formatted as "sha256:" followed by the lowercase hexadecimal or base64url encoding of the digest bytes. 4. *Numeric Precision and Deserialization Interoperability:* To prevent IEEE 754 floating-point serialization discrepancies across polyglot runtimes (e.g., 500 vs. 500.0 or decimal rounding), fixed-precision quantities such as currency amounts, Williams Expires 3 May 2027 [Page 13] Internet-Draft Proof-of-Intent (PoI) Core October 2026 interest rates, and clinical dosages in raw_params and asserted_params SHOULD be represented as JSON strings (e.g., "60000.00", "6.25"). Furthermore, verifiers MUST compute SHA- 256(JCS(...)) over the raw parsed JSON tree inside the JWS payload prior to unmarshaling into language-specific domain structs that might strip unknown or null fields. 6. Proof-of-Intent Envelope (PoIE) Core Profile 6.1. Two-Node Core Envelope ([R0, R1]) and Header Size Considerations In PoI Core, a Proof-of-Intent Envelope (Content-Type: application/ poi-envelope+json) contains a two-element chain array ([R0, R1]): * *Node 0 (R0, PROPOSAL):* Identifies the Resource Server's challenge. Its node_hash (H0) is SHA-256(ASCII(challenge_jws)). - *Detached Challenge Optimization (Header Size Control):* Because HTTP reverse proxies commonly enforce a 4 KB to 8 KB per-header limit, when a client submits the PoIE via the PoI- Envelope HTTP request header to the same stateful Resource Server that issued R0, Node 0 MAY omit the full challenge_jws string and include only challenge_id and node_hash: H0 (detached mode). For stateless verification or when the serialized PoI-Envelope exceeds 4 KB, the full envelope (including challenge_jws) SHOULD be transmitted in the HTTP request body (Content-Type: application/poi-envelope+json). * *Node 1 (R1):* Represents the human's decision (APPROVE, REJECT, or SUPERCEDE), referencing H0 via target_node_hash (for APPROVE/ REJECT) or supercedes_node_hash (for SUPERCEDE). _Note: Multi-node chains (seq >= 2) for organizational escalations are defined in [POI-CHAINED]._ 6.2. Decision Semantics: APPROVE, REJECT, and SUPERCEDE 1. *APPROVE*: The human signer attests approval of the exact parameter state committed in H0 without modification. 2. *REJECT*: The human signer explicitly denies H0, terminating the transaction. 3. *SUPERCEDE*: The human signer rejects the parameters in H0 (supercedes_node_hash: H0) and asserts a replacement parameter object (asserted_params and asserted_params_hash), optionally accompanied by justification metadata. Williams Expires 3 May 2027 [Page 14] Internet-Draft Proof-of-Intent (PoI) Core October 2026 * *Normative Rule:* Implementations MUST NOT mutate R0 in place when a human edits parameters. Every human modification MUST be recorded as a SUPERCEDE node linking to H0. 6.3. Assurance Tiers and Attestation Bindings Node R1 MUST be cryptographically signed according to one of the following Assurance Tiers: 6.3.1. Tier 1: Ephemeral Session PoP (urn:ietf:params:oauth:poi:tier:session-pop) * The node contains an assertion_jws (typ: "poi+jwt;kind=assert") signed by the client's active EIK. * The JWS Protected Header MUST contain "kcert": "". * Per [RFC8725] Section 3.9, the JWS Payload MUST include an *aud* claim set to the target Resource Server's iss URI from the ICO, alongside intent_id, challenge_id, seq: 1, decision, supercedes_node_hash (or target_node_hash), and client_iat. * Requires zero out-of-band prompts beyond clicking the action button inside the Signing Vault. 6.3.2. Tier 2: Platform Biometric / User Verification (urn:ietf:params:oauth:poi:tier:webauthn-uv) * The Signing Vault invokes W3C [WebAuthn] navigator.credentials.get() with userVerification: "required". * The WebAuthn challenge parameter MUST be set to the raw 32-byte SHA-256(JCS(assertion_payload)) digest (where assertion_payload includes aud matching ico.iss). * In the returned authenticatorData, both Bit 0 (UP - User Present) and Bit 2 (UV - User Verified) MUST be set (1). * Optionally, the Signing Vault MAY also sign the bundle with the Tier 1 EIK to bind the hardware assertion to the active session_id. Williams Expires 3 May 2027 [Page 15] Internet-Draft Proof-of-Intent (PoI) Core October 2026 6.3.3. Tier 3: Cross-Platform Hardware Token (urn:ietf:params:oauth:poi:tier:webauthn-hw) * Identical to Tier 2, except the WebAuthn ceremony MUST be restricted to allowCredentials corresponding to registered cross- platform/roaming hardware authenticators (e.g., FIDO2 hardware security keys) verified via authenticator attestation during registration. 7. Stateless Verification and Countersigned Intent Receipts (CIR) 7.1. Normative Core Verification Algorithm A Resource Server or offline verifier validating a PoI Core envelope ([R0, R1]) MUST execute the following steps in order. Verifiers MAY apply a configurable clock skew tolerance when evaluating nbf and exp claims, which SHOULD NOT exceed 60 seconds. If any step fails, verification MUST fail immediately: 1. *Validate Root Proposal (R0):* * Parse chain[0].challenge_jws (or retrieve the cached ICO via challenge_id if detached), verify typ is "poi+jwt;kind=chal", and verify its signature using the Resource Server's trusted public key. * Confirm chain[0].node_hash == SHA-256(ASCII(challenge_jws)). * At ingestion time, confirm current server time t_eval satisfies ico.nbf <= t_eval <= ico.exp and ico.challenge_id has not been previously consumed. 2. *Validate Link and Digests (R1):* * Confirm chain[1].seq == 1. * Confirm the parent reference (target_node_hash for APPROVE/ REJECT, or supercedes_node_hash for SUPERCEDE) equals chain[0].node_hash (H0). * Confirm assertion.aud == ico.iss (and, if kcert.aud is present, confirm ico.iss is in kcert.aud). * If chain[1].node_type == "SUPERCEDE", recompute SHA- 256(JCS(asserted_params)) over the raw JSON tree and confirm it matches asserted_params_hash. 3. *Validate Signer Credentials and Assurance Tier (R1):* Williams Expires 3 May 2027 [Page 16] Internet-Draft Proof-of-Intent (PoI) Core October 2026 * *For Tier 1 (session-pop):* 1. Extract kcert from the protected header, verify its typ is "poi+jwt;kind=kct", and verify its signature against the Authorization Server's trusted public key. 2. Let t_eval be the current server time (at ingestion) or cir.received_at (during offline audit). Confirm kcert.nbf <= t_eval <= kcert.exp. 3. Verify assertion_jws has typ: "poi+jwt;kind=assert" and verify its signature using the public key in kcert.cnf.jwk. * *For Tier 2 / Tier 3 (webauthn-uv / webauthn-hw):* 1. Parse clientDataJSON and confirm type == "webauthn.get", challenge == base64url(SHA-256(JCS(assertion_payload))), and origin matches the configured Signing Vault origin. If clientDataJSON.crossOrigin == true (when the Signing Vault is an embedded cross-origin iframe), confirm clientDataJSON.topOrigin matches the allowlisted host application origin. 2. Verify the RP ID hash in authenticatorData and confirm UP == 1 and UV == 1. 3. Verify the WebAuthn signature against the registered credential public key associated with the signer and confirm the credential class matches the tier (platform vs. cross-platform hardware). 4. *Determine Effective Parameter State:* * If R1 is APPROVE, the effective parameters are R0.raw_params. * If R1 is SUPERCEDE and satisfies the Resource Server's assurance and authority policy, the effective parameters are R1.asserted_params. 7.2. Countersigned Intent Receipt (CIR) Because EIK certificates (KCT) are short-lived, an attacker who compromises a client host _after_ a KCT expires (or just before expiry) might attempt to forge a backdated assertion timestamped inside [nbf, exp] and inject it into an audit database later. Williams Expires 3 May 2027 [Page 17] Internet-Draft Proof-of-Intent (PoI) Core October 2026 To defeat backdated audit forgery: 1. Immediately upon verifying a PoIE while the KCT is within its active [nbf, exp] window, the Resource Server (or an append-only transparency service per [RFC9943]) MUST generate a *Countersigned Intent Receipt (CIR)* (typ: "poi+jwt;kind=rcpt"). 2. The CIR MUST include received_at (server ingestion NumericDate), intent_id, head_node_hash (H1), committed_params_hash, and the Resource Server's cryptographic signature. 3. Offline auditors MUST verify that kcert.nbf <= cir.received_at <= kcert.exp for all Tier 1 assertions in the receipted chain. 8. Error Handling and Failure Modes When an Authorization Server, Resource Server, or Verifier rejects a PoI request, rollover request, or Proof-of-Intent Envelope (PoIE), it MUST return a deterministic error code corresponding to the specific failure mode. 8.1. Error Response Signaling (PoI-Challenge and RFC 9457) Resource Servers and Authorization Servers signal PoI errors using two complementary mechanisms: 1. *PoI-Challenge Response Header:* For HTTP 401 Unauthorized and 403 Forbidden responses triggered by a PoI failure, the server MUST include a PoI-Challenge header: PoI-Challenge: error="kct_expired", error_description="Ephemeral Intent Key expired", intent_id="intent_loan_4409" 2. *Problem Details JSON Body ([RFC9457]):* The server SHOULD return an HTTP response body formatted as application/problem+json per [RFC9457], extended with poi_error, intent_id, failed_node_seq, required_tier, and an optional challenge_jws. _Non-normative example of an RFC 9457 Problem Details error response:_ Williams Expires 3 May 2027 [Page 18] Internet-Draft Proof-of-Intent (PoI) Core October 2026 HTTP/1.1 401 Unauthorized PoI-Challenge: error="kct_expired", error_description="KCT expired prior to evaluation time", intent_id="intent_loan_4409" Content-Type: application/problem+json { "type": "urn:ietf:params:oauth:poi:error:kct_expired", "title": "Ephemeral Intent Key Certificate Expired", "status": 401, "detail": "KCT exp (1793391000) < eval time (1793391125).", "poi_error": "kct_expired", "intent_id": "intent_loan_4409", "failed_node_seq": 1 } 8.2. Cryptographic Signature, Audience, and Key Binding Errors * *invalid_kct_signature* (HTTP 401 Unauthorized): - _Trigger:_ The Key Certification Token (kcert) signature in a Tier 1 assertion or key rollover request fails verification against the Authorization Server's trusted public key, references an unknown/revoked kid, has an invalid typ (!= "poi+jwt;kind=kct"), or specifies a disallowed alg (none or symmetric MAC). * *invalid_ico_signature* (HTTP 400 Bad Request or Client-Side Rejection): - _Trigger:_ The root Intent Challenge Object (chain[0].challenge_jws) fails signature verification against the Resource Server's public key or has typ != "poi+jwt;kind=chal". If the Signing Vault detects this error upon receiving a challenge from an intermediary agent, the Signing Vault MUST refuse to render the approval prompt and MUST abort signing immediately. * *invalid_assertion_signature* (HTTP 401 Unauthorized): - _Trigger:_ For Tier 1, the JWS signature on assertion_jws does not verify using kcert.cnf.jwk. For Tier 2/3, the WebAuthn signature does not verify over authenticatorData || SHA- 256(clientDataJSON) using the user's registered credential public key. * *audience_mismatch* (HTTP 401 Unauthorized): Williams Expires 3 May 2027 [Page 19] Internet-Draft Proof-of-Intent (PoI) Core October 2026 - _Trigger:_ The aud claim in assertion_jws (or assertion_payload) does not match the Resource Server's iss URI in the ICO (assertion.aud != ico.iss), or kcert.aud is present and excludes the Resource Server. * *invalid_webauthn_attestation* (HTTP 401 Unauthorized): - _Trigger:_ In a Tier 2 or Tier 3 assertion, one or more WebAuthn verification invariants failed (clientDataJSON.type != "webauthn.get", origin or topOrigin mismatch, RP ID hash mismatch, UP or UV bit is 0, or authenticator class does not match the tier requirement). * *invalid_rollover_proof* (HTTP 401 Unauthorized): - _Trigger:_ During PoP Key Chaining Rotation (Section 4.3), the signature on the poi+jwt;kind=roll request fails verification under the active predecessor key K_n specified in kcert.cnf.jwk. 8.3. Temporal and Validity Window Errors (nbf, exp, auth_time, Replay) * *kct_not_yet_valid* (HTTP 401 Unauthorized): - _Trigger:_ Evaluation timestamp t_eval < kcert.nbf (beyond clock skew tolerance, which SHOULD NOT exceed 60 seconds). * *kct_expired* (HTTP 401 Unauthorized): - _Trigger:_ Evaluation timestamp t_eval > kcert.exp, or a client attempts to sign a PoP key rollover request using an expired predecessor key K_n. * *challenge_not_yet_valid* (HTTP 400 Bad Request): - _Trigger:_ Evaluation timestamp t_eval < ico.nbf. * *challenge_expired* (HTTP 401 Unauthorized or 403 Forbidden): - _Trigger:_ Evaluation timestamp t_eval > ico.exp. The Resource Server MAY include a newly minted challenge_jws in the error response. * *session_max_age_exceeded* (HTTP 401 Unauthorized): Williams Expires 3 May 2027 [Page 20] Internet-Draft Proof-of-Intent (PoI) Core October 2026 - _Trigger:_ Although the current KCT is within [nbf, exp], (t_eval - kcert.auth_time) exceeds either the Resource Server's required freshness policy (max_age) or the Authorization Server's maximum session lifetime. * *session_revoked* (HTTP 401 Unauthorized): - _Trigger:_ The logical session_id referenced in the KCT has been administratively terminated or logged out prior to kcert.exp. * *challenge_replayed* (HTTP 409 Conflict): - _Trigger:_ The challenge_id in the ICO or the nonce in a key rollover request has already been consumed. 8.4. Envelope Integrity and Step-Up Errors * *malformed_poi_envelope* (HTTP 400 Bad Request): - _Trigger:_ The PoI-Envelope header or body cannot be parsed as valid JSON/JWS, omits required claims, or has a mismatched typ parameter (kind). * *chain_continuity_broken* (HTTP 422 Unprocessable Content): - _Trigger:_ chain[0].node_hash does not match SHA- 256(ASCII(challenge_jws)), or R1's parent hash pointer (target_node_hash or supercedes_node_hash) does not equal H0. * *params_hash_mismatch* (HTTP 422 Unprocessable Content): - _Trigger:_ Recomputed SHA-256(JCS(params)) does not match the signed raw_params_hash or asserted_params_hash (or WebAuthn clientDataJSON.challenge), indicating parameter tampering. * *intent_rejected* (HTTP 422 Unprocessable Content): - _Trigger:_ R1 is a valid REJECT assertion node; the Resource Server records the rejection and aborts execution permanently. * *intent_proof_required* (HTTP 403 Forbidden): - _Trigger:_ No PoI-Envelope was provided for a protected action; response includes the initial challenge_jws (R0). * *insufficient_assurance_tier* (HTTP 403 Forbidden): Williams Expires 3 May 2027 [Page 21] Internet-Draft Proof-of-Intent (PoI) Core October 2026 - _Trigger:_ R1 is cryptographically valid, but its assurance tier is lower than required by the Resource Server (e.g., when a SUPERCEDE parameter edit crosses into a higher assurance requirement). _(Note: Additional error codes for multi-hop escalations, asynchronous TOCTOU state drift, and concurrent approver Compare-and- Swap conflicts are defined in [POI-CHAINED].)_ 8.5. Summary Matrix of PoI Core Error Codes +============================+=============+======+================+ |poi_error Code |Category |HTTP |Retryable with | | | |Status|New Signature? | +============================+=============+======+================+ |intent_proof_required |Step-Up / |403 |Yes (Sign | | |Challenge | |returned ICO) | +----------------------------+-------------+------+----------------+ |insufficient_assurance_tier |Step-Up / |403 |Yes (Step up to | | |Challenge | |required_tier) | +----------------------------+-------------+------+----------------+ |invalid_kct_signature |Cryptographic|401 |No (Re- | | | | |authenticate to | | | | |IdP) | +----------------------------+-------------+------+----------------+ |invalid_ico_signature |Cryptographic|400 |No (Abort; | | | | |potential MITM) | +----------------------------+-------------+------+----------------+ |invalid_assertion_signature |Cryptographic|401 |No | +----------------------------+-------------+------+----------------+ |audience_mismatch |Cryptographic|401 |No (Potential | | |/ Binding | |cross-service | | | | |replay) | +----------------------------+-------------+------+----------------+ |invalid_webauthn_attestation|Cryptographic|401 |Yes (Retry with | | | | |valid | | | | |authenticator) | +----------------------------+-------------+------+----------------+ |invalid_rollover_proof |Cryptographic|401 |No (Re- | | | | |authenticate to | | | | |IdP) | +----------------------------+-------------+------+----------------+ |kct_not_yet_valid |Temporal |401 |Yes (After nbf | | |(nbf) | |or clock sync) | +----------------------------+-------------+------+----------------+ |kct_expired |Temporal |401 |Yes (Rotate key | | |(exp) | |or re- | | | | |authenticate) | Williams Expires 3 May 2027 [Page 22] Internet-Draft Proof-of-Intent (PoI) Core October 2026 +----------------------------+-------------+------+----------------+ |challenge_not_yet_valid |Temporal |400 |Yes (After | | |(nbf) | |ico.nbf) | +----------------------------+-------------+------+----------------+ |challenge_expired |Temporal |401 / |Yes (Sign fresh | | |(exp) |403 |challenge_jws) | +----------------------------+-------------+------+----------------+ |session_max_age_exceeded |Temporal |401 |Yes (After | | |(auth_time) | |interactive re- | | | | |auth) | +----------------------------+-------------+------+----------------+ |session_revoked |Temporal / |401 |No (Session | | |Session | |terminated) | +----------------------------+-------------+------+----------------+ |challenge_replayed |Replay |409 |No (Request new | | | | |challenge) | +----------------------------+-------------+------+----------------+ |malformed_poi_envelope |Syntax / |400 |No | | |Format | | | +----------------------------+-------------+------+----------------+ |chain_continuity_broken |Chain |422 |No (Tampered or | | |Integrity | |broken link) | +----------------------------+-------------+------+----------------+ |params_hash_mismatch |Payload |422 |No (Tampered | | |Integrity | |parameters) | +----------------------------+-------------+------+----------------+ |intent_rejected |Terminal |422 |No (Human | | |Decision | |explicitly | | | | |rejected) | +----------------------------+-------------+------+----------------+ Table 2 9. Security Considerations 9.1. Confused Deputy and Post-Approval Agent Bypass When a human approves an action or asserts modified parameters via SUPERCEDE, the Resource Server MUST execute the verified canonical parameters directly. The Resource Server MUST NOT return modified parameters to an autonomous LLM or AI agent for re-interpretation or re-submission, as doing so re-introduces the agent as a potential confused deputy between human signature and state execution. The intermediary agent SHOULD receive only a read-only execution receipt (CIR). Williams Expires 3 May 2027 [Page 23] Internet-Draft Proof-of-Intent (PoI) Core October 2026 9.2. Key Smuggling, Cross-Origin Vault Isolation, and WebAuthn Permissions Policy Generating the EIK with extractable: false prevents exfiltration of raw private key bytes over the network. However, an attacker achieving Cross-Site Scripting (XSS) within a complex web application could attempt to invoke crypto.subtle.sign() in-situ (acting as a signing oracle). To mitigate signing oracle abuse for Tier 1 keys, implementations SHOULD isolate key generation, key storage, ICO signature verification, display_facts rendering, and the physical approval button inside a dedicated, minimal cross-origin iframe (e.g., https://vault.example.org) enforced with a strict Content Security Policy (script-src 'self'; object-src 'none'). The host application (https://app.example.org) communicates with the Signing Vault exclusively via window.postMessage by passing the Resource Server's signed ICO. *WebAuthn Cross-Origin Iframe Delegation:* When Tier 2 or Tier 3 [WebAuthn] ceremonies are invoked from within a cross-origin Signing Vault iframe (https://vault.example.org), the embedding host document (https://app.example.org) MUST delegate credential access via the HTTP Permissions-Policy header (Permissions-Policy: publickey- credentials-get=(self "https://vault.example.org")) and the iframe allow attribute (