Protocol
Web Bot Auth compatibility
Experimental: complete a challenge with an RFC 9421 HTTP Message Signature and a Signature-Agent key directory instead of a registered key.
The Web Bot Auth provider is implemented and enabled on POST /api/v1/verify, but its behaviour may change as the underlying drafts evolve. The registry provider (registered Ed25519 keys) is the primary path in v1.
Overview
Agents that publish their public keys in a Web Bot Auth key directory can sign the /verify request itself with an HTTP Message Signature (RFC 9421). The signature's nonce parameter must equal the challenge's nonce, which binds the signed request to exactly one challenge. No prior registration with imnotahuman.ai is needed; the resulting identity is the agent's origin.
Request
curl -X POST https://imnotahuman.ai/api/v1/verify \
-H 'content-type: application/json' \
-H 'signature-agent: "https://agent.example"' \
-H 'signature-input: sig1=("@authority" "signature-agent");created=1789905607;expires=1789905907;keyid="fIpJN_bqfhSP3P4ikoK4_vs36sWvfiDG3cgfCRJ6GRo";alg="ed25519";nonce="aW1ub3RhaHVtYW4tZG9jcy1leGFtcGxlLW5vbmNlISE";tag="web-bot-auth"' \
-H 'signature: sig1=:0IKKR9d3yZ4MIdTuKMNO99q+fF8kC5kp1Vak61hrQb1TEBhlzCDtkZxq7Ho1m5IjetPefqSAbrkDrHnueQhlCw==:' \
-d '{"challenge_id":"ch_mfr4q2xk7tbn3ycz5w6ah2ep4d"}'| Header / field | Requirement | Notes |
|---|---|---|
Signature-Agent | required | Your key directory origin as an sf-string, e.g. "https://agent.example". https only; no port, credentials, localhost, IP literals or .local/.internal hosts. |
Signature-Input | required | Dictionary member label=(components);params. Components must include "@authority" and "signature-agent". @method, @path, @scheme, @target-uri and any request header may also be covered. |
Signature | required | Same label as Signature-Input with the signature as a byte sequence (:base64:). |
body | required | {"challenge_id": "ch_…"} and nothing else. |
The Signature-Input parameters are checked as follows:
| Parameter | Requirement | Failure |
|---|---|---|
created | integer, ≤ now + 60 | SIGNATURE_EXPIRED / SIGNATURE_MALFORMED |
expires | integer, ≥ now, ≤ created + 3600 | SIGNATURE_EXPIRED |
keyid | RFC 7638 JWK thumbprint of the signing key | KEY_UNKNOWN if no directory key matches |
alg | "ed25519" | SIGNATURE_MALFORMED |
nonce | the challenge's nonce | CHALLENGE_MISMATCH |
tag | "web-bot-auth" | SIGNATURE_MALFORMED. If several signatures are present the one tagged web-bot-auth is used. |
Signature base
The base follows RFC 9421. @authority is imnotahuman.ai (the public host of the API), @path is /api/v1/verify, @scheme is https. Header values are trimmed and line-folded whitespace is collapsed.
"@authority": imnotahuman.ai
"signature-agent": "https://agent.example"
"@signature-params": ("@authority" "signature-agent");created=1789905607;expires=1789905907;keyid="fIpJN_bqfhSP3P4ikoK4_vs36sWvfiDG3cgfCRJ6GRo";alg="ed25519";nonce="aW1ub3RhaHVtYW4tZG9jcy1leGFtcGxlLW5vbmNlISE";tag="web-bot-auth"The @signature-params line is the inner-list exactly as serialised in the header.
Key directory
The directory is fetched from the Signature-Agent origin at /.well-known/http-message-signatures-directory (if the Signature-Agent URL has a path, that path is used instead). It must be a JSON document with a keys array of OKP JWKs. The keyid parameter is matched against the RFC 7638 thumbprint of each key, computed over {"crv":"Ed25519","kty":"OKP","x":"…"} with SHA-256 and base64url encoding.
{
"keys": [
{ "kty": "OKP", "crv": "Ed25519", "x": "_Gqb_W0_oiqrRCCw8P_X8DSeNSwTiMpA4rUS3OqqBZk" }
]
}- Fetched with
Accept: application/http-message-signatures-directory+json, application/json, 5 s timeout, redirects refused. - Maximum 64 KiB; only the first 20 keys are considered. Unparseable keys are skipped.
- Cached for 5 minutes per directory URL.
- Unreachable or invalid directory:
502 SIGNATURE_AGENT_UNAVAILABLE.
Result
On success the VerificationResult has method: "web_bot_auth" and agent: { id: "https://agent.example", name: "agent.example" }. The token's sub is that origin. No registry agent record is created and no agent_id appears in events. Registration challenges cannot be completed this way.
Hosts should note that a web_bot_auth identity is only as trustworthy as the directory host's control over its domain and keys. See Threat model.