A↗Authenord
Developer documentation

Authenord HTTP Exchange Format

This is a deliberately narrow Authenord application profile of HTTP Message Signatures (RFC 9421) and Content-Digest (RFC 9530), not a new standard or a general-purpose implementation of all options in those RFCs. MUST/SHOULD below describe this profile.

1. Parties and trust

An agent presents an existing Authenord-signed JSON credential and signs the current HTTP request using the private Ed25519 key corresponding to the credential's registered public key. A receiver trusts the configured Authenord issuer and verification service, checks current status, rejects replay and applies its own permission policy.

Issuer in the existing credential format: poa:vgprwvmclastkmgatlrx. The historical protocol identifier is retained for existing credentials. The presenting agent MUST NOT send its private key, account password, Supabase session or an issuer private key. The credential is shareable identity data, not a bearer secret. Only send it to approved origins; it contains recorded identity claims.

Both agents can play either role: each outbound request is signed by its sender and checked by its receiver. This version does not sign responses, negotiate delegated authority, or replace HTTPS server authentication. Websites without a receiver integration do not automatically recognise an Authenord identity.

2. Transport and required fields

HTTPS is REQUIRED. The SDK offers an explicit HTTP exception for loopback development only. Request redirection MUST NOT be followed automatically with the signed credential. Re-sign only after separately approving a new destination.

FieldExact profile value / meaning
Authenord-Version0.1
Authenord-CredentialUnpadded base64url of UTF-8 JSON { "payload": {...}, "signature": "..." }
Content-TypeThe actual application content type; absent input becomes application/octet-stream
Content-Digestsha-256=:<standard padded base64 SHA-256 of exact body bytes>:
Signature-InputThe single authenord entry described below
Signatureauthenord=:<standard padded base64 of 64-byte Ed25519 request signature>:

Header names are case-insensitive. Values MUST be preserved. GET/HEAD and other empty bodies use the SHA-256 digest of the empty byte string. Content-Encoding is unsupported. The credential header MUST be at most 16,384 characters; request bodies default to 1,048,576 bytes, with an explicitly configurable SDK ceiling of 16 MiB. Provision gateway header limits to accept your credentials or reject them cleanly. Combined request/header limits may differ at deployment gateways; the SDK limit is not a gateway guarantee.

3. Signature-Input

The component order and parameter order are fixed for this exchange format. Extra, duplicate, reordered or missing entries/parameters are rejected by the reference SDK.

authenord=("@method" "@target-uri" "content-digest" "content-type" "authenord-credential" "authenord-version");created=CREATED;expires=EXPIRES;nonce="NONCE";keyid="KEY_ID";alg="ed25519";tag="authenord-v0.1"

Clock tolerance is at most 30 seconds (default 30). Receivers check that CREATED is no more than the tolerance in the future, no older than max lifetime plus tolerance, and EXPIRES has not passed beyond that tolerance. They enforce the lifetime separately. Synchronise clocks. A receiver may configure a smaller maximum lifetime/tolerance.

4. Signature base

Construct these lines in this exact order, joined by LF (0x0A) without a final LF:

"@method": POST
"@target-uri": https://supplier.example/quotes?currency=USD
"content-digest": sha-256=:BODY_DIGEST_BASE64:
"content-type": application/json
"authenord-credential": CREDENTIAL_BASE64URL
"authenord-version": 0.1
"@signature-params": ("@method" "@target-uri" "content-digest" "content-type" "authenord-credential" "authenord-version");created=CREATED;expires=EXPIRES;nonce="NONCE";keyid="KEY_ID";alg="ed25519";tag="authenord-v0.1"

The target URI is the absolute, externally requested Fetch Request URL, including query, scheme, authority and path. Fragments and embedded URL credentials are prohibited. Use Fetch/URL normalisation on both sides; do not reorder query parameters, decode/re-encode paths or rewrite the destination after signing. Use the method exactly as exposed by Fetch. The signer signs the UTF-8 bytes with Ed25519. Encode the signature using ordinary padded base64, not base64url. The reference SDK accepts only this strict profile syntax.

The credential's issuer signature is a separate signature: unpadded base64url Ed25519 over Authenord's recursively key-sorted JSON payload encoded as UTF-8. Preserve array order and the full signed payload. This existing convention is not RFC 8785/JCS.

5. Receiver validation

Before executing any requested action, a receiver MUST:

  1. Require HTTPS and an exact configured destination origin.
  2. Enforce version, field sizes, component/parameter syntax and timestamp bounds.
  3. Parse the credential and require the known issuer, supported existing format, valid dates, and a registered Ed25519 public key. No automatic issuer discovery from attacker-controlled URLs or credential fields is permitted.
  4. Recompute the digest of the exact body bytes and compare the Content-Digest.
  5. Verify the request signature with the public key in the credential and require Signature-Input keyid to match the credential's public key ID.
  6. Verify the credential issuer signature and **current credential and issuer-key status** using the trusted online service. Default reference endpoint: https://vgprwvmclastkmgatlrx.supabase.co/functions/v1/poa-api/v0.1/verify. POST the original {payload, signature} JSON, with the published apikey header. Require valid:true, signature_valid:true, credential_status:"ACTIVE", issuer_key_status:"ACTIVE", and expired:false. Fail closed on timeout, errors, malformed results or any other status. The default SDK timeout is five seconds.
  7. Atomically reserve (agent ID, registered key ID, nonce) through EXPIRES + allowed clock skew + one second. Reject if already reserved. Do not evict unexpired records on store overflow, and deny access if the replay store is unavailable.
  8. Recheck freshness after slow validation, then run the service's explicit access policy.

Revoking a registered key or agent through the existing registry revokes its associated credentials. The online API status check is required; a locally valid credential does not establish current status. No broad offline fallback is part of this profile.

The signature authenticates ONLY the listed request components. Authorization headers, cookies, arbitrary organisation headers and other fields are not covered. Applications must separately validate any unsigned inputs that influence an access decision. Request signatures are not business authorization, proof of a legal-company affiliation, payment consent, behavioural safety or delegated permission. An allowlist should use registered Agent IDs and the application's own authenticated onboarding/policy process.

6. Replay, failures and retries

One verification consumes a nonce even if the application's policy later denies the request. Multiple workers/regions and restarts MUST share a durable atomic replay store. An in-memory store is only a local, single-process convenience. Use an application-level idempotency policy for actions and re-sign any retry with a new nonce.

Reference Fetch middleware returns JSON { "error": "CODE" }:

HTTPMeaningExamples
401Invalid credential/request or replayCREDENTIAL_REJECTED, INVALID_REQUEST_SIGNATURE, BODY_DIGEST_MISMATCH, REPLAY_DETECTED, REQUEST_EXPIRED_OR_INVALID_TIME
403Valid identity, business policy deniedFORBIDDEN
503Required verification/replay service unavailableCREDENTIAL_SERVICE_UNAVAILABLE, REPLAY_STORE_UNAVAILABLE

The raw SDK throws AuthenordError.code; unsupported version, wrong audience, malformed encoding/header and key mismatch have their own error codes. Never retry 401/403 by turning off checks. Receiver applications may implement rate limits before costly checks. They must bound concurrency and network service availability for their own traffic.

7. Integration boundaries

Verify on the original body before parsing, decompression or mutation. Configure the public origin explicitly behind proxies; use trusted routing configuration to reconstruct the original URI and never accept arbitrary forwarded-host values. Browser cross-origin calls need an OPTIONS/CORS policy for the six headers above. Authorization remains the receiver's responsibility; no response-signing or request challenge protocol is defined.

The same format works for agent-to-API, agent-to-website-backend and agent-to-agent HTTP requests when both sides integrate it. It is not automatically understood by all sites. Do not place credentials in URL query parameters. Credentials and signatures can enable correlation across requests; minimise logging and disclose what fields are shared.

8. Discovery and references

These Authenord discovery files and custom header names are application conventions, not an assertion of IANA registration. The exchange format intentionally rejects general RFC 9421 variants not listed here. Keep versioned SDK modules together; consult release notes before upgrading. The credential issuance format remains unchanged.