Skip to main content
You’re going to make a service accept AFAuth-signed requests. After this, any AI agent in the world can sign up to your service with its own keypair — no portal to maintain, no API keys to provision.

Install

Configure a Server

defineService is the opinionated convenience factory. It returns a Server — the same class that wraps Verifier and exposes endpoint handlers for discovery, signup, account introspection, owner invitation, claim completion, and key rotation — but with two spam-resistance switches flipped ON by default:
  1. Discovery advertises billing.unclaimed_mode: "attested_only" (§9.2).
  2. The attestor defaults to trustAttestor() (AFAP-0006 §10).
The net effect: un-attested implicit signups are rejected at the wire, and all of a human’s agents — which carry the same per-service pseudonym sub_h (§10.4) — are grouped onto one account (§10.4.4: one account, many devices). Bucket your free-tier quota, rate limits, and bans on the account and a human’s whole fleet shares one bucket, no matter how many keypairs they spin up — while their legitimate PC and phone agents both keep working.
Because this default rejects un-attested signups, an agent reaches your service by linking to a human at trust.afauth.org and presenting an AFAuth-Attestation JWT — the agent quickstart shows that step (the afauth signup CLI auto-mints it). To accept un-linked agents while you ramp, set attestation: "optional" below.
The synthesized discovery doc derives the canonical §4.1 endpoints from baseUrl: /afauth/v1/accounts, /afauth/v1/accounts/me/owner-invitation, /afauth/v1/accounts/me/keys/rotate, and /afauth/v1/claim (plus the /claim claim page). These match the paths @afauthhq/agent signs, so a default agent interoperates out of the box. To customize paths, advertise additional accepted_attestors, or declare limits, pass a discovery override — it merges on top:
For multi-attestor setups, custom HmacAttestor, or fully custom discovery, drop to new Server({...}) directly — see @afauthhq/server overview.

Route incoming requests to the handlers

Verify it works

Hit the discovery endpoint:
For deeper conformance, run the spec’s Appendix C vectors against your Verifier in your own test suite — @afauthhq/server’s test suite already does this, so cloning that pattern is the fastest path. The canonical vectors live at AFAuthHQ/spec/vectors.

Production checklist

  • Swap Memory* stores for durable backends. @afauthhq/worker ships D1AccountStore (multi-agent accounts; atomic device-grouping via the (iss, sub_h) index), KvNonceStore, KvRevocationList. See Deploy to Cloudflare Workers.
  • Replace consoleEmailHandler with a real email transport.
  • Host the claim page — the SDK doesn’t route it for you because it’s service UI. Reference: examples/worker/src/index.ts.
  • Decide your billing mode. The defineService default is attested_only — set attestation: "off" to opt out, or "optional" for a migration path.

Next steps