Skip to content

v0.3.0

Released 2026-10-26.

v0.3.0 still tracks draft-hardt-oauth-aauth-protocol-11, draft-hardt-httpbis-signature-key-09, and draft-hardt-aauth-bootstrap-02. The wire format is unchanged, so v0.2 and v0.3 parties interoperate. v0.3 verifies more strictly, so it refuses some requests v0.2 accepted; see Security.

Upgrade

go get github.com/aauth-dev/aauth-go@v0.3.0

Go 1.26 or later, as for v0.2. Some APIs change, mostly in the server packages: approvals carry the revision of the request shown, interaction codes are looked up and then consumed at the person's decision, the ClaimsProvider takes a request, and stores gain pruning and counting methods. AuthorizationHandler requires TrustIssuer, and an agent provider's Domain must be its issuer's host. The migration guide lists every change with before and after code.

accessserver.Client now reports an access server's 402 Payment Required as an error wrapping *aauth.PaymentRequiredError when no Payment handler is configured.

Breaking changes

These change the API, so code using them needs updating to compile:

  • personserver: ConsumeCodeFor is removed; LookupCode(ctx, code, client) shows a request and ConsumeCode(ctx, code, client, person) consumes its code at the person's decision. ClaimsProvider takes a *ClaimsRequest. Store gains Prune, TokenStore gains CountRevocations and PendingStore gains CountOpenPending.
  • accessserver: Approve(ctx, id, revision, scope) and ConsumeCode(ctx, code, client, person). Store gains CountOpenPending, CountRevocations and Prune.
  • sandbox: LoadOrCreateCA takes optional domains, and Signer is no longer comparable.

These compile unchanged but now fail or refuse what v0.2 accepted:

  • AuthorizationHandler answers 500 until TrustIssuer is set.
  • NewResourceGuard fails when Resource has no host. In four-party mode the guard takes auth tokens only from Audience, so TrustIssuer lists person servers only.
  • personserver.Approve fails with ErrRequestChanged for a request the agent updated unless Grant.Revision names the revision shown.
  • agentprovider.New fails when Config.Domain is not the issuer's host, and verifiers refuse an agent token whose sub is outside its iss domain.
  • SelfSignedResolver verifies only top-level agent tokens.
  • Agent tokens over 24 hours and resource tokens over 5 minutes are refused (MaxLifetime), as are request bodies over 4 MiB during verification (MaxBodySize).
  • The person server refuses call chaining unless Config.AllowCallChaining is set.
  • Pending URLs answer 410 Gone after delivering their result once.
  • Problem responses no longer carry internal error text.
  • aauth-sandbox serve listens on 127.0.0.1 unless --listen-any-interface is given, and the signing helper signs only for the sandbox's hosts and upstreams unless --signer-any-target is given. The sandbox replaces its CA on the first run, so trust the new ca.pem again in Postman, curl or your browser profile.

Highlights

  • Capabilities. Agents say what they can handle with AAuth-Capabilities (Transport.Capabilities): involving the person, answering clarifications, or paying. Resources check CanRaise and CanRequirePayment before asking, so an agent is never left waiting for a person nobody will ask.
  • Access ahead of a call. Transport.Authorize asks a resource's authorization endpoint for a scope before the first request, and caches the auth token or session token it gets. Resources serve the endpoint with AuthorizationHandler.
  • Payment. A 402 Payment Required carries the payment protocol's challenge in PaymentRequiredError; set Transport.Payment to settle it, and the transport polls or retries afterwards. No payment protocol is built in.
  • ResourceGuard. Each operation of a resource declares the least it needs (AccessAgent, AccessPerson, or AccessAuth with a scope). The guard verifies the presented token, challenges for the next one, and hands the verified Caller to the handler. An auth-token challenge also asks for the scope the agent already holds, so one auth token per resource keeps every grant.
  • Hosted agents in one call. agentprovider.Client.Enroll enrolls a key at an agent provider and returns an aauth.Agent that keeps its tokens fresh.
  • The sandbox. aauth-sandbox runs the agent provider, person server, access server and demo resources for all five access modes on https://*.aauth.test, locally or in Docker, with its own certificate authority, consent pages, a message trace, and a signing helper for clients that cannot sign, such as Postman and curl. The helper also signs as a request's own Signature-Key names, so generic clients need no sandbox headers. --remote swaps in another implementation of a role, and --upstream puts a resource of your own behind it. See the sandbox guide.
  • Walkthrough code. examples/walkthrough has tested code for each step of the AAuth walkthroughs, for every role, marked as named regions that the PIDL walkthrough viewer shows next to the HTTP messages.

Security

v0.3.0 closes several ways a party could act beyond what it was given.

  • Signatures are bound to the receiving server. Servers and ResourceGuard refuse a request whose signed @authority is another host, so a server an agent calls cannot replay the request to another server. Use RequestVerifyOptions.Authority and AuthorityOf when you verify requests yourself.
  • Four-party resources take auth tokens only from their access server. With ResourceGuardConfig.Audience set, an auth token must be issued by that access server, so a person server cannot skip it.
  • Agent identifiers belong to their provider. An agent token's sub must be in the domain of its iss. SelfSignedResolver verifies only top-level agent tokens.
  • Consent covers what the person saw. An agent cannot widen a request the person approved while an access server decides, and approvals fail with ErrRequestChanged when the request changed after it was shown.
  • Key discovery stays on the issuer. dwk must be one of the four AAuth metadata documents, and redirects to another host are refused.
  • Bounded work for unauthenticated callers. Verification reads at most 4 MiB of a body, the JWKS cache resists floods of unknown issuers, stores are capped and pruned, and rate limits are kept per key space.
  • Less to learn from errors. Responses carry fixed descriptions, not internal error text.
  • Interaction codes are consumed at the person's authenticated decision, limited per client, and refused once expired. Pending URLs answer 410 Gone after delivering their result.
  • Call chaining is opt-in at the person server (Config.AllowCallChaining), and ResourceGuard can check revocation (IsRevoked) and passes the token's account and tenant to the handler.
  • The sandbox stays on your machine. It listens on loopback by default; the signing helper returns redirects unchanged, answers only local clients, refuses browser requests, and signs only for the sandbox's hosts and upstreams; its CA is limited to the sandbox's names; and the image builds with Go 1.27.3.

Fixes

  • ChainInteraction and WriteClarification mark their 202 bodies as JSON.
  • aauth-sandbox serve records its listener address before its first request, which could otherwise dial the default port.

Documentation

  • The agent guide covers enrolling at a hosted agent provider, declaring capabilities, requesting access ahead of a call, and paying.
  • The resource guide covers ResourceGuard, checking capabilities, and the authorization endpoint.
  • The new sandbox guide covers running locally and in Docker, the signing helper, the trace, and fronting your own server, and trusting its CA in each tool rather than system-wide.
  • The design and security notes cover signature binding, agent identifiers, four-party issuers and consent revisions.

Every change is in the changelog.