Network Working Group N. Kavian Internet-Draft Jarwin, Inc. (InFlow) Intended status: Standards Track 27 June 2026 Expires: 29 December 2026 The Agent Enrollment Protocol draft-kavian-agent-enrollment-protocol-00 Abstract The Agent Enrollment Protocol (AEP) defines an HTTP-based mechanism for autonomous agents to discover service enrollment requirements, enroll an agent identity, obtain optional session credentials, revoke those credentials, and query enrollment status. AEP uses Decentralized Identifiers, client assertion JWTs, and HTTP Problem Details to provide a narrow machine-first enrollment and authentication substrate for agent-to-service interactions. Status of This Memo This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79. 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 29 December 2026. Copyright Notice Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved. Kavian Expires 29 December 2026 [Page 1] Internet-Draft AEP June 2026 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 2. Requirements Language . . . . . . . . . . . . . . . . . . . . 3 3. Terminology . . . . . . . . . . . . . . . . . . . . . . . . . 3 4. Protocol Overview . . . . . . . . . . . . . . . . . . . . . . 4 5. HTTP Binding . . . . . . . . . . . . . . . . . . . . . . . . 5 6. Discovery and Inspect . . . . . . . . . . . . . . . . . . . . 6 7. DID Method: did:web . . . . . . . . . . . . . . . . . . . . . 8 8. AEP HTTP Authentication Scheme . . . . . . . . . . . . . . . 8 9. Client Assertion JWT . . . . . . . . . . . . . . . . . . . . 9 10. The Inspect Command . . . . . . . . . . . . . . . . . . . . . 11 11. The Enroll Command . . . . . . . . . . . . . . . . . . . . . 11 12. The Status Command . . . . . . . . . . . . . . . . . . . . . 12 13. The Grant Command . . . . . . . . . . . . . . . . . . . . . . 13 14. The Revoke Command . . . . . . . . . . . . . . . . . . . . . 14 15. Idempotency . . . . . . . . . . . . . . . . . . . . . . . . . 15 16. Error Handling . . . . . . . . . . . . . . . . . . . . . . . 15 17. Extensibility . . . . . . . . . . . . . . . . . . . . . . . . 18 18. Wire Identifier Syntax . . . . . . . . . . . . . . . . . . . 19 19. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 19 19.1. HTTP Authentication Scheme . . . . . . . . . . . . . . . 19 19.2. Well-Known URI . . . . . . . . . . . . . . . . . . . . . 19 19.3. Media Type . . . . . . . . . . . . . . . . . . . . . . . 20 19.4. AEP Command Registry . . . . . . . . . . . . . . . . . . 21 19.5. AEP Binding Identifier Registry . . . . . . . . . . . . 22 19.6. AEP Extension Identifier Registry . . . . . . . . . . . 23 19.7. AEP Error Code Registry . . . . . . . . . . . . . . . . 24 19.8. AEP Grant Type Registry . . . . . . . . . . . . . . . . 25 20. Security Considerations . . . . . . . . . . . . . . . . . . . 26 21. Privacy Considerations . . . . . . . . . . . . . . . . . . . 27 22. References . . . . . . . . . . . . . . . . . . . . . . . . . 28 22.1. Normative References . . . . . . . . . . . . . . . . . . 28 22.2. Informative References . . . . . . . . . . . . . . . . . 30 Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 30 Kavian Expires 29 December 2026 [Page 2] Internet-Draft AEP June 2026 1. Introduction Autonomous agents increasingly interact with internet services without a human directly completing registration forms, email confirmations, password setup, or dashboard-based API-key provisioning. Existing HTTP authentication mechanisms can authenticate an already-provisioned client, but they do not define a machine-first enrollment flow by which an autonomous agent discovers a service's requirements, presents a cryptographic identity, and becomes recognized by that service. The Agent Enrollment Protocol (AEP) defines that enrollment substrate. AEP lets an Agent discover what a Service requires, enroll a did:web identity, authenticate AEP commands with a per- request client assertion JWT, optionally obtain a session credential, revoke issued session credentials, and query enrollment status. AEP is deliberately narrow. It does not define payment settlement, checkout semantics, action authorization, KYC execution, or legal policy. Those functions can compose above or beside AEP. This document defines only the minimum HTTP protocol needed for interoperable Agent enrollment and session-credential bootstrapping. This document's scope is limited to the HTTP binding for Inspect, Enroll, Grant, Revoke, and Status. Update, Rotate, Decommission, non-HTTP transports, concrete session-credential formats, policy disclosures, KYA, ZK proofs, and other extensions are out of scope for this document. 2. 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. 3. Terminology Agent: Software acting autonomously. An Agent holds or controls a cryptographic key and initiates AEP requests. Service: The HTTP server that receives AEP requests and decides whether to enroll or recognize an Agent. Owner: The human or organization that owns or controls an Agent. Owner details are represented as claims when a Service requires them. Kavian Expires 29 December 2026 [Page 3] Internet-Draft AEP June 2026 Platform: An optional operator that hosts Agent identity material or signing infrastructure. A Platform is not required by AEP. Verifier: A party that verifies claims about an Agent or Owner and may issue attestations referenced by the Agent. This document does not define attestation formats. Inspect document: The JSON discovery document published by a Service at /.well-known/aep. It advertises AEP version, supported commands, accepted identity methods, requested claims, endpoint configuration, and extension support. Client assertion: A JWT signed by the Agent's private key and presented on authenticated AEP commands. The assertion binds the Agent identity, Service identity, command name, issuance time, expiration time, and replay identifier. Session credential: A stateful credential issued by the Grant command and presented on later requests according to a separate session-credential specification. Grant type: A string identifier for a concrete session-credential format supported by the Service, such as an OAuth Bearer, API-key, or Basic credential specification. 4. Protocol Overview The baseline AEP flow is: 1. The Agent fetches the Service's Inspect document. 2. The Agent evaluates whether it can satisfy the Service's did:web and claim requirements. 3. The Agent constructs a client assertion JWT with aud equal to the Service DID and op equal to the command being invoked. 4. The Agent invokes Enroll. 5. The Agent calls Status when enrollment is pending or when it needs current state. 6. The Agent may call Grant for a supported session-credential type. 7. The Agent may call Revoke to invalidate issued session credentials. Kavian Expires 29 December 2026 [Page 4] Internet-Draft AEP June 2026 Inspect is unauthenticated. Enroll, Grant, Revoke, and Status are authenticated with the baseline Authorization: AEP form. Session credentials, once issued, MAY be used on commands that allow the selected credential type; Grant and Revoke themselves always use the baseline client assertion. 5. HTTP Binding This document defines an HTTP binding using HTTP semantics [RFC9110] over HTTP/1.1 [RFC9112], HTTP/2 [RFC9113], or HTTP/3 [RFC9114]. Network use of this binding requires TLS 1.3 or later [RFC8446]. Plaintext HTTP is out of scope. The binding uses only GET and POST: +=========+========+==================================+ | Command | Method | Endpoint | +=========+========+==================================+ | Inspect | GET | /.well-known/aep | +---------+--------+----------------------------------+ | Enroll | POST | enroll relative to endpoint_base | +---------+--------+----------------------------------+ | Status | GET | status relative to endpoint_base | +---------+--------+----------------------------------+ | Grant | POST | grant relative to endpoint_base | +---------+--------+----------------------------------+ | Revoke | POST | revoke relative to endpoint_base | +---------+--------+----------------------------------+ Table 1 The endpoint_base value is published in the Inspect document under http.endpoint_base. If omitted, Agents MUST use /aep/. Agents construct command URLs by appending the command's relative path to endpoint_base with exactly one / separator, regardless of whether endpoint_base includes a trailing slash. For example, both /aep and /aep/ produce /aep/enroll for Enroll. Requests and successful responses that carry AEP JSON payloads use application/aep+json, which uses the +json structured syntax suffix [RFC6839]. Error responses use application/problem+json. Authenticated commands carry a baseline client assertion as: Authorization: AEP Kavian Expires 29 December 2026 [Page 5] Internet-Draft AEP June 2026 When a session credential is used on a command that allows it, the credential presentation form is defined by the concrete session- credential document. 6. Discovery and Inspect The Inspect document is available at the well-known URI path defined for AEP [RFC8615]: GET /.well-known/aep HTTP/1.1 Host: example.com Accept: application/aep+json The response body is a JSON object [RFC8259]. AEP-owned numeric protocol values are represented as JSON strings. Field names use lower_snake_case. Claim names use dotted lowercase tokens: claim-name = claim-token *("." claim-token) claim-token = LCALPHA *(LCALPHA / DIGIT / "_") LCALPHA = %x61-7A The LCALPHA rule is defined here. The DIGIT rule is defined by RFC 5234 [RFC5234]. The Inspect document shown here contains only the fields required for the HTTP binding, did:web, Inspect, Enroll, Grant, Revoke, and Status: Kavian Expires 29 December 2026 [Page 6] Internet-Draft AEP June 2026 { "aep_version": "1.0", "bindings": { "supported": ["http"] }, "claims": { "optional": [], "preferred": [], "required": ["contact.email"] }, "commands": { "grant_types": ["oauth-bearer"], "supported": ["enroll", "grant", "inspect", "revoke", "status"] }, "core": { "signing_algorithms": ["EdDSA", "ES256"] }, "extensions": { "supported": [] }, "http": { "endpoint_base": "/aep/" }, "identity": { "methods": ["did:web"] }, "service": { "did": "did:web:api.example.com" } } commands.supported lists commands the Service exposes. Agents MUST NOT invoke commands absent from this list. commands.grant_types lists concrete session-credential formats the Service can issue and revoke. If this array is empty or absent, the Service MUST NOT list grant or revoke in commands.supported. identity.methods MUST contain did:web when the Service accepts this document's identity method. Other DID methods are out of scope for this document. service.did identifies the Service. Agents use this value as the aud claim in client assertion JWTs. Kavian Expires 29 December 2026 [Page 7] Internet-Draft AEP June 2026 Services SHOULD send HTTP cache metadata, including Cache-Control and ETag, on Inspect responses. A default freshness lifetime of 300 seconds is RECOMMENDED when the Service does not need a shorter policy window. 7. DID Method: did:web This document defines did:web [DID-WEB] as the only required identity method. A Service that supports this document advertises: { "identity": { "methods": ["did:web"] } } An Agent using this document identifies itself with a did:web URI. The Service resolves the DID to obtain the Agent's public verification key: * did:web: resolves to https:///.well-known/did.json. * did:web:: resolves to https:////did.json. The resolved DID document MUST contain a verification method referenced by the JWT kid header. The verification method MUST expose a public key in a form the Service can validate against the selected JOSE signing algorithm. Services MUST resolve did:web documents over HTTPS. Services SHOULD cache resolved DID documents and SHOULD honor upstream cache metadata. A default cache lifetime of 300 seconds is RECOMMENDED when no shorter upstream lifetime is provided. If the Agent presents an identity method not listed in the Service's identity.methods array, the Service MUST reject the request as not_recognized. 8. AEP HTTP Authentication Scheme The AEP HTTP authentication scheme uses the AEP auth-scheme value. The rules ALPHA, DIGIT, DQUOTE, and SP are defined by RFC 5234 [RFC5234]. The rules auth-param, BWS, and OWS are defined by HTTP semantics [RFC9110]. Kavian Expires 29 December 2026 [Page 8] Internet-Draft AEP June 2026 AEP-credentials = "AEP" 1*SP compact-jws compact-jws = base64url "." base64url "." base64url base64url = 1*( ALPHA / DIGIT / "-" / "_" ) AEP-challenge = "AEP" [ 1*SP AEP-challenge-param *( OWS "," OWS AEP-challenge-param ) ] AEP-challenge-param = reason-param / auth-param reason-param = "reason" BWS "=" BWS DQUOTE error-code DQUOTE error-code = lc-token *( "_" lc-token ) lc-token = LCALPHA *( LCALPHA / DIGIT ) The AEP-credentials form is used in the Authorization header field. The AEP-challenge form is used in the WWW-Authenticate header field. The reason parameter, when present, carries an AEP error code. 9. Client Assertion JWT Enroll, Grant, Revoke, and Status use a signed client assertion JWT for Agent authentication. Inspect is unauthenticated and does not use a client assertion. The client assertion JWT is carried as: Authorization: AEP The JWT is a JWS compact serialization [RFC7515] consisting of a JOSE header, JWT claims set [RFC7519], and signature. The JOSE header MUST contain: { "alg": "EdDSA", "typ": "JWT", "kid": "did:web:agent.example.com:agents:123#key-1" } alg identifies the signing algorithm. Services supporting this document MUST support EdDSA [RFC8037] and ES256 [RFC7518] and advertise accepted algorithms in core.signing_algorithms. Agents MUST select an algorithm advertised by the Service. The none algorithm and symmetric JOSE algorithms MUST NOT be used for Agent identity assertions. typ MUST be JWT. kid identifies the Agent's DID and MAY include a fragment selecting a verification method in the resolved DID document. The DID portion of kid MUST equal the Agent DID carried in iss and sub. Kavian Expires 29 December 2026 [Page 9] Internet-Draft AEP June 2026 The JWT claims set MUST contain: { "iss": "did:web:agent.example.com:agents:123", "sub": "did:web:agent.example.com:agents:123", "aud": "did:web:api.example.com", "op": "enroll", "iat": 1748428800, "exp": 1748428860, "jti": "9f8a4d2e-1c3b-4f5e-8b7a-000000000000" } iss and sub MUST both equal the Agent DID. aud MUST equal the Service DID advertised as service.did in the Inspect document. op MUST equal the command being invoked. The values defined by this document are enroll, grant, revoke, and status. iat and exp are NumericDate values as defined by JWT [RFC7519]: seconds since the Unix epoch represented as JSON numbers. These claims are an exception to AEP-owned JSON payload numeric-string encoding. Services MUST reject assertions where exp - iat is greater than 300 seconds. Services SHOULD allow no more than 30 seconds of local clock skew. jti MUST be freshly generated for each assertion. Services MUST maintain a replay cache keyed by at least (sub, jti) for the assertion lifetime plus the accepted clock-skew window. To verify a client assertion, the Service MUST: 1. Parse the JWT header, claims set, and signature. 2. Reject the assertion if alg is not advertised by the Service or is prohibited by this document. 3. Resolve the DID identified by kid. 4. Select the referenced verification method. 5. Verify the JWS signature. 6. Verify iss, sub, aud, op, iat, exp, and jti according to this section. Kavian Expires 29 December 2026 [Page 10] Internet-Draft AEP June 2026 Any verification failure MUST use the common not_recognized error defined in this document's error handling section. 10. The Inspect Command Inspect is the unauthenticated discovery command. An Agent invokes Inspect by fetching the Service's well-known AEP document: GET /.well-known/aep HTTP/1.1 Host: example.com Accept: application/aep+json The Service returns 200 OK with an application/aep+json body containing the Inspect document described in this document. Inspect has no request body and no client assertion. Agents SHOULD cache Inspect documents according to the Service's HTTP cache metadata. Agents MUST re-fetch the Inspect document before invoking a command if the cached document has expired. 11. The Enroll Command Enroll registers an Agent DID with a Service. The request uses the baseline client assertion with op equal to enroll. Endpoint: POST /aep/enroll HTTP/1.1 Host: example.com Content-Type: application/aep+json Authorization: AEP Idempotency-Key: Request body: { "agent_did": "did:web:agent.example.com:agents:123", "claims": { "contact.email": "ops@example.com" }, "idempotency_key": "9f8a4d2e-1c3b-4f5e-8b7a-000000000000" } agent_did MUST equal the Agent DID in the client assertion iss, sub, and kid values, ignoring any kid fragment. The DID method MUST be accepted by the Service's identity.methods advertisement. Kavian Expires 29 December 2026 [Page 11] Internet-Draft AEP June 2026 claims carries claim values requested by the Service's Inspect document. This document does not define a complete claim catalog. Claim names are strings and claim values are JSON values. Services MUST ignore unknown claims unless local policy requires rejection. idempotency_key is an opaque retry key. When both the HTTP Idempotency-Key header and body field are present, they MUST contain the same value. Successful Enroll responses use 200 OK. A synchronous enrollment returns: { "status": "active" } If enrollment requires asynchronous verification, the Service returns: { "owner_action_required": "false", "status": "pending", "verification_pending": ["contact.email"] } The Agent polls Status to learn whether a pending enrollment has become active or rejected. 12. The Status Command Status returns the Service's current state for the authenticated Agent identity. The request uses the baseline client assertion with op equal to status, or a session credential when a concrete session- credential document allows it. Endpoint: GET /aep/status HTTP/1.1 Host: example.com Authorization: AEP Status has no request body. Successful Status responses use 200 OK: Kavian Expires 29 December 2026 [Page 12] Internet-Draft AEP June 2026 { "owner_action_required": "false", "requirements_pending": [], "since": "2026-05-28T12:00:00Z", "status": "active" } status describes the Agent identity's state at the Service: +=============+===================================================+ | Value | Meaning | +=============+===================================================+ | active | The identity is enrolled and operational. | +-------------+---------------------------------------------------+ | pending | Enrollment is awaiting asynchronous verification. | +-------------+---------------------------------------------------+ | unavailable | The identity is temporarily unavailable for | | | Service-defined non-punitive reasons. | +-------------+---------------------------------------------------+ | suspended | The identity is temporarily disabled by Service | | | action. | +-------------+---------------------------------------------------+ | terminated | The identity is permanently de-registered. | +-------------+---------------------------------------------------+ | rejected | Asynchronous verification failed. | +-------------+---------------------------------------------------+ Table 2 since is the RFC 3339 [RFC3339] timestamp of the last state transition. requirements_pending lists claim names the Agent should provide to satisfy current Service requirements. owner_action_required is a JSON string boolean. A value of "true" indicates that the Agent's Owner must complete an out-of-band action before the identity can become or remain active. 13. The Grant Command Grant exchanges a baseline client assertion for a session credential. The request uses the baseline client assertion with op equal to grant. A session credential MUST NOT be used to authenticate Grant. Endpoint: Kavian Expires 29 December 2026 [Page 13] Internet-Draft AEP June 2026 POST /aep/grant HTTP/1.1 Host: example.com Content-Type: application/aep+json Authorization: AEP Idempotency-Key: Request body: { "grant_type": "oauth-bearer" } grant_type MUST be one of the values advertised in commands.grant_types. Concrete session-credential documents MAY define additional request fields. The successful response body is defined by the concrete session- credential document. This core document requires only that the response be a JSON object and that the selected document define credential presentation, expiry semantics, and revocation behavior. 14. The Revoke Command Revoke invalidates session credentials previously issued by Grant. The request uses the baseline client assertion with op equal to revoke. A session credential MUST NOT be used to authenticate Revoke. Endpoint: POST /aep/revoke HTTP/1.1 Host: example.com Content-Type: application/aep+json Authorization: AEP Idempotency-Key: Request body: { "grant_type": "oauth-bearer" } grant_type MUST be one of the values advertised in commands.grant_types. By default, Revoke targets all credentials of that grant type issued to the authenticated Agent. Concrete session- credential documents MAY define additional fields for narrower credential targeting. Kavian Expires 29 December 2026 [Page 14] Internet-Draft AEP June 2026 To revoke all session credentials of every grant type issued to the authenticated Agent, the request body is: { "all_grant_types": "true" } all_grant_types is a string boolean. When all_grant_types is "true", the request MUST NOT contain grant_type or credential_id. A Service that supports Revoke MUST support all_grant_types so an Agent can invalidate all issued session credentials without discovering or iterating over every concrete grant type. A malformed Revoke request, including a request with mutually exclusive fields, fails with invalid_request. Successful Revoke responses use 200 OK and an empty JSON object: {} The Service MUST return success regardless of whether any matching credentials existed. 15. Idempotency POST commands are state-mutating and MUST support safe retry with the Idempotency-Key HTTP header. This requirement applies to Enroll, Grant, and Revoke in this document. Services MUST cache the response associated with (agent_did, Idempotency-Key) for at least 1 hour. If a request repeats the same key with the same authenticated Agent and the same request body, the Service MUST return the cached response or an equivalent successful response. If the same authenticated Agent reuses an idempotency key with a different request body, the Service MUST return 409 Conflict with code equal to idempotency_conflict. The Enroll request body MAY also contain idempotency_key for bindings or application frameworks that persist idempotency metadata with the body. When both forms are present, they MUST match. 16. Error Handling The HTTP binding uses RFC 9457 Problem Details [RFC9457] with an AEP code field. Kavian Expires 29 December 2026 [Page 15] Internet-Draft AEP June 2026 HTTP/1.1 401 Unauthorized Content-Type: application/problem+json WWW-Authenticate: AEP reason="not_recognized" { "code": "not_recognized", "status": 401, "type": "https://aep.example/errors/not_recognized" } The code field is the canonical machine-readable AEP error code. type SHOULD identify stable documentation for the error class. title MAY be omitted from production responses. This document defines the following HTTP error codes: +========================+========+=================================+ | AEP code | HTTP | Meaning | | | status | | +========================+========+=================================+ | enrollment_failed | 400 | Generic enrollment failure | | | | where the Service suppresses | | | | precise detail. | +------------------------+--------+---------------------------------+ | invalid_request | 400 | The request body, parameters, | | | | or field combination is | | | | malformed or invalid. | +------------------------+--------+---------------------------------+ | not_recognized | 401 | Umbrella anti-enumeration | | | | error for failed identity, | | | | signature, audience, | | | | operation, replay, time- | | | | window, archived-identity, or | | | | unsupported-method checks. | +------------------------+--------+---------------------------------+ | identity_suspended | 403 | The recognized identity is | | | | temporarily disabled by | | | | Service action. | +------------------------+--------+---------------------------------+ | identity_terminated | 403 | The recognized identity is | | | | permanently de-registered. | +------------------------+--------+---------------------------------+ | identity_unavailable | 403 | The recognized identity is | | | | temporarily unavailable for | | | | Service-defined reasons. | +------------------------+--------+---------------------------------+ | requirements_unmet | 422 | Required claims are missing | | | | or invalid. | Kavian Expires 29 December 2026 [Page 16] Internet-Draft AEP June 2026 +------------------------+--------+---------------------------------+ | verification_pending | 403 | Enrollment or required | | | | verification has not | | | | completed. | +------------------------+--------+---------------------------------+ | verification_timeout | 422 | Required asynchronous | | | | verification did not complete | | | | in the Service's policy | | | | window. | +------------------------+--------+---------------------------------+ | rate_limited | 429 | The Agent exceeded a Service | | | | rate limit. | +------------------------+--------+---------------------------------+ | unsupported_grant_type | 400 | Grant or Revoke requested a | | | | grant_type not advertised by | | | | the Service. | +------------------------+--------+---------------------------------+ | idempotency_conflict | 409 | An idempotency key was reused | | | | with a different request | | | | body. | +------------------------+--------+---------------------------------+ Table 3 Services MUST use not_recognized for bad signatures, unknown Agent identities, wrong aud, wrong op, replayed jti, time-window violations, archived identities, unsupported identity methods during authenticated contact, and unknown or revoked session credentials. Services MUST NOT reveal which of these checks failed. Services MUST use invalid_request for malformed JSON, missing required fields, invalid field types, unsupported field combinations, and syntactically invalid requests when returning the error would not reveal identity-recognition state. Services MUST implement constant-time-shaped response behavior for not_recognized paths so that observable latency does not distinguish a known Agent from an unknown Agent or a validly formatted assertion from a bad signature. When a request fails for multiple reasons, the Service MUST choose the least revealing error. For example, a request with both a bad signature and missing claims returns not_recognized, not requirements_unmet. Kavian Expires 29 December 2026 [Page 17] Internet-Draft AEP June 2026 17. Extensibility This document defines the extension points needed by the core protocol: * extensions.supported advertises extension identifiers implemented by the Service. * commands.grant_types advertises concrete session-credential formats available through Grant and Revoke. * commands.grant_types_config MAY carry per-grant-type configuration defined by a concrete session-credential document. * claims.required, claims.preferred, and claims.optional MAY contain claim names defined by other documents. * Additional top-level Inspect fields MAY be added by future documents. Agents MUST ignore extension identifiers and additive fields they do not understand, unless local policy requires the Agent to refuse enrollment when a required capability is absent. Services MUST NOT redefine the semantics of commands, fields, status values, or error codes defined by this document. Extensions are additive. Concrete session-credential documents MUST define: 1. The grant_type string. 2. Grant request fields beyond grant_type, if any. 3. Grant response shape. 4. Credential presentation on HTTP requests. 5. Expiry semantics. 6. Revoke request fields beyond grant_type and all_grant_types, if any. 7. Error behavior beyond the core errors, if any. Kavian Expires 29 December 2026 [Page 18] Internet-Draft AEP June 2026 18. Wire Identifier Syntax Command identifiers, binding identifiers, and grant type identifiers use lowercase hyphenated tokens: wire-identifier = lc-token *( "-" lc-token ) Error codes use lowercase underscore-separated tokens: error-code = lc-token *( "_" lc-token ) Extension identifiers MUST be absolute URIs. AEP-owned extension identifiers SHOULD use the URN form urn:aep:ext::#v=. 19. IANA Considerations This section requests registrations and registry creation following RFC 8126 [RFC8126]. 19.1. HTTP Authentication Scheme IANA is requested to register the following HTTP authentication scheme in the "HTTP Authentication Schemes" registry: +============================+=================================+ | Field | Value | +============================+=================================+ | Authentication Scheme Name | AEP | +----------------------------+---------------------------------+ | Reference | This document | +----------------------------+---------------------------------+ | Notes | Agent Enrollment Protocol | | | client assertion authentication | +----------------------------+---------------------------------+ Table 4 19.2. Well-Known URI IANA is requested to register the following URI suffix in the "Well- Known URIs" registry: Kavian Expires 29 December 2026 [Page 19] Internet-Draft AEP June 2026 +=====================+============================================+ | Field | Value | +=====================+============================================+ | URI Suffix | aep | +---------------------+--------------------------------------------+ | Change Controller | IETF | +---------------------+--------------------------------------------+ | Reference | This document | +---------------------+--------------------------------------------+ | Related Information | Agent Enrollment Protocol Inspect document | +---------------------+--------------------------------------------+ Table 5 19.3. Media Type IANA is requested to register the following media type in the "Media Types" registry: +==================+===========================================+ | Field | Value | +==================+===========================================+ | Type name | application | +------------------+-------------------------------------------+ | Subtype name | aep+json | +------------------+-------------------------------------------+ | Required | None | | parameters | | +------------------+-------------------------------------------+ | Optional | None | | parameters | | +------------------+-------------------------------------------+ | Encoding | Same as JSON [RFC8259] | | considerations | | +------------------+-------------------------------------------+ | Security | AEP payloads can contain Agent | | considerations | identifiers, claims, session credentials, | | | and other security-sensitive protocol | | | data. Implementations need to apply the | | | authentication, confidentiality, anti- | | | replay, anti-enumeration, logging, and | | | privacy requirements described in the | | | Security Considerations and Privacy | | | Considerations sections of this document. | +------------------+-------------------------------------------+ | Interoperability | None | | considerations | | +------------------+-------------------------------------------+ Kavian Expires 29 December 2026 [Page 20] Internet-Draft AEP June 2026 | Published | This document | | specification | | +------------------+-------------------------------------------+ | Applications | Services and Agents implementing AEP | | that use this | | | media type | | +------------------+-------------------------------------------+ | Fragment | Same as JSON [RFC8259] | | identifier | | | considerations | | +------------------+-------------------------------------------+ | Additional | None | | information | | +------------------+-------------------------------------------+ | Person and email | IETF iesg@ietf.org (mailto:iesg@ietf.org) | | address to | | | contact for | | | further | | | information | | +------------------+-------------------------------------------+ | Intended usage | COMMON | +------------------+-------------------------------------------+ | Restrictions on | None | | usage | | +------------------+-------------------------------------------+ | Author | IETF | +------------------+-------------------------------------------+ | Change | IETF | | controller | | +------------------+-------------------------------------------+ Table 6 19.4. AEP Command Registry IANA is requested to create an "AEP Commands" registry. The registration policy is Specification Required as defined by RFC 8126. Designated experts are requested to verify that new command registrations define command semantics, authentication requirements, request and response shapes, idempotency behavior for state-mutating commands, and error behavior. Each entry contains: Kavian Expires 29 December 2026 [Page 21] Internet-Draft AEP June 2026 +=============+=================================+ | Field | Description | +=============+=================================+ | Command | Lowercase wire identifier. | +-------------+---------------------------------+ | Description | Short command description. | +-------------+---------------------------------+ | Reference | Stable specification reference. | +-------------+---------------------------------+ Table 7 Initial entries are: +=========+====================================+===============+ | Command | Description | Reference | +=========+====================================+===============+ | inspect | Discover Service AEP capabilities. | This document | +---------+------------------------------------+---------------+ | enroll | Register an Agent identity with a | This document | | | Service. | | +---------+------------------------------------+---------------+ | status | Query the Agent identity's current | This document | | | state. | | +---------+------------------------------------+---------------+ | grant | Issue a session credential. | This document | +---------+------------------------------------+---------------+ | revoke | Revoke session credentials. | This document | +---------+------------------------------------+---------------+ Table 8 19.5. AEP Binding Identifier Registry IANA is requested to create an "AEP Binding Identifiers" registry. The registration policy is Specification Required as defined by RFC 8126. Designated experts are requested to verify that new binding registrations define transport semantics, endpoint discovery, authentication carriage, payload encoding, error mapping, and security considerations. Each entry contains: Kavian Expires 29 December 2026 [Page 22] Internet-Draft AEP June 2026 +====================+=================================+ | Field | Description | +====================+=================================+ | Binding Identifier | Lowercase wire identifier. | +--------------------+---------------------------------+ | Description | Short binding description. | +--------------------+---------------------------------+ | Reference | Stable specification reference. | +--------------------+---------------------------------+ Table 9 Initial entries are: +====================+================================+===========+ | Binding Identifier | Description | Reference | +====================+================================+===========+ | http | HTTP binding for AEP commands. | This | | | | document | +--------------------+--------------------------------+-----------+ Table 10 19.6. AEP Extension Identifier Registry IANA is requested to create an "AEP Extension Identifiers" registry. The registration policy is Specification Required as defined by RFC 8126. Designated experts are requested to verify that new extension registrations define the extension identifier, discovery behavior, protocol fields or commands added by the extension, error behavior, and security and privacy considerations. Each entry contains: +======================+=========================================+ | Field | Description | +======================+=========================================+ | Extension Identifier | Absolute URI identifying the extension. | +----------------------+-----------------------------------------+ | Description | Short extension description. | +----------------------+-----------------------------------------+ | Reference | Stable specification reference. | +----------------------+-----------------------------------------+ Table 11 This document creates the registry but does not register concrete extensions. Kavian Expires 29 December 2026 [Page 23] Internet-Draft AEP June 2026 19.7. AEP Error Code Registry IANA is requested to create an "AEP Error Codes" registry. The registration policy is Specification Required as defined by RFC 8126. Designated experts are requested to verify that new error codes are binding-independent, use lower_snake_case, avoid exposing identity- enumeration detail, and define default HTTP status mapping and remediation behavior. Each entry contains: +=============+========================================+ | Field | Description | +=============+========================================+ | Code | Lowercase lower_snake_case error code. | +-------------+----------------------------------------+ | HTTP Status | Default HTTP status code. | +-------------+----------------------------------------+ | Description | Short error description. | +-------------+----------------------------------------+ | Reference | Stable specification reference. | +-------------+----------------------------------------+ Table 12 Initial entries are: +========================+========+=====================+===========+ | Code | HTTP | Description | Reference | | | Status | | | +========================+========+=====================+===========+ | enrollment_failed | 400 | Generic | This | | | | enrollment | document | | | | failure. | | +------------------------+--------+---------------------+-----------+ | invalid_request | 400 | Malformed or | This | | | | invalid request. | document | +------------------------+--------+---------------------+-----------+ | not_recognized | 401 | Anti-enumeration | This | | | | recognition | document | | | | failure. | | +------------------------+--------+---------------------+-----------+ | identity_suspended | 403 | Recognized | This | | | | identity is | document | | | | suspended. | | +------------------------+--------+---------------------+-----------+ | identity_terminated | 403 | Recognized | This | | | | identity is | document | Kavian Expires 29 December 2026 [Page 24] Internet-Draft AEP June 2026 | | | terminated. | | +------------------------+--------+---------------------+-----------+ | identity_unavailable | 403 | Recognized | This | | | | identity is | document | | | | temporarily | | | | | unavailable. | | +------------------------+--------+---------------------+-----------+ | requirements_unmet | 422 | Required claims | This | | | | are missing or | document | | | | invalid. | | +------------------------+--------+---------------------+-----------+ | verification_pending | 403 | Verification has | This | | | | not completed. | document | +------------------------+--------+---------------------+-----------+ | verification_timeout | 422 | Verification did | This | | | | not complete in | document | | | | time. | | +------------------------+--------+---------------------+-----------+ | rate_limited | 429 | Rate limit | This | | | | exceeded. | document | +------------------------+--------+---------------------+-----------+ | unsupported_grant_type | 400 | Unsupported | This | | | | Grant or Revoke | document | | | | grant type. | | +------------------------+--------+---------------------+-----------+ | idempotency_conflict | 409 | Idempotency key | This | | | | reused with a | document | | | | different | | | | | request body. | | +------------------------+--------+---------------------+-----------+ Table 13 19.8. AEP Grant Type Registry IANA is requested to create an "AEP Grant Types" registry. The registration policy is Specification Required as defined by RFC 8126. Designated experts are requested to verify that new grant type registrations define the Grant request fields, Grant response shape, credential presentation syntax, expiry semantics, Revoke behavior, and security considerations for credential storage and leakage. Each entry contains: Kavian Expires 29 December 2026 [Page 25] Internet-Draft AEP June 2026 +=============+=================================+ | Field | Description | +=============+=================================+ | Grant Type | Lowercase wire identifier. | +-------------+---------------------------------+ | Description | Short credential description. | +-------------+---------------------------------+ | Reference | Stable specification reference. | +-------------+---------------------------------+ Table 14 This document creates the registry but does not register concrete grant types. OAuth Bearer, API-key, and Basic session credentials are defined by separate documents. 20. Security Considerations Network use of the HTTP binding defined by this document requires TLS 1.3 or later. Plaintext HTTP is out of scope. Client assertions are replay resistant only when Services validate the full chain: aud, op, jti, iat, and exp. aud binds the assertion to the Service DID. op binds the assertion to a command. jti prevents in-window duplicate use. iat and exp bound the usable time window. Services that skip any of these checks weaken the authentication model. Services SHOULD keep assertion lifetimes short. This document sets a maximum validity interval of 300 seconds. Services MAY enforce a shorter maximum. The did:web method relies on the HTTPS origin that publishes the DID document. A Service that accepts an Agent's did:web identity trusts the corresponding web origin to publish the correct verification method. Services SHOULD cache DID documents for operational stability but MUST ensure that cache lifetimes do not prevent timely key replacement after compromise. The core.signing_algorithms advertisement is security relevant. Services MUST NOT advertise algorithms they do not intend to accept, and MUST NOT accept algorithms that were not advertised. Agents MUST NOT use none or symmetric JOSE algorithms for Agent identity assertions. Implementations SHOULD follow JWT best current practices [RFC8725]. Kavian Expires 29 December 2026 [Page 26] Internet-Draft AEP June 2026 Authentication failures are an enumeration risk. Services MUST collapse recognition failures to not_recognized and MUST shape timing so attackers cannot distinguish an unknown Agent, a bad signature, a wrong audience, a wrong operation, a replay, an expired assertion, or an archived identity. Grant issues session credentials that may be bearer credentials depending on the concrete session-credential document. Services and Agents MUST treat returned credentials as secrets. Concrete session- credential documents MUST define credential lifetime, presentation, storage guidance, and revocation semantics. Revoke MUST be available for every advertised grant type. If a session credential is stolen, an attacker may impersonate the Agent until the credential expires or is revoked. Agents that suspect compromise can authenticate with the baseline client assertion and invoke Revoke for the affected grant type. Services SHOULD rate-limit Inspect, Enroll, Grant, Revoke, and Status to reduce probing and credential-issuance abuse. Rate limits MUST NOT create distinguishable recognition errors that defeat the anti- enumeration rules above. 21. Privacy Considerations AEP exposes Agent identity and claims to Services. Agents and Services should minimize disclosure by using the Inspect document as the negotiation surface: Services list required, preferred, and optional claims; Agents provide the minimum set needed for the intended interaction. Services SHOULD keep claims.required limited to data required for enrollment or legal operation. Over-declaring required claims increases privacy risk and reduces interoperability. Agents SHOULD avoid sending claims absent from claims.required, claims.preferred, or claims.optional. Services MUST ignore unknown claims unless local policy requires rejection. A did:web Agent identity can be correlatable if the same DID is reused across Services. Platforms or Agent operators that require unlinkability SHOULD use a distinct did:web URI and signing key per Service enrollment. The URI path component SHOULD be opaque and SHOULD NOT reveal the Agent's master identity, account identifier, or target Service. Kavian Expires 29 December 2026 [Page 27] Internet-Draft AEP June 2026 Services SHOULD maintain a Service-local pairwise identifier for enrolled Agents rather than using the Agent DID as the primary internal record key across all contexts. Such identifiers SHOULD be opaque and MUST NOT be disclosed as cross-Service correlators. Platform-hosted Agent identities introduce Platform-level visibility: the Platform can observe or reconstruct which Services an Agent enrolls with. This document does not prevent that visibility. Agents with stronger privacy requirements should account for the Platform trust relationship before using a Platform-hosted did:web identity. Session credentials can become correlation handles when reused outside the issuing Service or logged by intermediaries. Concrete session-credential documents MUST define presentation rules that avoid unnecessary disclosure and MUST prohibit logging raw credential values. Inspect documents may disclose Service policy and capability information to unauthenticated readers. Services SHOULD avoid publishing sensitive operational details in Inspect beyond what Agents need for interoperability. 22. References 22.1. Normative References [DID-WEB] W3C Credentials Community Group, "The did:web Method Specification", n.d., . [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, . [RFC3339] Klyne, G. and C. Newman, "Date and Time on the Internet: Timestamps", RFC 3339, DOI 10.17487/RFC3339, July 2002, . [RFC5234] Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax Specifications: ABNF", STD 68, RFC 5234, DOI 10.17487/RFC5234, January 2008, . Kavian Expires 29 December 2026 [Page 28] Internet-Draft AEP June 2026 [RFC6839] Hansen, T. and A. Melnikov, "Additional Media Type Structured Syntax Suffixes", RFC 6839, DOI 10.17487/RFC6839, January 2013, . [RFC7515] Jones, M., Bradley, J., and N. Sakimura, "JSON Web Signature (JWS)", RFC 7515, DOI 10.17487/RFC7515, May 2015, . [RFC7518] Jones, M., "JSON Web Algorithms (JWA)", RFC 7518, DOI 10.17487/RFC7518, May 2015, . [RFC7519] Jones, M., Bradley, J., and N. Sakimura, "JSON Web Token (JWT)", RFC 7519, DOI 10.17487/RFC7519, May 2015, . [RFC8037] Liusvaara, I., "CFRG Elliptic Curve Diffie-Hellman (ECDH) and Signatures in JSON Object Signing and Encryption (JOSE)", RFC 8037, DOI 10.17487/RFC8037, January 2017, . [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, . [RFC8259] Bray, T., Ed., "The JavaScript Object Notation (JSON) Data Interchange Format", STD 90, RFC 8259, DOI 10.17487/RFC8259, December 2017, . [RFC8446] Rescorla, E., "The Transport Layer Security (TLS) Protocol Version 1.3", RFC 8446, DOI 10.17487/RFC8446, August 2018, . [RFC8615] Nottingham, M., "Well-Known Uniform Resource Identifiers (URIs)", RFC 8615, DOI 10.17487/RFC8615, May 2019, . [RFC9110] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., "HTTP Semantics", STD 97, RFC 9110, DOI 10.17487/RFC9110, June 2022, . [RFC9112] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., "HTTP/1.1", STD 99, RFC 9112, DOI 10.17487/RFC9112, June 2022, . Kavian Expires 29 December 2026 [Page 29] Internet-Draft AEP June 2026 [RFC9113] Thomson, M., Ed. and C. Benfield, Ed., "HTTP/2", RFC 9113, DOI 10.17487/RFC9113, June 2022, . [RFC9114] Bishop, M., Ed., "HTTP/3", RFC 9114, DOI 10.17487/RFC9114, June 2022, . [RFC9457] Nottingham, M., Wilde, E., and S. Dalal, "Problem Details for HTTP APIs", RFC 9457, DOI 10.17487/RFC9457, July 2023, . 22.2. Informative References [RFC8126] Cotton, M., Leiba, B., and T. Narten, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 8126, DOI 10.17487/RFC8126, June 2017, . [RFC8725] Sheffer, Y., Hardt, D., and M. Jones, "JSON Web Token Best Current Practices", BCP 225, RFC 8725, DOI 10.17487/RFC8725, February 2020, . Author's Address N. Kavian Jarwin, Inc. (InFlow) Email: nas@inflowpay.ai Kavian Expires 29 December 2026 [Page 30]