Internet-Draft HTTP Message Signatures for Bots August 2026
Meunier & Major Expires 7 February 2027 [Page]
Workgroup:
Web Bot Auth
Internet-Draft:
draft-meunier-webbotauth-httpsig-protocol-01
Published:
Intended Status:
Standards Track
Expires:
Authors:
T. Meunier
Cloudflare
S. Major
Google

HTTP Message Signatures for automated traffic

Abstract

This document describes a protocol for identifying automated traffic using [HTTP-MESSAGE-SIGNATURES]. The goal is to allow automated HTTP clients to cryptographically sign outbound requests, allowing HTTP servers to verify their identity with confidence.

It defines the Signature-Agent header field for in-band key discovery, a key directory format based on JWKS, and a well-known URI at which that directory is served.

About This Document

This note is to be removed before publishing as an RFC.

The latest revision of this draft can be found at https://thibmeu.github.io/http-message-signatures-directory/draft-meunier-webbotauth-httpsig-protocol.html. Status information for this document may be found at https://datatracker.ietf.org/doc/draft-meunier-webbotauth-httpsig-protocol/.

Discussion of this document takes place on the Web Bot Auth Working Group mailing list (mailto:web-bot-auth@ietf.org), which is archived at https://mailarchive.ietf.org/arch/browse/web-bot-auth/. Subscribe at https://www.ietf.org/mailman/listinfo/web-bot-auth/.

Source for this draft and an issue tracker can be found at https://github.com/thibmeu/http-message-signatures-directory.

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 7 February 2027.

Table of Contents

1. Introduction

Agents are increasingly used in business and user workflows, including AI assistants, search indexing, content aggregation, and automated testing. These agents need to reliably identify themselves to origins for several reasons:

  1. Regulatory compliance requiring transparency of automated systems

  2. Origin resource management and access control

  3. Protection against impersonation

  4. Service level differentiation between human and automated traffic

Current identification methods such as IP allowlisting, User-Agent strings, or shared API keys have significant limitations in security, scalability, and manageability. This document defines a protocol enabling agents to cryptographically identify themselves using [HTTP-MESSAGE-SIGNATURES]. It proposes that every request from bots be signed by a private key owned by its provider. This way, every origin can validate the service identifier. Section 4 defines what that identifier is and what validation it establishes.

2. Motivation

There is an increase in agent traffic on the Internet. Many agents choose to identify their traffic today via IP Address lists and/or unique User-Agents. This is often done to demonstrate trust and safety claims, support allowlisting/denylisting the traffic in a granular manor, and enable sites to monitor and rate limit per agent operator. However, these mechanisms have drawbacks:

  1. User-Agent, when used alone, can be spoofed meaning anyone may attempt to act as that agent. It is also overloaded - an agent may be using Chromium and wish to present itself as such to ensure rendering works, yet it still wants to differentiate its traffic to the site.

  2. IP blocks alone can present a confusing story. IPs on cloud plaforms have layers of ownership - the platform owns the IP and registers it in their published IP blocks, only to be re-published by the agent with little to bind the publication to the actual service provider that may be renting infra. Purchasing dedicated IP blocks is expensive, time consuming, and requires significant specialist knowledge to set up. These IP blocks may have prior reputation history that needs to be carefully inspected and managed before purchase and use.

  3. An agent may go to every website on the Internet and share a secret with them like a Bearer from [OAUTH-BEARER]. This is impractical to scale for any agent beyond select partnerships, and insecure, as key rotation is challenging and becomes less secure as the consumers scale.

Using well-established cryptography, we can instead define a simple and secure mechanism that empowers small and large agents to share their identity.

2.1. Objectives and constraints

This protocol has two objectives:

  1. Continuity of bot trust, so that an origin can tell it is dealing with the same party it dealt with before.

  2. Optional binding to another anchor, such as a domain.

It works under two constraints:

  1. Preserve the simplicity of usage for bots, and the simplicity of action for websites.

  2. Require no pre-established relationship between the two.

The second constraint is what rules out shared secrets and per-site onboarding. The first is a statement about operational cost on both ends: a site today greps its logs for an IP address and a User-Agent, and with this protocol it greps for a handle it can verify.

2.2. HTTP layer choice

This protocol operates solely at the HTTP layer. It allows signatures to be generated and verified without modifying the transport layer or TLS stack. It enables flexible deployment across proxies, gateways, and origin servers, and aligns with existing tooling and infrastructure that already inspect and manipulate HTTP headers.

Because the signature is embedded in the request itself, it travels with the message through intermediaries, preserving end-to-end verifiability even when requests are forwarded or transformed within the HTTP layer.

3. Conventions and Definitions

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.

The following terms are used throughout this document:

User

An entity initiating requests through an agent. May be a human operator or another system.

Agent

An orchestrated user agent (e.g. Chromium, CURL). It implements the HTTP protocol and constructs valid HTTP requests with [HTTP-MESSAGE-SIGNATURES] signatures.

Origin

An HTTP server receiving signed requests that implements the HTTP protocol and verifies [HTTP-MESSAGE-SIGNATURES] signatures. It acts as a verifier of the signature as defined by [HTTP-MESSAGE-SIGNATURES].

4. Identifiers and Trust Model

This section defines the identifiers produced by this protocol and what a verifier can conclude from a valid signature.

4.1. The Signature-Agent URL is the identifier

An Agent identifies itself with the HTTPS URL it publishes its keys at, carried in Signature-Agent (Section 5.2.1). A verifier resolves that member value (Section 5.5) and checks the signature against the keys it returns. The identifier is the URL the verifier fetched, which for a directory member is the well-known URI rather than the value the client sent. What the verifier ends up with is a pair: that URL, and a key the URL provides. Origins can log, rate limit, allowlist, or block the URL the way they do IP addresses and User-Agent today.

The URL on its own carries nothing. A client picks the value it sends, so an unresolved Signature-Agent is a claim rather than an identity. It becomes an identifier once the verifier fetches it and finds that it provides a key that verifies the request (Section 4.4). Until then, verifiers MUST NOT attach policy to it.

A valid signature over a resolved URL proves that the request came from a holder of a key that URL publishes, and that requests with the same URL come from holders of keys that URL publishes. Section 5.2.3 bounds reuse. It says nothing about who operates the Agent, whether the Agent is benign, or whether the request is authorized. Those are origin policy.

Nothing stops an Agent from abandoning a URL and standing up another one, and the protocol does not try to prevent this. It targets honest clients that want to be recognised across requests.

4.2. Rotation

Because the identifier is the URL and not the key, an Agent can rotate keys without losing continuity. It publishes the new key alongside the old one, then drops the old one (Section 5.5.2). The URL does not change, so a verifier that recognised it before still recognises it after. No name and no third party are involved.

keyid selects which key verifies a given request. Verifiers cannot use it to carry continuity across a rotation, as that value is derived from the key material.

[SIGNATURE-KEY] takes a different approach, where a long-lived key signs short-lived delegated keys. Deployments MAY use it. This document does not define rotation that way.

4.3. When no URL is sent

Signature-Agent is RECOMMENDED but not required. Without it, a verifier has only the key, and the identifier is the keyid thumbprint defined in Section 5.2. Verification still works, provided the verifier already holds that key.

This mode has no rotation. A new key is a new identifier, and the verifier has no way to connect the two.

4.4. What the URL endorses

Resolving a Signature-Agent URL over TLS establishes that the host named in the URL served this key set at fetch time. Whoever controls that URL says this key signs for it. That is what makes the URL usable as an identifier, and all it gives you. It does not say that the operator of that URL is honest, or that is is the same party everyone knows about.

What matters is the association between a URL and the keys published there. A verifier that already holds the keys does not need to fetch it. A verifier MUST NOT attribute a request to a Signature-Agent URL unless it made this ssociation. This can be either by resolving the URL itself, at request time or ahead of it, or from Section 5.5.3. Verifiers may refetch a URL to handle up key additions and removals, bounded by Appendix C.4.

Where a verifier obtains the same pair from more than one source, the newer pair wins, including when it omits a key that older resolution included. Pairs are ordered by when they were produced, not when the verifier obtained them: the created parameter for a directory response signature (Appendix B), and the time of the fetch for a directory the verifier resolved itself.

4.5. Binding a key to a Web origin

A well-known URL is a special case of the above. When a Signature-Agent value resolves through the directory type (Section 5.5), the identifier is still the URL, but that URL now names a domain rather than an arbitrary path on one. [WELLKNOWN-URI] reserves the path, so the domain operator stands behind the key set.

In practice, this is meant to allow additional information to be carried against a name. That mechanism lives in Appendix B. A verifier that wants to use this case may also recognise the shape of the URL and apply those checks itself.

4.6. Out of scope

This protocol does not authenticate human users, does not provide anonymous authentication, and does not define authorization or delegation. It does not define how trust is accrued, held, or exchanged, and it defines no mechanism for one origin to convey an opinion about an Agent to another. See Section 7.

A client has a choice whether to sign its requests, and an origin has a choice how it treats signed and unsigned requests. Multiple factors could influence either decision, but the decisions themselves are outside the scope of this document.

5. Protocol Overview

Exchange Cryptographic material User Request Agent Origin Request + Signature Response Response

A User initiates an action requiring the Agent to perform an HTTP request. The Agent constructs the request, generates a signature using its signing key, and includes it in the request as defined in Section 3.1 of [HTTP-MESSAGE-SIGNATURES] along with the Signature-Agent header for discovery of its verification key. Upon receiving the request, the Origin ensures it has the verification key for the Agent, validates the signature, and processes the request if the signature is valid.

5.1. Deployment Models

Signature verification can be performed either directly by origins or delegated to a fronting proxy. Direct verification by origins provides simplicity and control. Proxy verification offloads processing and enables shared caching across multiple origins. The choice depends on traffic volume and operational requirements.

5.2. Generating HTTP Message Signature

[HTTP-MESSAGE-SIGNATURES] defines components to be signed.

Agents MUST include at least one of the following components:

@authority

as defined in Section 2.2.3 of [HTTP-MESSAGE-SIGNATURES]

@target-uri

as defined in Section 2.2.2 of [HTTP-MESSAGE-SIGNATURES]

Agents MUST include the following @signature-params as defined in Section 2.3 of [HTTP-MESSAGE-SIGNATURES]

created

as defined in Section 2.3 of [HTTP-MESSAGE-SIGNATURES]

expires

as defined in Section 2.3 of [HTTP-MESSAGE-SIGNATURES]

keyid

MUST be a base64url JWK SHA-256 Thumbprint as defined in Section 3.2 of [JWK-THUMBPRINT] for RSA and EC, and in Appendix A.3 of [JWK-OKP] for ed25519.

tag

MUST be web-bot-auth

The signing key is available to the agent at request time. Algorithms should be registered with IANA as part of HTTP Message Signatures Algorithm registry.

The creation of the signature is defined in Section 3.1 of [HTTP-MESSAGE-SIGNATURES].

It is RECOMMENDED that expiry be no more than 24 hours.

The components above bind the signature to an authority, not to a request. A signature covering @authority alone verifies against any method, path, or body sent to that authority until it expires, so anyone who observes one request can reuse it against the same origin until then. expires bounds how long that lasts; the covered components bound what it reaches. Agents that want to narrow it SHOULD also cover @method, and either @path or @target-uri, as Appendix D.2 does. A signer that omits them remains conformant. Appendix C.7 covers what that costs on the wire.

No component covers the body. An Agent that needs one MUST send and cover Content-Digest [DIGEST-FIELDS]. This document does not require it. Most automated traffic is GET, and a mandatory digest would force every Agent to buffer request bodies it would otherwise stream.

5.2.1. Signature-Agent

Signature-Agent is a Dictionary Structured Header as defined in Section 3.2 of [STRUCTURED-HEADERS]. Its member values MUST be String Items that contain a [URI], whose scheme MUST be https. If dictionary values are not valid URI-references, the entire header field MAY be ignored.

Each member carries a type parameter, a Token Item as defined in Section 3.3.4 of [STRUCTURED-HEADERS], naming the discovery mechanism that resolves the value to key material. Section 5.5 defines the types. When type is absent, its value is directory. A verifier that does not support a type value MUST ignore that member, and MUST NOT infer the mechanism from the URI path, media type, or response body.

Earlier versions of this protocol defined Signature-Agent as a bare String, and deployments still send it (Appendix E.1.3). A verifier MAY accept that form and treat it as a dictionary with a single member whose key is the label of the signature covering it. Signers MUST send the dictionary form. The two are distinguishable on the wire: a String Item begins with a double quote " while a Dictionary member key does not.

It is RECOMMENDED that the Agent sends requests with Signature-Agent header, as described in Section 5.2.5. If the header is to be sent, one of its members MUST be signed as a component as defined in Section 2.1 of [HTTP-MESSAGE-SIGNATURES]. The Signature-Agent member identifies where candidate key material can be found. The key used to verify the signature is selected by the keyid parameter of the corresponding Signature-Input member.

This results in the following components to be signed

("@authority" "signature-agent";key="sig1")

It is RECOMMENDED that the key matches the signature label.

5.2.2. Multiple signatures

A request MAY contain more than one Web Bot Auth signature. Each signature is identified by its HTTP Message Signatures label. When Signature-Agent is present, each signer SHOULD provide a Signature-Agent member for its label.

A signer MAY cover members from another signature label, which preserves evidence that another signer contributed to the request. A signer that covers "signature";key=X MUST also cover "signature-input";key=X, and MUST cover every component identifier listed in "signature-input";key=X.

A signature value on its own does not identify the message it was computed over, which is why Section 7.3.7 of [HTTP-MESSAGE-SIGNATURES] recommends against signing one. Covering signature-input is not sufficient: it lists component identifiers, whose values resolve against whatever message the verifier holds. An outer signature that named those identifiers without covering them would still verify after the whole header set was lifted onto a different message, the ambiguity Section 7.3.7 of [HTTP-MESSAGE-SIGNATURES] describes. Covering the union addresses this: the outer signer commits to a message on which the inner signature is checkable, under which key, and over which validity window.

A signer that cannot cover one of those components, because it changed the value the inner signature was computed over, MUST NOT cover the inner signature member. It signs the request on its own terms, and the inner signature is left untouched.

Verifiers MUST validate each signature independently against its own covered components and its own key. An outer signature that covers an inner one is evidence that those bytes, over that set of components, were present. It does not make the inner signature valid, and it does not express authorization, delegation, or consent. Those meanings are deployment policy, or are carried in separately signed fields.

5.2.3. Anti-replay

Origins MAY want to prevent signatures from being spoofed or used multiple times by bad actors and thus require a nonce to be added to the @signature-params. This is described in Section 7.2.2 of [HTTP-MESSAGE-SIGNATURES].

Agents SHOULD extend @signature-parameters defined in Section 5.2 as follows:

nonce

base64url encoded random byte array. It is RECOMMENDED to use a 64-byte array.

Client MUST ensure that this nonce is unique for the validity window of the signature, as defined by created and expires attributes.

5.2.4. Additional headers

Agents MAY include additional components, such as specific HTTP headers, in the signature. This can be prompted by the origin requesting additional headers, as described in Section 5.3, or initiated by the agent to provide more information within the signature scope. For example, an agent might include an HTTP header expressing its intent and sign it.

Origins MAY ignore certain headers at their own discretion, and request a new signature, as described in Section 5.3.

5.2.5. Sending a request

An Agent SHOULD send a request with the signature generated above. Updating the overview diagram, the flow looks as follow.

Exchange Cryptographic material Agent Origin GET /path/to/resource Signature: sig=abc== Signature-Input: sig=("@authority" "signature-agent";key="sig");\ created=1700000000;\ expires=1700011111;\ keyid="ba3e64==";\ tag="web-bot-auth" Signature-Agent: sig="https://signer.example.com"

The Agent SHOULD send requests with two headers

  1. Signature defined in Section 5.2

  2. Signature-Input defined in Section 5.2

As described in Section 5.2.1, it is RECOMMENDED that the Agent also send the Signature-Agent header. Without it the Agent is identified by its key alone, with the consequences described in Section 4.3.

5.3. Requesting a Message signature

Section 5 of [HTTP-MESSAGE-SIGNATURES] defines the Accept-Signature field which can be used to request a Message Signature from a client by an origin. An Origin MAY choose to request signatures from clients that did not initially provide them. If requesting, Origins MUST use the same parameters as those defined by the Section 5.2. The status code SHOULD be 403 Forbidden as defined in Section 15.5.4 of [HTTP].

Origin MAY request a new signature with tag "web-bot-auth" even if a nonce is provided, for example if it believes the nonce is a replay, or if it doesn't store nonces and thus requests new signatures every time. The status code SHOULD be 429 Too Many Requests as defined in Section 4 of [HTTP-MORE-STATUS-CODE].

5.4. Validating Message signature

Upon receiving an HTTP request, the origin has to verify the signature. The algorithm is provided in Section 3.2 of [HTTP-MESSAGE-SIGNATURES]. Similar to a regular User-Agent check, this happens at the HTTP layer, once headers are received.

Additional requirements are placed on this validation:

  • During step 1 to 3 included, if the Origin fails to parse the provided Signature, Signature-Input, or Signature-Agent headers, it MAY respond with status code 400 Bad Request as defined in Section 15.5.1 of [HTTP].

  • During step 4, the Origin MAY discard signatures for which the tag is not set to web-bot-auth.

  • During step 5, the Origin MAY discard signatures for which it does not know the keyid for the Signature-Agent URL the signature covers.

  • During step 5, if the keyid is not known for that URL, the Origin MAY fetch key material as indicated by the Signature-Agent header defined in Section 5.2.1. Fetching key material affects only whether verification is possible, not what a valid signature means (Section 4.4).

Key lookup MUST be keyed on the (URL, key) pair, not on the key alone. A verifier that indexes by keyid alone will verify a request as coming from one URL that provides a key it learned from another, and attribute that request to the URL the client asserted. The party whose URL is asserted cannot detect or stop this: its own directory is never fetched, so no rotation or removal has any effect.

Origin MAY require the nonce to satisfy certain constraints: be globally unique using a global nonce store, be unique to a specific location or time window using a local cache, or no constraint at all.

5.5. Key Distribution and Discovery

This section describes how a verifier resolves a Signature-Agent URL to key material. Section 4.4 covers what the fetch does and does not establish.

The reference for discovery is an HTTPS URL, carried in a Signature-Agent member as defined in Section 5.2.1. The member's type parameter names how the URL resolves to key material. This protocol defines three types:

directory

The member value MUST be the ASCII serialization of an origin as defined in Section 6.2 of [ORIGIN], and a verifier MUST ignore a member carrying anything else (an empty path / MAY be accepted though). Resolve the HTTP Message Signatures Directory at the well-known URI registered in Section 8.1, at that origin. This is the default when no type parameter is present.

jwks_uri

Resolve the member value as a direct JWK Set URI.

cimd

Resolve the member value as a Client ID Metadata Document [CIMD] URI. The document then provides key material through jwks or jwks_uri.

All three types produce an identifier: the URL the verifier resolved, with any query and fragment discarded. For directory that is the well-known URI, one per origin. For jwks_uri and cimd it is the member value; the verifier fetches that value as sent, so the query is dropped from the identifier and not from the request. Otherwise one key set would yield an identifier per spelling, and an Agent could mint them at will.

Identifiers are compared after normalization as described in Section 6.2.2 of [URI] and Section 6.2.3 of [URI]. Two identifiers are the same when their normalized forms are equal octet for octet.

The types differ in what additional information the verifier learns from the URL. TLS authenticates the host but not the path, and nothing reserves the jwks_uri or cimd path to the host's operator. The well-known URI is reserved, so directory additionally names a domain (Section 4.5).

For all types, the key is selected using the keyid parameter in Signature-Input.

Note: when a JWK set is served at the well-known URI registered in Section 8.1, JWK MAY carry a kid. In this case, it MUST be set to the thumbprint defined in Section 5.2, so a verifier selects a key by matching keyid against kid. Deriving kid from the key material keeps it globally unique and lets a verifier check the directory's own labelling rather than trusting it.

jwks_uri and cimd resolve to key sets that may serve other consumers, where kid is an operator-chosen label. A verifier that cannot match keyid against kid there computes thumbprints instead.

Signature-Agent: sig1="https://signature-agent.test"
Signature-Agent: sig1="https://signature-agent.test/jwks.json";type=jwks_uri
Signature-Agent: sig1="https://signature-agent.test/card";type=cimd

5.5.1. Directory format

All three types resolve to a JSON Web Key Set (JWKS) as defined in Section 5 of [JWK]. The alg parameter is restricted to algorithms registered in the HTTP Signature Algorithms section of [HTTP-MESSAGE-SIGNATURES-IANA].

The directory MUST be served over HTTPS. A directory served at the well-known URI registered in Section 8.1 MUST be served with media type application/http-message-signatures-directory+json.

A verifier SHOULD validate the directory format and reject malformed entries.

GET /.well-known/http-message-signatures-directory HTTP/1.1
Host: example.com
Accept: application/http-message-signatures-directory+json

HTTP/1.1 200 OK
Content-Type: application/http-message-signatures-directory+json
Cache-Control: max-age=86400
{
  "keys": [{
    "kty": "OKP",
    "crv": "Ed25519",
    "kid": "NFcWBst6DXG-N35nHdzMrioWntdzNZghQSkjHNMMSjw",
    "x": "JrQLj5P_89iXES9-vFgrIy29clF9CC_oPPsw3c5D0bs",
    "use": "sig",
    "nbf": 1712793600,
    "exp": 1715385600
  }]
}

5.5.2. Key rotation

Directory operators SHOULD rotate keys by publishing the old and the new key together, then removing the old one:

  1. Add the new key to the directory before its intended use date

  2. Continue to include the old key until its expiration date

  3. Remove expired keys from the directory

Removing a key from the directory deactivates it. Verifiers stop accepting it once their cached copy expires, so the directory's cache lifetime bounds how long a removed key keeps verifying. Verifiers SHOULD cache the directory contents and refresh upon expiration, as described in Appendix C.4.

It is not a revocation mechanism, and this document does not define any.

5.5.3. Redistributed key material

IP addresses and user-agent have been aggregated and distributed via lists. This section says what a verifier may conclude from key material it did not fetch itself. Defining a format for redistribution is out of scope.

A verifier MUST NOT attribute a request to a Signature-Agent URL on the basis of redistributed key material unless it carries, for the key in question, a valid directory response signature as described in Appendix B whose expires has not passed. Without that proof the material stays usable for verifying signatures, but it carries no URL, so the identifier falls back to the key thumbprint (Section 4.3).

The main requirement is to terminate the TLS connection. A verifier polling a directory on its own schedule is resolving it. So is a control plane polling on behalf of the verifiers it serves. None of these options constitute redistribution. Nor is a list that names directory URLs rather than embedding keys. For instance, [REGISTRY] works that way, and the verifier still resolves them.

5.5.4. Signature-Key header

[SIGNATURE-KEY] defines a separate key discovery header for HTTP Message Signatures. Deployments MAY use it when they need that model. This protocol uses Signature-Agent as its default discovery mechanism.

5.6. Session considerations

Per-request signing and verification costs CPU; uncached key discovery adds latency. For high request rates, an origin can verify a request-specific signature once and issue a session credential for later requests. This can amortize asymmetric verification and reduce bytes, but adds the risks of token theft and replay.

A reused signature already has token semantics until expires. A session established from one extends that window past expires unless the credential is bounded to it: no longer-lived, and no wider in scope than the components the signature covered. Session establishment and binding are out of scope.

6. Security Considerations

6.1. Use of TLS

We reassess Section 7.1.2 of [HTTP-MESSAGE-SIGNATURES]. Clients SHOULD use TLS [RFC8446] (https) or equivalent transport security when making requests with Message signatures. Failing to do so exposes the Message signature to numerous attacks that could give attackers unintended access.

This include reverse proxy and their consideration presented in Section 6.7.

An origin SHOULD refuse Signature headers when communicated over an unsecured channel.

6.2. Performance Impact

Origins should account for the overhead of signature verification in their operations. A local cache of public keys reduces network requests and verification latency. The choice of signing algorithm impacts CPU requirements. Origins should monitor verification latency and set appropriate timeouts to maintain service levels under load. See Section 5.6: a session amortizes that cost by replacing verification with a bearer credential. Appendix C.7 covers the byte cost.

6.3. Nonce validation

Clients control the nonce. While Section 5.2.3 mandates that clients MUST provide a globally unique nonce, it is the origin's responsibility to enforce it.

Different validation policies have different performance and operational considerations. Global uniqueness requires a global nonce store. Some origins may find that their use case can tolerate sharding on location, timing, or other properties.

6.4. Key Compromise Response

This document defines no revocation. Removing a compromised key from the directory is the only remedy, and it takes effect at each verifier on its next refresh, so the key can keep verifying for as long as Section 5.5.2 allows. The protocol carries no channel back to verifiers, so an Agent cannot reach them sooner. Signature lifetimes (Section 5.2) are the only lever that acts faster.

Agents SHOULD remove a compromised key and publish a replacement immediately. Origins should support rapid key rotation and monitor for suspicious signature patterns.

6.5. Shared Secrets Considered Harmful

Implementations MUST NOT use shared HMAC defined in Section 3.3.3 of [HTTP-MESSAGE-SIGNATURES]. Shared secrets break non-repudiation and make auditing difficult. Each automated client SHOULD use a unique asymmetric keypair to ensure attribution, support key rotation, and enable effective rotation if needed.

6.6. Key Reuse Considered Harmful

Implementations SHOULD NOT reuse a signing key for different purposes. For example, if an agent implementor has two agents they want to differentiate, these should use distinct signing keys and signing key directories.

6.7. Reverse proxy consideration

An origin may be placed behind a reverse proxy, which means the proxy will see the Signature and Signature-Agent headers before the origin does. A proxy SHOULD NOT strip the Signature or Signature-Agent headers from requests.

A proxy SHOULD NOT replay signatures against other reverse proxies used by the origin, as this allows impersonation of the principal signature agent.

Origins MAY require a specific nonce policy to prevent such malicious behaviour and decide to validate the signature themselves. This has to be done in accordance with Section 6.3. For example, an origin could require a nonce derived from public information (such as the current date), mandate nonce chaining (where each nonce is the hash of the previous one), or provide its own nonce in an Accept-Signature response to challenge the agent.

Such policies MAY incur additional round-trip between the client and the origin to convey accept-signature header, or deployment specific exchanges.

6.7.1. Signature-Agent labeling

Section 7.2.5 of [HTTP-MESSAGE-SIGNATURES] allows an intermediary to relabel a signature, because the label of a Signature dictionary member is not part of the signature base. The key of a Signature-Agent member is different: when a signature covers "signature-agent";key="agent2", that key appears in the signature base, so changing it invalidates the signature. Only the holder of the signing key can produce a signature over the new member key.

An intermediary MUST NOT alter the key of a Signature-Agent member that is covered by a signature it is not able to recompute. Relabeling the Signature dictionary member remains permitted.

A signer acting as an intermediary on its own signature is not restricted by this, since it can sign the result.

6.8. Server-Side Request Forgery (SSRF)

As described in Section 5.5, verifiers may fetch key directories based on the value conveyed in Signature-Agent when included in a request. Since clients control the Signature-Agent header value, this introduces a risk of server-side request forgery (SSRF) attacks by malicious clients.

Verifiers SHOULD take appropriate precautions as follows:

Response size

a directory can be arbitrarily large. Verifiers SHOULD reject responses exceeding a defined byte limit after content decoding.

Key count

a JWKS with many keys forces O(n) key search. Verifiers SHOULD enforce a maximum key count.

Fetch latency

no timeout allows slowloris-style exhaustion. Verifiers SHOULD apply a wall-clock timeout to directory fetches.

Redirect chains

unbounded HTTP redirects can be used to amplify requests. Verifiers SHOULD limit redirect depth.

Network address ranges

no address filtering can target internal services. Verifiers SHOULD prevent directory fetches to private, loopback, and link-local address ranges.

Further recommendations can be found in the Open Worldwide Application Security Project (OWASP) SSRF Prevention Cheat Sheet [OWASP-SSRF].

6.9. Test and Demonstration Keys

Test keys, including the example keys in [HTTP-MESSAGE-SIGNATURES], MUST NOT be used in production. Verifiers SHOULD reject known test keys when they are detected in key directories or out-of-band configuration.

6.10. Static Signatures

Deployments MUST NOT treat a precomputed Web Bot Auth signature as a long-lived access credential. A reusable static signature has bearer-token semantics and can be replayed until the covered signature parameters, key, or verifier policy make it unusable.

Agents SHOULD generate signatures for the request being sent, with bounded created and expires values. Long expiration windows increase replay risk.

6.11. Discovery Failure

Resolving a Signature-Agent URL can fail in several ways: the name does not resolve, the connection or TLS handshake fails, the response is not a directory or contains no key matching keyid, or the fetch is refused by the verifier's own limits (Section 6.8). All have the same outcome for the request in hand. The verifier holds no association between that URL and the signing key, so under Section 4.4 it MUST NOT attribute the request to that URL. It may still verify the signature if it holds the key by other means, in which case the identifier is the thumbprint (Section 4.3); otherwise the request is unverified.

They differ in what they say about cached state, and verifiers MUST keep them apart. A directory that resolves and does not contain the key is evidence: it is newer than whatever the verifier holds, and under Section 4.4 replaces it. That is how a removed key stops verifying. A directory that fails to resolve is not evidence and MUST NOT evict a cached entry, or an operator's outage revokes its keys at every verifier at once.

A failed fetch says nothing about the signer. It does not prove the signer is malicious, and it does not make the request trusted. What an origin does with an unverified request is local policy, and treating it as a distinct outcome rather than as success or failure is discussed in Appendix C.1. Verifiers should also expect failures to be correlated: a single operator's directory going down takes out every request naming it at once, across every verifier whose cache expires in the same window.

6.12. Unsigned requests

Most HTTP requests carry no signature. A verifier that sees none has learned nothing about the sender: not that it is automated, not that it is human, not that it is evading anything. Absence of a signal is not evidence about the party that did not send it, in the same way that a failed fetch (Section 6.11) is not evidence about the signer.

What an origin does with a request it cannot attribute is its own decision, as it was before this protocol existed. This document neither requires an origin to treat unsigned requests differently nor gives it grounds to.

7. Privacy Considerations

7.1. Public Identity

This protocol assumes that automated clients identify themselves explicitly using digital signatures. The identity associated with a signing key is expected to be publicly discoverable for verification purposes. This reduces anonymity and allows receivers to associate requests with specific agents. If an agent wishes not to identify itself, this is not the right choice of protocol for it.

7.2. No Human Correlation

The key used for signing MUST NOT be tied to a specific human individual. Keys SHOULD represent a role, company, or automation identity (e.g., "news-aggregator- bot", "example-crawler-v1"). This avoids accidental exposure of personally identifiable information and prevents the misuse of keys for user tracking or profiling.

7.3. Minimizing Tracking Risks

To limit tracking risks, implementations SHOULD avoid long-lived, globally unique key identifiers unless strictly necessary. Key rotation SHOULD be supported, and clients SHOULD take care to avoid signing information that could be used to correlate activity across contexts, especially where sensitive user data is involved.

7.4. Directory content and access patterns

A key directory should only contain keys actively used for signing. Additional keys or metadata expose more about the signing service than verification requires. Verifiers fetching a directory also reveal something about their verification patterns, so directory servers should avoid logging personally identifiable information from directory requests.

8. IANA Considerations

This section contains considerations for IANA.

8.1. Well-Known 'http-message-signatures-directory' URI

This document updates the "Well-Known URIs" Registry [WellKnownURIs] with the following values.

Table 1: 'http-message-signatures-directory' Well-Known URI
URI Suffix Change Controller Reference Status Related information
http-message-signatures-directory IETF this document permanent None

8.2. Media Types

The following entries should be added to the IANA "media types" registry:

  • "application/http-message-signatures-directory+json"

The templates for these entries are listed below and the reference should be this RFC.

8.2.1. "application/http-message-signatures-directory+json" media type

Type name:

application

Subtype name:

http-message-signatures-directory

Required parameters:

N/A

Optional parameters:

N/A

Encoding considerations:

"binary"

Security considerations:

see Section 6

Interoperability considerations:

N/A

Published specification:

this specification

Applications that use this media type:

Services that implement the signer role for HTTP Message Signatures and verifiers that interact with the signer for the purpose of validating signatures.

Fragment identifier considerations:

N/A

Additional information:
Magic number(s):
N/A
Deprecated alias names for this type:
N/A
File extension(s):
N/A
Macintosh file type code(s):
N/A
Person and email address to contact for further information:

see Authors' Addresses section

Intended usage:

COMMON

Restrictions on usage:

N/A

Author:

see Authors' Addresses section

Change controller:

IETF

9. References

9.1. Normative References

[CIMD]
Parecki, A. and E. Smith, "OAuth Client ID Metadata Document", Work in Progress, Internet-Draft, draft-ietf-oauth-client-id-metadata-document-02, , <https://datatracker.ietf.org/doc/html/draft-ietf-oauth-client-id-metadata-document-02>.
[DIGEST-FIELDS]
Polli, R. and L. Pardue, "Digest Fields", RFC 9530, DOI 10.17487/RFC9530, , <https://www.rfc-editor.org/rfc/rfc9530>.
[HTTP]
Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., "HTTP Semantics", STD 97, RFC 9110, DOI 10.17487/RFC9110, , <https://www.rfc-editor.org/rfc/rfc9110>.
[HTTP-CACHE]
Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., "HTTP Caching", STD 98, RFC 9111, DOI 10.17487/RFC9111, , <https://www.rfc-editor.org/rfc/rfc9111>.
[HTTP-MESSAGE-SIGNATURES]
Backman, A., Ed., Richer, J., Ed., and M. Sporny, "HTTP Message Signatures", RFC 9421, DOI 10.17487/RFC9421, , <https://www.rfc-editor.org/rfc/rfc9421>.
[HTTP-MESSAGE-SIGNATURES-IANA]
"HTTP Message Signatures", n.d., <https://www.iana.org/assignments/http-message-signature/http-message-signature.xhtml>.
[HTTP-MORE-STATUS-CODE]
Nottingham, M. and R. Fielding, "Additional HTTP Status Codes", RFC 6585, DOI 10.17487/RFC6585, , <https://www.rfc-editor.org/rfc/rfc6585>.
[JWK]
Jones, M., "JSON Web Key (JWK)", RFC 7517, DOI 10.17487/RFC7517, , <https://www.rfc-editor.org/rfc/rfc7517>.
[JWK-OKP]
Liusvaara, I., "CFRG Elliptic Curve Diffie-Hellman (ECDH) and Signatures in JSON Object Signing and Encryption (JOSE)", RFC 8037, DOI 10.17487/RFC8037, , <https://www.rfc-editor.org/rfc/rfc8037>.
[JWK-THUMBPRINT]
Jones, M. and N. Sakimura, "JSON Web Key (JWK) Thumbprint", RFC 7638, DOI 10.17487/RFC7638, , <https://www.rfc-editor.org/rfc/rfc7638>.
[ORIGIN]
Barth, A., "The Web Origin Concept", RFC 6454, DOI 10.17487/RFC6454, , <https://www.rfc-editor.org/rfc/rfc6454>.
[RFC2119]
Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/rfc/rfc2119>.
[RFC8174]
Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, , <https://www.rfc-editor.org/rfc/rfc8174>.
[STRUCTURED-HEADERS]
Nottingham, M. and P. Kamp, "Structured Field Values for HTTP", RFC 9651, DOI 10.17487/RFC9651, , <https://www.rfc-editor.org/rfc/rfc9651>.
[URI]
Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform Resource Identifier (URI): Generic Syntax", STD 66, RFC 3986, DOI 10.17487/RFC3986, , <https://www.rfc-editor.org/rfc/rfc3986>.
[WellKnownURIs]
"Well-Known URIs", n.d., <https://www.iana.org/assignments/well-known-uris/well-known-uris.xhtml>.

9.2. Informative References

[HPACK]
Peon, R. and H. Ruellan, "HPACK: Header Compression for HTTP/2", RFC 7541, DOI 10.17487/RFC7541, , <https://www.rfc-editor.org/rfc/rfc7541>.
[HTTP-BEST-PRACTICES]
Nottingham, M., "Building Protocols with HTTP", BCP 56, RFC 9205, DOI 10.17487/RFC9205, , <https://www.rfc-editor.org/rfc/rfc9205>.
[OAUTH-BEARER]
Jones, M. and D. Hardt, "The OAuth 2.0 Authorization Framework: Bearer Token Usage", RFC 6750, DOI 10.17487/RFC6750, , <https://www.rfc-editor.org/rfc/rfc6750>.
[OWASP-SSRF]
"OWASP Server-Side Request Forgery Prevention Cheat Sheet", n.d., <https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html>.
[QPACK]
Krasic, C., Bishop, M., and A. Frindell, Ed., "QPACK: Field Compression for HTTP/3", RFC 9204, DOI 10.17487/RFC9204, , <https://www.rfc-editor.org/rfc/rfc9204>.
[REGISTRY]
Guerreiro, M., Kirazci, U., and T. Meunier, "Registry and Signature Agent card for Web bot auth", Work in Progress, Internet-Draft, draft-meunier-webbotauth-registry-03, , <https://datatracker.ietf.org/doc/html/draft-meunier-webbotauth-registry-03>.
[RFC8446]
Rescorla, E., "The Transport Layer Security (TLS) Protocol Version 1.3", RFC 8446, DOI 10.17487/RFC8446, , <https://www.rfc-editor.org/rfc/rfc8446>.
[SIGNATURE-KEY]
Hardt, D. and T. Meunier, "HTTP Signature Keys", Work in Progress, Internet-Draft, draft-hardt-httpbis-signature-key-08, , <https://datatracker.ietf.org/doc/html/draft-hardt-httpbis-signature-key-08>.
[USE-CASES]
Nottingham, M., "Use Cases for Authentication of Web Bots", Work in Progress, Internet-Draft, draft-nottingham-webbotauth-use-cases-02, , <https://datatracker.ietf.org/doc/html/draft-nottingham-webbotauth-use-cases-02>.
[WELLKNOWN-URI]
Nottingham, M., "Well-Known Uniform Resource Identifiers (URIs)", RFC 8615, DOI 10.17487/RFC8615, , <https://www.rfc-editor.org/rfc/rfc8615>.

Appendix A. Use cases and what they need

[USE-CASES] collects the use cases this group has discussed. Most are served by the URL alone. The table below records which ones need the domain binding in Appendix B, and why.

Table 2: Use cases and the identifier they need
Use case What the origin does Needs
Mitigating volumetric abuse Rate limit per URL URL
Controlling access by bots Set policy per URL URL
Providing different content to bots Recognise a given URL URL
Auditing bot behaviour Group logs by URL URL
Classifying traffic Correlate observed behaviour with a URL URL
IP address mobility and sharing Nothing: the signature does not depend on the IP URL
Robots.txt alignment Match the crawler against a name in the file Domain
Conveying contextual information Read signed headers alongside the identifier Domain

The last two are the pattern from Section 4.5. Both consume something held against a name rather than against the key: a robots.txt file names crawlers, and contextual assertions are only worth as much as the party making them. End-user authentication and anonymous authentication are out of scope.

Appendix B. Validating the domain binding

This appendix describes what a verifier checks when it wants the domain a key is published under, rather than the URL on its own. It applies to the directory type in Section 5.5. Verification, rotation, and continuity do not depend on any of it, and a verifier that only needs the URL as an identifier can skip the whole appendix.

Authority over the domain comes from the TLS connection to the directory. Nothing below adds to that.

B.1. Possession proof on the directory response

It is RECOMMENDED that a directory server construct and include one HTTP Message Signature per key with the response, as defined in [HTTP-MESSAGE-SIGNATURES]. Each key SHOULD be used to provide one signature. These signatures prove possession of the advertised keys and, by covering @authority, prevent the key set from being re-served under a different authority. This matters for a domain-bound identifier, where the verifier is about to consume information it holds against the name: it distinguishes a key set the key holders assembled from one that was copied.

Directory server MUST include the following covered components:

@authority

as defined in Section 2.2.3 of [HTTP-MESSAGE-SIGNATURES]. req flag defined in Section 2.4 of [HTTP-MESSAGE-SIGNATURES] MUST be set.

content-digest

as defined in [DIGEST-FIELDS].

Directory server MUST include the following @signature-params as defined in Section 2.3 of [HTTP-MESSAGE-SIGNATURES]

created

as defined in Section 2.3 of [HTTP-MESSAGE-SIGNATURES]

expires

as defined in Section 2.3 of [HTTP-MESSAGE-SIGNATURES]

Without them the signature is a permanent assertion that these keys were bound to this authority at some unstated time, of no use to a verifier consuming it through Section 5.5.3.

keyid

MUST be a base64url JWK SHA-256 Thumbprint as defined in Section 3.2 of [JWK-THUMBPRINT] for RSA and EC, and in Appendix A.3 of [JWK-OKP] for ed25519.

tag

MUST be http-message-signatures-directory

A verifier relying on the domain MUST validate these signatures using the keys provided by the directory, MUST validate the Content-Digest field against the response body, and MUST ignore keys that do not have a corresponding valid signature. A verifier MUST reject a directory response signature whose created is in the future, as it would a certificate that is not yet valid. Section 4.4 orders competing evidence by created, so a future-dated signature would outrank every later fetch.

B.2. What the binding attaches to

The binding is not exclusive. Several domains may publish the same key, and the binding attaches to the pair the verifier validated, not to the key on its own. A verifier that recognises a key under one domain has learned nothing about the same key served under another.

Appendix C. Deployment Guidance

This appendix is operational guidance. It does not define new protocol requirements.

C.1. Verifier Outcomes

Verifiers should keep three outcomes distinct:

verified

the signature and key material validate.

invalid

the signature, covered components, key, or freshness checks fail.

unverified

the verifier cannot obtain enough information to decide, for example because directory discovery failed or the key is unknown.

Origins can apply local policy to each outcome. During deployment, treating unverified as one bot-management signal is safer than treating it as either verified or invalid.

C.2. Directory Availability

Directory resources are bootstrap material. Operators serving a directory should make it reachable without requiring Web Bot Auth on the directory request. They should also avoid bot protection rules that block ordinary verifier fetches of the well-known resource.

The directory endpoint should support GET. Supporting HEAD, ETag, Last-Modified, Cache-Control, and conditional requests can reduce fetch load. Cache is specifically discussed in Appendix C.4.

C.3. Bounded Directory Fetches

Verifiers fetch directories named by untrusted requests, and should bound those fetches as described in Section 6.8.

Verifiers should also coalesce concurrent fetches for the same directory and apply per-directory or per-origin concurrency limits. This avoids a fetch storm when many requests reference the same uncached directory.

C.4. Cache Behaviour

Verifiers should use normal HTTP caching semantics [HTTP-CACHE] for key directories. In particular, verifiers should respect Cache-Control, Expires, Date, ETag, and Last-Modified when present.

A verifier should not fetch the directory for every request. It should refresh cached directories when they become stale, and can use background refresh with jitter to avoid synchronized refetches.

C.5. Negative Caching and Retry

Verifiers can cache unsuccessful discovery outcomes for a short period to reduce repeated fetches. Negative cache entries should expire after no more than five minutes. They are operational throttling state, not proof that a signature is invalid.

Network failures, TLS failures, and 5xx responses should be treated as transient unless local policy says otherwise. Verifiers should retry with bounded exponential backoff and jitter. When a directory response includes Retry-After, verifiers should respect it as described by [HTTP] and [HTTP-BEST-PRACTICES].

C.6. Freshness and Replay

Shorter signature lifetimes reduce replay risk but increase sensitivity to clock skew and signing failures. Nonces provide stronger replay defense, but require state at the verifier. Some deployments can tolerate bounded replay for short windows; others need strict Section 6.3.

These choices are deployment policy. Verifiers should avoid accepting signatures with freshness windows longer than their risk model permits.

C.7. Field compression

Covering per-request components costs bytes when a connection is reused. HPACK [HPACK] and QPACK [QPACK] can index a repeated Signature, Signature-Input, or Signature-Agent value, so a signature reused across requests on one connection is sent once and referenced afterwards. A per-request value cannot be referenced; it is sent as a literal every time. Huffman coding and an indexed field name reduce that literal, they do not replace the reference.

This is not a reason to widen the covered components. The bytes saved are the bytes of a credential anyone who observes it can replay until expires (Section 5.2), and one static signature for many requests is an anti-pattern (Appendix C.12). An encoder that treats a signature as a credential may also decline to index it (Section 7.1.3 of [HPACK]).

C.8. Directory Response Signature Lifetimes

Where the key set is redistributed, revocation latency is already floored by how often the redistributor republishes, so a short expires on a directory response signature (Appendix B) buys nothing and costs availability: at expiry every consumer drops that operator's keys to unverified at once, with no serving stale. Operators should set expires well beyond the republication interval of any list they expect to appear in. The lever for faster revocation is publishing more often, not signing shorter.

C.9. Rollout and Fallback

Web Bot Auth deployments will coexist with existing bot identification signals during rollout. Verifiers can continue to use existing methods such as IP-based checks, forward-confirmed reverse DNS, local allowlists, and reputation systems.

Fallback should not turn an unsupported or unverifiable Web Bot Auth signature into a trusted identity. It should leave the request in the origin's existing bot-management path.

C.10. Proxies and Intermediaries

Proxies and intermediaries need to preserve the fields covered by a signature if the origin will verify that signature. If a proxy rewrites the authority, path, or signed header fields, the origin may no longer see the message that was signed.

A deployment can instead verify at the proxy and pass the result to the origin through a deployment-local trusted channel. That assertion is local policy; it is not a replacement for the original HTTP Message Signature.

C.11. CORS

Key directories contain public key material. If browser-based verifiers need to fetch them cross-origin, a directory server can use a permissive CORS policy such as Access-Control-Allow-Origin: * without credentials. CORS is not key authentication and does not replace signature validation.

C.12. Deployment Anti-Patterns

Deployments should avoid:

  • using test or demonstration keys in production

  • issuing one static signature for many requests

  • asking users to copy long-lived signatures into third-party tools

  • sharing one signing key across unrelated agents or purposes

  • relying on manual key rotation as the only revocation mechanism

Appendix D. Examples

D.1. Delegation and chaining

Delegation and chaining are out of scope for this document and are expected to be specified separately. Input is welcome on the associated GitHub issue.

D.2. Multiple signatures with a remote browser

This example shows Alice's agent using a remote browser to fetch a resource. The agent signs selected request fields. The remote browser signs the request it sends to the origin and also covers the agent's signature fields. The signature values are illustrative; this is not a test vector.

NOTE: '\' line wrapping per RFC 8792

GET /resource HTTP/1.1
Host: origin.example
Signature-Agent: agent="https://agent.alice.example",\
 browser="https://browser.example"
Signature-Input: agent=("@method" "@authority" "@path"\
 "signature-agent";key="agent");created=1735689600\
 ;keyid="poqkLGiymh_W0uP6PZFw-dvez3QJT5SolqXBCW38r0U"\
 ;tag="web-bot-auth",\
 browser=("@method" "@authority" "@path"\
 "signature-agent";key="browser"\
 "signature-agent";key="agent"\
 "signature-input";key="agent"\
 "signature";key="agent");created=1735689601\
 ;keyid="oD0HwocPBSfpNy5W3bpJeyFGY_IQ_YpqxSjQ3Yd-CLA"\
 ;tag="web-bot-auth"
Signature: agent=:YWdlbnQtc2lnbmF0dXJl:,\
 browser=:YnJvd3Nlci1zaWduYXR1cmU=:

The origin verifies each signature on its own. The agent signature covers the fields selected by Alice's agent. The browser signature covers the request sent by the remote browser, its own Signature-Agent member, and all three of the agent label's fields, as Section 5.2.2 requires. This records that the remote browser forwarded a request carrying the agent's signature. It does not say that Alice's agent authorized the remote browser to act for it.

Appendix E. Test Vectors

These vectors exercise the minimum this document requires, so most of them cover @authority and nothing else, with an expires far enough out that they do not age. That combination is a parsing and verification exercise, not a configuration to copy: as Section 5.2 explains, a signature covering @authority alone is reusable against that authority for any method, path, and body until it expires. Deployments should cover more and expire sooner.

E.1. RSASSA-PSS Using SHA-512

The test vectors in this section use the RSA-PSS key defined in Appendix B.1.2 of [HTTP-MESSAGE-SIGNATURES]. This section includes non-normative test vectors that may be used as test cases to validate implementation correctness.

E.1.1. Signature-Agent absent from the request

This example presents a minimal signature using the rsa-pss-sha512 algorithm over test-request. The request does not contain a Signature-Agent header.

The corresponding signature base is:

NOTE: '\' line wrapping per RFC 8792

"@authority": example.com
"@signature-params": ("@authority")\
 ;created=1735689600\
 ;keyid="oD0HwocPBSfpNy5W3bpJeyFGY_IQ_YpqxSjQ3Yd-CLA"\
 ;alg="rsa-pss-sha512"\
 ;expires=4889289600\
 ;nonce="JojDFWJ90jf+gZhdKeTyJYsu1XvNPZSFAGhvYq5SuV3gneOEUAhq+xl792WGuD1W+Dr6NRmx+m+t06NsYnL4iA=="\
 ;tag="web-bot-auth"

This results in the following Signature-Input and Signature header fields being added to the message under the label sig1:

NOTE: '\' line wrapping per RFC 8792

Signature-Input: sig1=("@authority")\
 ;created=1735689600\
 ;keyid="oD0HwocPBSfpNy5W3bpJeyFGY_IQ_YpqxSjQ3Yd-CLA"\
 ;alg="rsa-pss-sha512"\
 ;expires=4889289600\
 ;nonce="JojDFWJ90jf+gZhdKeTyJYsu1XvNPZSFAGhvYq5SuV3gneOEUAhq+xl792WGuD1W+Dr6NRmx+m+t06NsYnL4iA=="\
 ;tag="web-bot-auth"
Signature: sig1=:hWPaj85MWQiRkzU4jnIKvdPQiDfMCPIoxOP8nZveNc3aFQ7r/UmXWCwGNImw588iRvTFey5TR3fVEgnXpcttlyK+u5pN831z9Wlr+IMNfub4uEM3SuO+SKFygJZyLG0pf7OAiRcU4C0gyx1BS/+z9ydQTRzDLr88wCkBBRqwGRrSi8HTwxkqg1jugobh93hcnU6gV8MK1n+VnhRprIgl2RQSO6q5cfbB4OS8C4t/8ndW0lYmP2SWzKZJXnpX5Wrj17PuLqnVW6MO8pJnLAMXNvxUdx32KHeq/cHFrzZazZsua3UOoP+k+niHwoQ8bBWj1Vi4mM1mYJK+fk366cCLsQ==:

E.1.2. Signature-Agent included present on the request

This example presents a minimal signature using the rsa-pss-sha512 algorithm over test-request. The request contains a Signature-Agent header.

The corresponding signature base is:

NOTE: '\' line wrapping per RFC 8792

"@authority": example.com
"signature-agent";key="agent2": "https://signature-agent.test"
"@signature-params": ("@authority" "signature-agent";key="agent2")\
 ;created=1735689600\
 ;keyid="oD0HwocPBSfpNy5W3bpJeyFGY_IQ_YpqxSjQ3Yd-CLA"\
 ;alg="rsa-pss-sha512"\
 ;expires=4889289600\
 ;nonce="wcfPQPh7SzkvrIVvhD00vNk9PkxJNY2NVbYl2PVBB4zmUoluSwE7W6bPtF60QA3k8g06FU7PPCD+J58YofY1zg=="\
 ;tag="web-bot-auth"

This results in the following Signature-Input and Signature header fields being added to the message under the label sig2:

NOTE: '\' line wrapping per RFC 8792

Signature-Agent: agent2="https://signature-agent.test"
Signature-Input: sig2=("@authority" "signature-agent";key="agent2")\
 ;created=1735689600\
 ;keyid="oD0HwocPBSfpNy5W3bpJeyFGY_IQ_YpqxSjQ3Yd-CLA"\
 ;alg="rsa-pss-sha512"\
 ;expires=4889289600\
 ;nonce="wcfPQPh7SzkvrIVvhD00vNk9PkxJNY2NVbYl2PVBB4zmUoluSwE7W6bPtF60QA3k8g06FU7PPCD+J58YofY1zg=="\
 ;tag="web-bot-auth"
Signature: sig2=:gHzpLNeHaHIO19NaJH9YMW5dcVSi2s0wOMBr6p18vcofS106sfC4KBIS0/szPlBBd1vIcyQ88B6CTEWIhRAiVrb9zfX0mx1aG12CSGWcYkSirHeyTxhbuJvXd27ed6skWoy4PjXItq38936ivUQjfdIwXh1aX6HxkAC3vRnEdSNfntkLWeEuIQ5BLIOBGE39fSwg27Qjq6OVWYas/9/aFUr3HA34MXWYdp+//cvlEKDp3kRoLOw9ro0AOr6srHrTeEtxon2afcws1aZVSlPdd2fZSEIGmw9HAHLDCEkFTERu1gH2k/zIEqgy7CAYXI9E5slog0cLg/Vc6+f8gih33g==:

E.1.3. Legacy Signature-Agent, sf-string

Retained for implementers migrating to the dictionary form (Section 5.2.1). Do not copy it into new deployments.

This example presents a minimal signature using the rsa-pss-sha512 algorithm over test-request. The request contains a Signature-Agent header.

The corresponding signature base is:

NOTE: '\' line wrapping per RFC 8792

"@authority": example.com
"signature-agent": "https://signature-agent.test"
"@signature-params": ("@authority" "signature-agent")\
 ;created=1735689600\
 ;keyid="oD0HwocPBSfpNy5W3bpJeyFGY_IQ_YpqxSjQ3Yd-CLA"\
 ;alg="rsa-pss-sha512"\
 ;expires=1735693200\
 ;nonce="XSHtZVCThSIAksXsH9WBs6AtxtXC0eQGiIcUGSoJstFs8lAWakjhrfwzLhyjtme5iXMZvmFWqDEs6cT3Jf+BbQ=="\
 ;tag="web-bot-auth"

This results in the following Signature-Input and Signature header fields being added to the message under the label sig2:

NOTE: '\' line wrapping per RFC 8792

Signature-Agent: "https://signature-agent.test"
Signature-Input: sig2=("@authority" "signature-agent")\
 ;created=1735689600\
 ;keyid="oD0HwocPBSfpNy5W3bpJeyFGY_IQ_YpqxSjQ3Yd-CLA"\
 ;alg="rsa-pss-sha512"\
 ;expires=1735693200\
 ;nonce="XSHtZVCThSIAksXsH9WBs6AtxtXC0eQGiIcUGSoJstFs8lAWakjhrfwzLhyjtme5iXMZvmFWqDEs6cT3Jf+BbQ=="\
 ;tag="web-bot-auth"
Signature: sig2=:I1QWNzGXdP1a4dSvOHLCVOOanEYHDk+ZsVxM9MLX/p4ko69ghKwR5EOtAD96g7g4GWP7lmpM/jFAf9q8EFRDTPLjUXySwMv4YPgabv2LQihTJG2y8a2m6IGltyruwQNiqSJVUuRaG9+b17CGmAMFZh30X6GXLdQJrCARpeTqPwp2DC+a8haDE/VE5EruqzjA5/2mKwvrkzkSqeW5tOVtFwWRRHIOidquf/8Je6kM9mhgkg4arudLA5SL4wyyYE1jURIgcOl8agrfdJ5Def23DIRtiOLRa8jT9cpTLFAuFHN+mrZA/LH9h0gSIg1cPb+0cMASee5uku1KjWcFer7jWA==:

E.2. EdDSA Using Curve edwards25519

The test vectors in this section use the Ed25519 key defined in Appendix B.1.4 of [HTTP-MESSAGE-SIGNATURES]. This section include non-normative test vectors that may be used as test cases to validate implementation correctness.

E.2.1. Signature-Agent absent from the request

This example presents a minimal signature using the ed25519 algorithm over test-request. The request does not contain a Signature-Agent header.

The corresponding signature base is:

NOTE: '\' line wrapping per RFC 8792

"@authority": example.com
"@signature-params": ("@authority")\
 ;created=1735689600\
 ;keyid="poqkLGiymh_W0uP6PZFw-dvez3QJT5SolqXBCW38r0U"\
 ;alg="ed25519"\
 ;expires=4889289600\
 ;nonce="zIW8+cdmA3vdYagbxojpONwa/l0EKJ/O3/wD486VvsQjO/RxPaSt6ZxvQaMcQzNnqKN/mQ6hpGiFro2L2qkz5A=="\
 ;tag="web-bot-auth"

This results in the following Signature-Input and Signature header fields being added to the message under the label sig1:

NOTE: '\' line wrapping per RFC 8792

Signature-Input: sig1=("@authority")\
 ;created=1735689600\
 ;keyid="poqkLGiymh_W0uP6PZFw-dvez3QJT5SolqXBCW38r0U"\
 ;alg="ed25519"\
 ;expires=4889289600\
 ;nonce="zIW8+cdmA3vdYagbxojpONwa/l0EKJ/O3/wD486VvsQjO/RxPaSt6ZxvQaMcQzNnqKN/mQ6hpGiFro2L2qkz5A=="\
 ;tag="web-bot-auth"
Signature: sig1=:QKN4fTdIYfh82fvoZCQiQA1weuozfCS/Led2zTMbewMMqH8PI2Wsy/5c4ao6B6D09nraNQdBNOADg8aM1MqfCg==:

E.2.2. Signature-Agent included present on the request

This example presents a minimal signature using the ed25519 algorithm over test-request. The request contains a Signature-Agent header.

The corresponding signature base is:

NOTE: '\' line wrapping per RFC 8792

"@authority": example.com
"signature-agent";key="agent2": "https://signature-agent.test"
"@signature-params": ("@authority" "signature-agent";key="agent2")\
 ;created=1735689600\
 ;keyid="poqkLGiymh_W0uP6PZFw-dvez3QJT5SolqXBCW38r0U"\
 ;alg="ed25519"\
 ;expires=4889289600\
 ;nonce="n9p433xm+NJ3ph3upfBIGmsuwHw387YV7Q/F+6BSpGCVjYCqQw6rznNA8PVVLySrAWsv0hQtFioQb6E1YsauiA=="\
 ;tag="web-bot-auth"

This results in the following Signature-Input and Signature header fields being added to the message under the label sig2:

NOTE: '\' line wrapping per RFC 8792

Signature-Agent: agent2="https://signature-agent.test"
Signature-Input: sig2=("@authority" "signature-agent";key="agent2")\
 ;created=1735689600\
 ;keyid="poqkLGiymh_W0uP6PZFw-dvez3QJT5SolqXBCW38r0U"\
 ;alg="ed25519"\
 ;expires=4889289600\
 ;nonce="n9p433xm+NJ3ph3upfBIGmsuwHw387YV7Q/F+6BSpGCVjYCqQw6rznNA8PVVLySrAWsv0hQtFioQb6E1YsauiA=="\
 ;tag="web-bot-auth"
Signature: sig2=:RdNFx5Bj6au3YgAMQL/RzmUlZE8QZLIaXGRpw985hWnwPfMxT228NMk6ehRS1PSl4e8PhbNZACSanGdhEwYCCg==:

E.2.3. Legacy Signature-Agent, sf-string

Retained for implementers migrating to the dictionary form (Section 5.2.1). Do not copy it into new deployments.

This example presents a minimal signature using the ed25519 algorithm over test-request. The request contains a Signature-Agent header.

The corresponding signature base is:

NOTE: '\' line wrapping per RFC 8792

"@authority": example.com
"signature-agent": "https://signature-agent.test"
"@signature-params": ("@authority" "signature-agent")\
 ;created=1735689600\
 ;keyid="poqkLGiymh_W0uP6PZFw-dvez3QJT5SolqXBCW38r0U"\
 ;alg="ed25519"\
 ;expires=1735693200\
 ;nonce="e8N7S2MFd/qrd6T2R3tdfAuuANngKI7LFtKYI/vowzk4lAZYadIX6wW25MwG7DCT9RUKAJ0qVkU0mEeLElW1qg=="\
 ;tag="web-bot-auth"

This results in the following Signature-Input and Signature header fields being added to the message under the label sig2:

NOTE: '\' line wrapping per RFC 8792

Signature-Agent: "https://signature-agent.test"
Signature-Input: sig2=("@authority" "signature-agent")\
 ;created=1735689600\
 ;keyid="poqkLGiymh_W0uP6PZFw-dvez3QJT5SolqXBCW38r0U"\
 ;alg="ed25519"\
 ;expires=1735693200\
 ;nonce="e8N7S2MFd/qrd6T2R3tdfAuuANngKI7LFtKYI/vowzk4lAZYadIX6wW25MwG7DCT9RUKAJ0qVkU0mEeLElW1qg=="\
 ;tag="web-bot-auth"
Signature: sig2=:jdq0SqOwHdyHr9+r5jw3iYZH6aNGKijYp/EstF4RQTQdi5N5YYKrD+mCT1HA1nZDsi6nJKuHxUi/5Syp3rLWBA==:

Appendix F. Implementations

This draft has a couple of public implementations. A demonstration server has been deployed to https://http-message-signatures-example.research.cloudflare.com/.

It uses ed25519 example signing and verifying keys defined in Appendix B.1.4 of [HTTP-MESSAGE-SIGNATURES].

F.1. Clients

draft-meunier-webbotauth-httpsig-protocol-00

draft-meunier-web-bot-auth-architecture-03

F.2. Servers

draft-meunier-webbotauth-httpsig-protocol-00

draft-meunier-web-bot-auth-architecture-03

Acknowledgments

The editor would also like to thank the following individuals (listed in alphabetical order) for feedback, insight, and implementation of this document - Marwan Fayed, Maxime Guerreiro, Scott Hendrickson, Jonathan Hoyland, Nikhil Kandoi, Akshat Mahajan, Mark Nottingham, Eugenio Panero, Lucas Pardue, Malte Ubl, Loganaden Velvindron, Tanya Verma.

Changelog

draft-meunier-webbotauth-httpsig-protocol-01

draft-meunier-webbotauth-httpsig-protocol-00

draft-meunier-web-bot-auth-architecture-05

draft-meunier-web-bot-auth-architecture-04

draft-meunier-web-bot-auth-architecture-03

draft-meunier-web-bot-auth-architecture-02

draft-meunier-web-bot-auth-architecture-01

draft-meunier-web-bot-auth-architecture-00

Authors' Addresses

Thibault Meunier
Cloudflare
Sandor Major
Google