From e1d7224b831c8d3e1fd457862dc07178d0d8c4ff Mon Sep 17 00:00:00 2001 From: dickhardt Date: Tue, 11 Aug 2026 22:15:34 +0100 Subject: [PATCH] www: six access-mode diagrams for AAuth -11 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The four mode diagrams all opened with `HTTPSig w/ agent_token` + `POST /authorize`, which -11 no longer permits: an agent MUST present a person token at a resource's authorization endpoint, and a resource MUST have verified one before it issues a resource token. Every authorization flow therefore starts at the PS's person token endpoint. - Identity Based: unchanged. - Resource Managed: "AAuth Access Token" is now the session token, the one credential a resource issues for its own consumption. Returned in `AAuth-Access`, presented back in `Authorization: AAuth`, with `authorization` in the signature's covered components — not DPoP, which the old copy claimed. - Person Identity: new. Person token from `POST person_token_endpoint`, presented via `Signature-Key` in place of the agent token; the resource serves on the person's identity alone. No resource token, no auth token. - Person Server Managed: `POST /person` first, `/authorize` signed with the person token, resource token carries `ps`/`sub`/`person_token_jti`, and the PS hop is `POST /auth_token` (the metadata field `token_endpoint` was renamed `auth_token_endpoint`). - Federated: same, plus the PS calling the AS's `auth_token_endpoint`. - Per-Call: new, from R3 -02. The resource challenges an `r3_per_call` invocation with a resource token whose `r3_uri`/`r3_s256` reference a per-call proposal; the AS fetches it and evaluates the parameters, the PS puts them to the person, and the resource verifies the retry against what was approved. Six diagrams push the shared diagram height from 516 to 644, so a short diagram trailed 440px of dangling lifeline through the reserved space. Lifelines now stop just past the last message; the box stays one height so switching tabs does not shift the page. llms.txt: five access modes, not four, named as -11 names them; four token types plus the session token. Dropped the pin to draft-hardt-oauth-aauth-protocol-01. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01FmiCqDjRUSx6zb1N4gZPXE --- src/lib/components/JointSequence.svelte | 6 +- src/routes/+page.svelte | 93 ++++++++++++++++++++----- static/llms.txt | 10 +-- 3 files changed, 87 insertions(+), 22 deletions(-) diff --git a/src/lib/components/JointSequence.svelte b/src/lib/components/JointSequence.svelte index 5e77ae1..f09319f 100644 --- a/src/lib/components/JointSequence.svelte +++ b/src/lib/components/JointSequence.svelte @@ -98,6 +98,10 @@ return cursorY; }); const H = Math.max(cursorY + STEP_GAP, minHeight); + // Lifelines stop just past the last message rather than running to the bottom of the + // box. Diagrams share one height (minHeight) so switching tabs doesn't shift the page; + // without this a short diagram trails dashed lines through the reserved space. + const lifelineEnd = Math.min(H - 10, cursorY + STEP_GAP - 10); const graph = new joint.dia.Graph({}, { cellNamespace: joint.shapes }); const paper = new joint.dia.Paper({ @@ -124,7 +128,7 @@ xs.forEach((x) => { const line = new joint.shapes.standard.Link({ source: { x, y: TOP_PAD + ACTOR_H }, - target: { x, y: H - 10 }, + target: { x, y: lifelineEnd }, attrs: { line: { stroke: theme.lifeline, diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index c6b6e3b..22bc9eb 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -131,27 +131,53 @@ { name: 'Resource Managed', parties: 'Agent + Resource', - desc: 'Bridge to OAuth 2.0 — the resource handles authorization via its existing OAuth AS,
and returns an opaque AAuth Access Token the agent presents on repeat calls with DPoP.', + desc: 'Bridge to OAuth 2.0 — the resource runs its own authorization flow and returns a session token,
the one credential a resource issues for its own consumption, bound to the agent’s signature.', steps: [ { from: 'Agent', to: 'Resource', lines: ['HTTPSig w/ agent_token'] }, { from: 'Resource', to: 'Agent', lines: ['202 (interaction required)'], dashed: true }, { note: 'user completes interaction' }, { from: 'Agent', to: 'Resource', lines: ['GET pending URL'] }, - { from: 'Resource', to: 'Agent', lines: ['200 OK', 'AAuth-Access: opaque-token'], dashed: true }, - { from: 'Agent', to: 'Resource', lines: ['HTTPSig w/ agent_token', 'Authorization: AAuth opaque-token'] }, + { from: 'Resource', to: 'Agent', lines: ['200 OK', 'AAuth-Access: session-token'], dashed: true }, + { + from: 'Agent', + to: 'Resource', + lines: [ + 'HTTPSig w/ agent_token', + 'Authorization: AAuth session-token', + 'signature covers authorization' + ] + }, + { from: 'Resource', to: 'Agent', lines: ['200 OK'], dashed: true } + ] + }, + { + name: 'Person Identity', + parties: 'Agent + Resource + Person Server', + desc: "Federated login for agents — the Person Server issues a person token for one resource,
and the resource serves on the person's identity alone. No resource token, no auth token.", + steps: [ + { from: 'Agent', to: 'Person Server', lines: ['HTTPSig w/ agent_token', 'POST /person w/ {resource}'] }, + { from: 'Person Server', to: 'Agent', lines: ['person_token'], dashed: true }, + { from: 'Agent', to: 'Resource', lines: ['HTTPSig w/ person_token', 'GET /api/documents'] }, { from: 'Resource', to: 'Agent', lines: ['200 OK'], dashed: true } ] }, { name: 'Person Server Managed', parties: 'Agent + Resource + Person Server', - desc: "Native AAuth — the resource requires the user's identity or consent (or both).
The user's Person Server issues an auth token after the user approves.", + desc: "Native AAuth — the resource needs an authorization decision, not just the person's identity.
It issues a resource token bound to that person token; the Person Server returns an auth token.", steps: [ - { from: 'Agent', to: 'Resource', lines: ['HTTPSig w/ agent_token', 'POST /authorize'] }, - { from: 'Resource', to: 'Agent', lines: ['resource_token', '(aud = Person Server URL)'], dashed: true }, - { from: 'Agent', to: 'Person Server', lines: ['HTTPSig w/ agent_token', 'POST /token w/ resource_token'] }, + { from: 'Agent', to: 'Person Server', lines: ['HTTPSig w/ agent_token', 'POST /person w/ {resource}'] }, + { from: 'Person Server', to: 'Agent', lines: ['person_token'], dashed: true }, + { from: 'Agent', to: 'Resource', lines: ['HTTPSig w/ person_token', 'POST /authorize'] }, + { + from: 'Resource', + to: 'Agent', + lines: ['resource_token', '(aud = Person Server URL)', 'ps / sub / person_token_jti'], + dashed: true + }, + { from: 'Agent', to: 'Person Server', lines: ['HTTPSig w/ agent_token', 'POST /auth_token w/ resource_token'] }, { from: 'Person Server', to: 'Agent', lines: ['auth_token'], dashed: true }, - { from: 'Agent', to: 'Resource', lines: ['HTTPSig w/ auth token', 'GET /api/documents'] }, + { from: 'Agent', to: 'Resource', lines: ['HTTPSig w/ auth_token', 'GET /api/documents'] }, { from: 'Resource', to: 'Agent', lines: ['200 OK'], dashed: true } ] }, @@ -160,15 +186,45 @@ parties: 'Agent + Resource + Person Server + Access Server', desc: "Cross-domain AAuth — the resource has its own Access Server that federates with the agent's Person Server.
Authorization works across org and cloud boundaries without pre-registration.", steps: [ - { from: 'Agent', to: 'Resource', lines: ['HTTPSig w/ agent_token', 'POST /authorize'] }, - { from: 'Resource', to: 'Agent', lines: ['resource_token', '(aud = Access Server URL)'], dashed: true }, - { from: 'Agent', to: 'Person Server', lines: ['HTTPSig w/ agent_token', 'POST /token w/ resource_token'] }, - { from: 'Person Server', to: 'Access Server', lines: ['HTTPSig w/ jwks_uri', 'POST /token w/ resource_token'] }, + { from: 'Agent', to: 'Person Server', lines: ['HTTPSig w/ agent_token', 'POST /person w/ {resource}'] }, + { from: 'Person Server', to: 'Agent', lines: ['person_token'], dashed: true }, + { from: 'Agent', to: 'Resource', lines: ['HTTPSig w/ person_token', 'POST /authorize'] }, + { + from: 'Resource', + to: 'Agent', + lines: ['resource_token', '(aud = Access Server URL)', 'ps / sub / person_token_jti'], + dashed: true + }, + { from: 'Agent', to: 'Person Server', lines: ['HTTPSig w/ agent_token', 'POST /auth_token w/ resource_token'] }, + { from: 'Person Server', to: 'Access Server', lines: ['HTTPSig w/ jwks_uri', 'POST /auth_token w/ resource_token'] }, { from: 'Access Server', to: 'Person Server', lines: ['auth_token'], dashed: true }, { from: 'Person Server', to: 'Agent', lines: ['auth_token'], dashed: true }, - { from: 'Agent', to: 'Resource', lines: ['HTTPSig w/ auth token', 'GET /api/documents'] }, + { from: 'Agent', to: 'Resource', lines: ['HTTPSig w/ auth_token', 'GET /api/documents'] }, { from: 'Resource', to: 'Agent', lines: ['200 OK'], dashed: true } ] + }, + { + name: 'Per-Call', + parties: 'Agent + Resource + Person Server + Access Server', + desc: "R3 per-call authorization — the resource challenges one invocation with a proposal carrying that call's
concrete parameters. The person approves them, and the retry is verified against what was approved.", + steps: [ + { from: 'Agent', to: 'Resource', lines: ['HTTPSig w/ person_token', 'POST /send_email (r3_per_call)'] }, + { + from: 'Resource', + to: 'Agent', + lines: ['401 + resource_token', 'r3_uri/r3_s256 → per-call proposal'], + dashed: true + }, + { from: 'Agent', to: 'Person Server', lines: ['HTTPSig w/ agent_token', 'POST /auth_token w/ resource_token'] }, + { from: 'Person Server', to: 'Access Server', lines: ['HTTPSig w/ jwks_uri', 'POST /auth_token w/ resource_token'] }, + { from: 'Access Server', to: 'Resource', lines: ['GET r3_uri (signed)'] }, + { from: 'Resource', to: 'Access Server', lines: ['proposal: operation + parameters'], dashed: true }, + { note: 'person approves these exact parameters' }, + { from: 'Access Server', to: 'Person Server', lines: ['auth_token (r3_granted: this call)'], dashed: true }, + { from: 'Person Server', to: 'Agent', lines: ['auth_token'], dashed: true }, + { from: 'Agent', to: 'Resource', lines: ['HTTPSig w/ auth_token', 'POST /send_email (same parameters)'] }, + { from: 'Resource', to: 'Agent', lines: ['200 OK', 'parameters verified vs proposal'], dashed: true } + ] } ]; @@ -181,7 +237,7 @@ status: 'Internet-Draft', href: 'https://datatracker.ietf.org/doc/draft-hardt-oauth-aauth-protocol', editorsCopy: 'https://dickhardt.github.io/AAuth/draft-hardt-oauth-aauth-protocol.html', - desc: 'The authorization protocol for agent-to-resource access. Four access modes, three token types, agent governance, missions, clarification chat, and call chaining.', + desc: 'The authorization protocol for agent-to-resource access. Five access modes, four token types, agent governance, missions, clarification chat, and call chaining.', primary: true, indent: false }, @@ -199,7 +255,7 @@ status: 'Exploratory', href: 'https://dickhardt.github.io/AAuth/draft-hardt-aauth-r3.html', editorsCopy: null, - desc: 'Vocabulary-based authorization using formats agents already understand (MCP, OpenAPI, gRPC, GraphQL).', + desc: 'Vocabulary-based authorization using formats agents already understand (MCP, OpenAPI, gRPC, GraphQL), plus per-call proposals for operations authorized one call at a time.', primary: false, indent: true } @@ -562,8 +618,9 @@

How AAuth Works

- AAuth has four access modes. All replace API keys with cryptographic identity. - Capability grows from simplest to most capable — adopt incrementally as your needs expand. + AAuth has five access modes. All replace API keys with cryptographic identity. + They differ in what the resource ends up knowing and which party established it — adopt incrementally as your needs expand. + Per-call authorization, from R3, governs a single action rather than a class of access.

@@ -638,8 +695,10 @@
  • agent_token establishes the agent's identity
  • +
  • person_token names the person the agent acts for, at one resource
  • resource_token describes the access needed
  • auth_token grants an agent access to a resource
  • +
  • session-token issued by a resource for its own consumption, opaque to the agent
  • jwks_uri Person Server's JWKS endpoint, discovered via well-known metadata
diff --git a/static/llms.txt b/static/llms.txt index 3ed44d0..9884771 100644 --- a/static/llms.txt +++ b/static/llms.txt @@ -1,12 +1,14 @@ # AAuth -> AAuth is an authorization protocol for agent-to-resource authorization and identity claim retrieval, supporting four resource access modes with agent governance as an orthogonal layer. +> AAuth is an authorization protocol for agent-to-resource authorization and identity claim retrieval, supporting five resource access modes with agent governance as an orthogonal layer. ## What is AAuth? Every agent — any HTTP client — gets its own cryptographic identity: a domain, static metadata, and a JWKS. No pre-registration, no shared secrets, no dependency on a particular server. An agent signs a request and a resource decides what to do based on who the agent is. -AAuth supports four resource access modes (identity-based, resource-managed, PS-managed, federated), each adding parties and capabilities. Adoption does not require coordination between parties. +AAuth supports five resource access modes (agent identity, resource-managed, person identity, PS authorization, federated). They differ in what the resource ends up knowing and which party established it, not in how much of the protocol they use. Adoption does not require coordination between parties. + +Four token types travel between parties: the agent token (the agent's identity), the person token (the person the agent acts for, at one resource), the resource token (the access a resource needs authorized), and the auth token (the grant). A resource may additionally issue a session token for its own consumption, opaque to the agent, returned in `AAuth-Access` and presented back in `Authorization: AAuth`. ## Walk an Agent Through AAuth (Start Here) @@ -25,9 +27,9 @@ The demos run against the Hello beta Person Server; data is reset regularly. ## Specifications -- [AAuth Protocol (Internet-Draft)](https://datatracker.ietf.org/doc/draft-hardt-oauth-aauth-protocol/) — current version: [draft-hardt-oauth-aauth-protocol-01](https://datatracker.ietf.org/doc/html/draft-hardt-oauth-aauth-protocol-01). The authorization protocol. Four access modes, three token types, agent governance with missions, clarification chat, and call chaining. +- [AAuth Protocol (Internet-Draft)](https://datatracker.ietf.org/doc/draft-hardt-oauth-aauth-protocol/) — the datatracker page always resolves to the latest published version; the [editor's copy](https://dickhardt.github.io/AAuth/draft-hardt-oauth-aauth-protocol.html) tracks the working draft. The authorization protocol. Five access modes, four token types, agent governance with missions, clarification chat, and call chaining. - [HTTP Signature Keys (Internet-Draft)](https://datatracker.ietf.org/doc/draft-hardt-httpbis-signature-key/): Foundation layer. Well-known key discovery, `Signature-Key` header for conveying public keying material alongside HTTP Message Signatures (RFC 9421). -- [R3 — Rich Resource Requests (Exploratory)](https://dickhardt.github.io/AAuth/draft-hardt-aauth-r3.html): Vocabulary-based authorization using formats agents already understand (MCP, OpenAPI, gRPC, GraphQL). +- [R3 — Rich Resource Requests (Exploratory)](https://dickhardt.github.io/AAuth/draft-hardt-aauth-r3.html): Vocabulary-based authorization using formats agents already understand (MCP, OpenAPI, gRPC, GraphQL), plus per-call proposals for operations authorized one call at a time. ## Implementations