Author: Dick Hardt Email: [email protected]
Date: November 21, 2025
AAuth is an agent aware auth protocol for modern distributed systems:
- Progressive authentication - from abuse prevention to full authorization
- Agent identity - verify applications alongside users
- Resource identity - cryptographic proof of resource legitimacy, preventing confused deputy and MITM attacks
- Unified protocol - authentication and authorization in one flow
- Dynamic ecosystems - no pre-registration required
- Proof-of-possession - every request is signed, removing shared secrets
- Multi-hop access - resources calling resources with token exchange or downstream user interaction
Agent Auth (AAuth) is an exploratory specification examining what new capabilities and features may be useful to address use cases that are not well-served by existing protocols like OAuth 2.0, OpenID Connect (OIDC), and SAML. While these protocols excel in their designed use cases, the internet has evolved in ways that create gaps AAuth aims to fill.
The document explores use cases requiring capabilities beyond OAuth 2.0 and OIDC's design:
- From bearer tokens to proof-of-possession: Every request is cryptographically signed, eliminating bearer token exfiltration as an attack vector
- From pre-registered client IDs to HTTPS-based agent identities: Enabling dynamic ecosystems without registration bottlenecks
- From implicit resource trust to provable resource identity: Resources have cryptographic identities and issue signed resource tokens, preventing confused deputy and MITM attacks
- From long-lived shared secrets to ephemeral keys: Supporting distributed application instances with rapid revocation
- From separate authentication and authorization protocols to unified auth: Single flow provides both identity and delegated access
- From user-only authorization to agent-aware access control: Resources can enforce policies based on verified agent identity
- From coarse scopes to rich authorization context: Enabling meaningful user consent and least-privilege access
- From single-hop to multi-hop access: Resources often need to access downstream resources to fulfill requests. Token exchange enables access through multiple hops while maintaining proof-of-possession and user context, with interaction requests bubbling up as needed
AAuth builds on proven patterns from OAuth 2.0 (authorization code flow, refresh tokens, metadata discovery) and OIDC (identity claims, user authentication) while introducing capabilities for modern agent-based architectures.
This is an exploration and explainer, not a ready-to-adopt draft. The objective is to paint a picture of how modern authorization could work and spark discussion about addressing the gap between OAuth 2.0 assumptions and today's security and architectural realities.
- Introduction
- Terminology
- Protocol Overview
- Agent-Auth Response Header
- Agent Tokens
- Resource Tokens
- Auth Tokens
- Metadata Documents
- Protocol Details
- HTTP Message Signing Profile
- Auth Request Document
- Error Responses
- Security Model
- IANA Considerations
Appendixes:
- Appendix A: Relationship to OAuth 2.1 and OIDC
- Appendix B: Long Tail Agent Servers
- Appendix C: Agent Token Acquisition Patterns
- Appendix D: Relationship to Web-Bot-Auth
- Appendix E: Redirect Headers for Enhanced Security
OAuth was created to replace the anti-pattern of users providing their passwords to applications to scrape their data from web sites. With OAuth, users could authorize an application to scoped access of their data without sharing their passwords. The internet has evolved significantly since the release of OAuth 2.0.
-
Security requirements have changed.
Exfiltration of bearer tokens has become a common attack vector. While proof-of-possession with digital signatures is now practical and widely supported, bearer tokens and shared secrets are still used in most deployments.
-
Applications are distributed and more diverse.
When OAuth 2.0 was created, the client was typically a server. Today it may also be one of many widely distributed instances of a desktop, mobile, or command line application where managing a single long lived shared secret or private key is impractical.
-
Agents have loosened the client-server model.
Tightly bound, pre-registered client and server relationships are giving way to more open and dynamic ecosystems. In environments like the Model Context Protocol (MCP), a client may interact with any server, not just those it was pre-registered with.
-
Enterprise systems span multiple trust domains.
Organizations deploy hundreds of applications across vendors, each requiring access to resources in different security contexts. Role-based authorization is often insufficient. Fine-grained, dynamic access control often requires verifying both the calling application and user's identity.
-
OAuth scopes have become insufficient for modern authorization.
Traditional OAuth scopes like read or write provide only coarse-grained labels that fail to convey what data will be accessed, under what conditions, for what purpose, or for how long. This opacity prevents meaningful user consent and makes it impossible to enforce least privilege.
-
Resources have varying auth requirements.
Resources need different levels of protection for different operations. Public endpoints rely on IP addresses for rate limiting and abuse prevention. Application identity is verified through IP whitelisting, mTLS, or long-lived credentials. Authorization uses API keys, manually provisioned tokens, or OAuth flows—serving both user-delegated access and machine-to-machine patterns. These varying requirements have led to fragmented solutions: IP filtering for abuse, mTLS or credentials for application identity, OAuth or tokens for authorization.
-
Applications require both authentication and authorization.
OAuth 2.0 provides authorization (delegated access). OpenID Connect provides authentication (user identity via SSO, alongside SAML). Both protocols excel in their designed use cases: OAuth 2.0 for user-delegated API access; OIDC for browser-based SSO to web applications. However, applications often need both authentication and authorization in contexts where the separation creates friction.
Resources often need access to downstream resources.
Modern architectures frequently require resources to call other resources to fulfill requests. When a resource needs downstream access, it must acquire authorization—sometimes autonomously based on its identity, sometimes requiring user interaction despite having no direct user interface.
AAuth addresses these evolved requirements by redefining the relationships between three web participants:
- Agents: the applications and autonomous processes
- Resources: the protected APIs and data endpoints agents need to access
- Auth Servers: the systems that authenticate users and issue authorization
AAuth's protocol features directly address each trend:
-
HTTP Message Signing (HTTPSig) (Section 10) replaces bearer tokens and shared secrets. Every request an agent makes is cryptographically signed with an ephemeral key it controls, eliminating token exfiltration as an attack vector and providing verifiable proof-of-possession and message integrity when calling both an auth server and a protected resource
-
HTTPS-based agent identity and delegation addresses distributed applications. Agents are identified by HTTPS URLs rather than pre-registered client IDs and redirect URIs. An agent identity can be used directly by an agent server (publishing metadata and keys), or delegated to agent delegates through short-lived agent tokens that bind ephemeral signing keys to the agent's identity, enabling rapid key rotation without managing long-lived shared secrets.
-
Provable resource identity enables loose coupling between resources and auth servers while preventing confused deputy and MITM attacks. Resources are identified by HTTPS URLs and issue signed resource tokens, allowing any resource to work with any auth server without pre-registration or tight coupling.
-
Discoverable metadata enables dynamic ecosystems. Each participant publishes a metadata document describing their capabilities and endpoints, allowing agents, resources, and auth servers to interact without pre-established relationships.
-
Verifiable application and user identity supports multi-domain trust. Auth tokens can contain both the agent's cryptographically verified identity and user identity claims from the auth server, enabling fine-grained access control decisions based on who is requesting access and on whose behalf.
-
Extensible authorization context goes beyond simple scopes. Resources can provide detailed authorization requests conveying what data will be accessed, under what conditions, for what purpose, and for how long. This enables meaningful user consent, fine-grained policy enforcement, and least privilege access control.
-
Progressive auth levels allow resources to dynamically request the specific level of protection they need using the
Agent-Authheader. A resource can challenge for signature-based proof-of-possession, verified agent identity, or authorization from the auth server—unifying IP-based abuse prevention, mTLS application identity, and OAuth authorization into a single protocol that scales with request sensitivity. -
Unified authentication and authorization eliminates the OAuth/OIDC split. AAuth uses "auth" to represent both authentication and authorization in a single protocol. Auth tokens can contain both identity claims and authorization scopes, giving resources everything they need for access control decisions. This eliminates confusion about when to use OAuth vs. OIDC and prevents common mistakes like misusing ID tokens for API access.
-
Multi-hop resource access enables resources to access downstream resources to fulfill requests. The
user_interactionmechanism allows authorization requirements to bubble up through multiple resource layers, enabling users to grant access across trust boundaries. Token exchange (request_type=exchange) enables autonomous multi-hop access by allowing resources to act as agents, presenting upstream auth tokens to downstream auth servers to access downstream resources without user interaction.
-
agent: An autonomous process or application identified by an HTTPS URL (the
agentclaim). An agent may act directly as an agent server or as an agent delegate using delegated authority from an agent server. -
agent server: An agent acting with its authoritative identity, using its published JWKS to sign requests directly. The agent server publishes metadata and keys at
https://agent.example/.well-known/aauth-agentand may issue agent tokens to delegate its identity to agent delegates. For simplified key management for the long tail of agent servers see Appendix B. -
agent delegate: An agent acting under delegated authority from an agent server. An agent delegate proves its identity by presenting an agent token (JWT) that binds its signing key to the agent server's identity. Agent delegates include server workloads (e.g., SPIFFE workloads), application installations (mobile, desktop, CLI), and device-specific deployments.
-
agent token: A proof-of-possession JWT issued by an agent server to an agent delegate, binding the delegate's signing key and granting it authority to act on behalf of the agent server. Presented to a resource or auth server to prove agent identity. The JWT header includes
"typ": "agent+jwt"(media type:application/agent+jwt). -
auth server: A system identified by an HTTPS URL that authenticates the user, evaluates access requests, and issues auth tokens binding the agent's key to the granted access and user claims.
-
auth token: A proof-of-possession JWT issued by the auth server to an agent, enabling access to a resource. May contain identity claims, scopes, or both. The JWT header includes
"typ": "auth+jwt"(media type:application/auth+jwt).
auth was chosen to indicate a new token that can represent both authn and authz.
-
request token: An opaque string issued by the auth server representing a pending authorization request. The agent uses this token at the
agent_auth_endpointto initiate user consent. Similar torequest_uriin PAR (RFC 9126) but represented as an opaque token value rather than a URI. -
Auth Request Document: A JSON document retrieved via HTTPS that describes detailed authorization requirements for a resource. Used for complex authorization scenarios that cannot be expressed with simple scope strings. See Section 11 for details.
-
resource: A collection of one or more protected HTTPS endpoints identified by an HTTPS URL. A resource issues resource tokens to bind an agent and its access request to its identity. In some cases, the resource may be the agent itself (e.g., for SSO or user authentication).
-
resource token: A proof-of-possession JWT issued by a resource to an agent, binding the agent's identity and access request to the resource's identity. Presented to the auth server as proof of the access request's legitimacy. The JWT header includes
"typ": "resource+jwt"(media type:application/resource+jwt). -
resource metadata: A JSON document published by a resource at
/.well-known/aauth-resourcecontaining the resource's configuration including its identifier, auth server, resource token endpoint, and supported capabilities.
The following terms are defined in existing specifications and reused in AAuth:
-
refresh token: A credential used to obtain new access tokens without user interaction. (OAuth 2.0 [RFC 6749] Section 1.5)
-
user: A human or organization (resource owner) whose identity and consent are represented by the auth server. (OAuth 2.0 [RFC 6749] Section 1.1)
AAuth supports progressive authentication levels: pseudonymous, identified, and authorized; allowing resources to request the appropriate level of protection for each operation using the Agent-Auth response header (Section 4). The protocol involves three participants: agents (applications and autonomous processes), resources (protected APIs), and auth servers (systems that issue authorization). Agents prove their identity using HTTP Message Signatures (Section 10) with agent tokens (Section 5) or auth tokens (Section 6). This section illustrates how these participants interact through common use cases.
Resources use the Agent-Auth response header to dynamically challenge agents for appropriate authentication (Section 4). However, agents that already know the required scope or auth_request_url can request authorization directly from the auth server without first calling the resource. The use cases below illustrate the dynamic challenge pattern; direct authorization requests follow the same flow starting from the auth server interaction.
Note: The sequence diagrams in this section are simplified for clarity. Full parameter lists, validation steps, and security considerations are detailed in Section 9 (Protocol Details).
A web crawler accesses public content without authentication. When rate limits are exceeded, the resource challenges for pseudonymous authentication (Section 4) to grant higher limits using HTTP Message Signatures (Section 10) and a header web key.
sequenceDiagram
participant Agent as agent
participant Resource as resource
Agent->>Resource: unsigned request
Resource->>Agent: 200 OK
Note over Agent,Resource: ... more requests ...
Agent->>Resource: unsigned request
Resource->>Agent: 429 with<br/>Agent-Auth challenge
Agent->>Resource: HTTPSig request<br/>(scheme=hwk)
Resource->>Agent: 200 OK<br/>(higher rate limit)
A search engine crawler proves its identity using published JWKS (Section 8.1) to receive allowlisting and preferential rate limits.
sequenceDiagram
participant Agent as agent server
participant Resource as resource
Agent->>Resource: HTTPSig request<br/>(scheme=jwks_uri)
Resource->>Agent: fetch JWKS
Agent->>Resource: JWKS
Resource->>Resource: verify signature<br/>and identity
Resource->>Agent: 200 OK
A mobile app with millions of installations uses agent delegation (Section 5) so each installation has unique identity without shared secrets.
sequenceDiagram
participant Delegate as agent delegate
participant Server as agent server
participant Resource as resource
Delegate->>Server: request agent token
Server->>Delegate: agent token
Delegate->>Resource: HTTPSig request<br/>(scheme=jwt with agent-token)
Resource->>Server: fetch JWKS
Server->>Resource: JWKS
Resource->>Resource: verify agent token<br/>and signature
Resource->>Delegate: 200 OK
A data sync service copies customer records between CRM and billing systems hourly, authorized based on the service's identity (may request authorization directly if scope is pre-configured). The auth server (Section 9.3) issues an auth token (Section 6) without user interaction.
sequenceDiagram
participant Agent as agent
participant Resource as resource
participant Auth as auth server
Agent->>Resource: HTTPSig request<br/>(scheme=jwks_uri)
Resource->>Agent: 401 with<br/>resource_token + auth_server
Agent->>Auth: HTTPSig request<br/>with resource_token
Auth->>Auth: validate resource_token<br/>evaluate policy
Auth->>Agent: auth_token + refresh_token
Agent->>Resource: HTTPSig request<br/>(scheme=jwt with auth-token)
Resource->>Resource: verify auth token
Resource->>Agent: 200 OK
An agent authenticates users to itself (agent identifier matches resource identifier) for both SSO and API access. The agent requests authorization directly with scope or auth_request_url instead of a resource_token (Section 9.3). The returned auth token can be used to verify user identity and by agent delegates to call the agent's APIs, solving the OIDC limitation where ID tokens and access tokens are separate.
sequenceDiagram
participant User as user
participant Agent as agent
participant Auth as auth server
Agent->>Auth: HTTPSig request<br/>with scope (no resource_token)
Auth->>Auth: validate agent signature
Auth->>Agent: request_token
Agent->>User: redirect to auth server
User->>Auth: authenticate and consent
Auth->>Agent: authorization_code<br/>(via redirect)
Agent->>Auth: HTTPSig request<br/>with authorization_code
Auth->>Agent: auth_token + refresh_token
Note over Agent: auth_token used for:<br/>1. User identity (SSO)<br/>2. API access by delegates
An AI assistant accesses a user's calendar data with their explicit consent through an interactive authorization flow (Section 9.5). The auth token (Section 6) includes both user identity and authorization claims.
sequenceDiagram
participant User as user
participant Agent as agent
participant Resource as resource
participant Auth as auth server
Agent->>Resource: HTTPSig request<br/>(scheme=jwks_uri)
Resource->>Agent: 401 with<br/>resource_token + auth_server
Agent->>Auth: HTTPSig request<br/>with resource_token
Auth->>Auth: validate resource_token
Auth->>Agent: request_token
Agent->>User: redirect to auth server
User->>Auth: authenticate and consent
Auth->>Agent: authorization_code<br/>(via redirect)
Agent->>Auth: HTTPSig request<br/>with authorization_code
Auth->>Agent: auth_token + refresh_token
Agent->>Resource: HTTPSig request<br/>(scheme=jwt with auth-token)
Resource->>Agent: 200 OK
An agent maintains long-lived access by refreshing expired auth tokens (Section 9.7) using refresh tokens bound to its identity.
sequenceDiagram
participant Agent as agent
participant Auth as auth server
participant Resource as resource
Note over Agent: auth_token expired
Agent->>Auth: HTTPSig request<br/>with refresh_token
Auth->>Auth: verify agent identity<br/>and token binding
Auth->>Agent: new auth_token
Agent->>Resource: HTTPSig request<br/>(scheme=jwt with auth-token)
Resource->>Agent: 200 OK
When a resource requires user interaction (login, SSO, or consent for downstream access) but cannot interact with the user directly, it returns a user_interaction URL. The agent redirects the user to this URL, the resource facilitates the required interaction with the auth server, and then redirects the user back to the agent. See Section 9.9 for detailed protocol specification.
sequenceDiagram
participant User as user
participant Agent as agent
participant Resource as resource
participant Auth as auth server
Agent->>Resource: HTTPSig request<br/>(scheme=jwt with auth-token)
Resource->>Agent: 401 Agent-Auth:<br/>user_interaction="https://resource.example/auth?session=xyz"
Agent->>User: redirect to user_interaction URL<br/>(with return_url)
User->>Resource: GET /auth?session=xyz&<br/>return_url=...
Note over Resource,Auth: Resource may perform AAuth, login,<br/>SSO, OIDC, or OAuth flow
Resource->>User: redirect to auth server
User->>Auth: authenticate and consent
Auth->>Resource: authorization code
Resource->>Auth: exchange code for token
Auth->>Resource: auth_token
Note over Resource: Store auth_token keyed by session
Resource->>User: redirect back to agent return_url
Agent->>Resource: HTTPSig request<br/>(retry with session)
Resource->>Agent: 200 OK
Note over Agent,Auth: This flow enables AAuth resources<br/>to consume OAuth/OIDC protected APIs<br/>(see Appendix A.8)
When a resource needs to access a downstream resource to fulfill a request, it acts as an agent and presents the upstream auth token to the downstream auth server using request_type=exchange. The downstream auth server validates the upstream authorization and issues a new auth token with an act claim showing the delegation chain. See Section 9.10 for detailed protocol specification.
sequenceDiagram
participant Agent1 as agent 1
participant Resource1 as resource 1 / agent 2
participant Auth2 as auth server 2
participant Resource2 as resource 2
Agent1->>Resource1: HTTPSig request<br/>(scheme=jwt with auth token)
Resource1->>Resource2: attempt access<br/>(no auth)
Resource2->>Resource1: 401 Agent-Auth<br/>(resource_token, auth_server)
Note over Resource1,Resource2: Resource 2 challenges<br/>with resource_token
Resource1->>Auth2: HTTPSig request<br/>(scheme=jwt with upstream auth token)<br/>request_type=exchange<br/>+ resource_token
Note over Resource1,Auth2: Resource 1 acts as agent,<br/>presents upstream auth token via scheme=jwt
Auth2->>Auth2: Validate resource_token<br/>Validate upstream auth token<br/>Trust Auth Server 1<br/>Authorize exchange
Auth2->>Resource1: auth_token with act claim<br/>(bound to Resource 1's key,<br/>shows delegation chain)
Resource1->>Resource2: HTTPSig request<br/>(scheme=jwt with auth token)
Resource2->>Resource1: 200 OK
Resource1->>Agent1: 200 OK<br/>(aggregated response)
Note: For scenarios requiring user consent across multiple resources, use the user_interaction mechanism (Section 9.9) instead.
Resources use the Agent-Auth response header (using HTTP structured fields per RFC 8941) to indicate authentication and authorization requirements.
Requires HTTP Message Signing with any signature scheme (pseudonymous, identified, or authorized).
Agent-Auth: httpsig
Agent response: Include Signature-Key header with any scheme (scheme=hwk, scheme=jwks_uri, scheme=x509, or scheme=jwt).
Requires agent identity verification using verifiable agent identifiers.
Agent-Auth: httpsig; identity=?1
Agent response: Use scheme=jwks_uri or scheme=x509 (agent server) or scheme=jwt with agent token (agent delegate).
With algorithm restrictions:
Agent-Auth: httpsig; identity=?1; algs=("ed25519" "rsa-pss-sha512")
Resources with specific algorithm requirements MAY include the algs parameter as an inner list. If omitted, all standard algorithms are accepted.
Requires authorization from an auth server. The resource issues a resource token and returns it with the auth server identifier.
Agent-Auth: httpsig; auth-token; resource_token="eyJhbGciOiJFZERTQSIsInR5cCI6InJlc291cmNlK2p3dCIsImtpZCI6InJlc291cmNlLWtleS0xIn0.eyJpc3MiOiJodHRwczovL3Jlc291cmNlLmV4YW1wbGUiLCJhdWQiOiJodHRwczovL2F1dGguZXhhbXBsZSIsImFnZW50IjoiaHR0cHM6Ly9hZ2VudC5leGFtcGxlIiwiYWdlbnRfamt0IjoiTnpiTHNYaDh1RENjZC02TU53WEY0V183bm9XWEZaQWZIa3hac1JHQzlYcyIsImV4cCI6MTczMDIyMTIwMCwic2NvcGUiOiJkYXRhLnJlYWQgZGF0YS53cml0ZSJ9.signature"; auth_server="https://auth.example"
Agent response: Present the resource token to the specified auth server to obtain an auth token (Section 6), then retry request with scheme=jwt and the auth token.
When a resource requires user interaction (login, consent, or OAuth flow), it returns a user_interaction URL where the agent should direct the user.
Agent-Auth: httpsig; user_interaction="https://resource.example/auth?session=xyz"
With downstream resource parameters:
Agent-Auth: httpsig; user_interaction="https://resource.example/auth?session=xyz"; resource_token="eyJhbGc..."; auth_server="https://auth.example"
Agent response: Direct the user to the user_interaction URL with a return_url parameter, wait for the user to complete the interaction, then retry the original request. See Section 9.9 for details.
While Agent-Auth is typically used with 401 Unauthorized, resources MAY use it with other status codes to enable progressive rate limiting and abuse mitigation based on authentication level.
401 Unauthorized - Authentication required
Used when the current authentication level is insufficient:
HTTP/1.1 401 Unauthorized
Agent-Auth: httpsig; identity=?1429 Too Many Requests - Rate limit exceeded
Used when the agent has exceeded rate limits for their current authentication level, but a higher authentication level would have higher limits:
HTTP/1.1 429 Too Many Requests
Agent-Auth: httpsig; identity=?1
Retry-After: 60Example progressive rate limiting:
- Pseudonymous (scheme=hwk): 10 requests/minute
- Identified (scheme=jwks_uri, scheme=x509, or scheme=jwt with agent-token): 100 requests/minute
- Authorized (scheme=jwt with auth-token): 1000 requests/minute
403 Forbidden - Access denied for current authentication level
Used when the agent is blocked or access is denied at the current authentication level, but a higher level might be accepted:
HTTP/1.1 403 Forbidden
Agent-Auth: httpsig; auth-token; resource_token="eyJhbGc..."; auth_server="https://auth.example"This allows resources to block abusive pseudonymous traffic while still accepting identified or authorized requests from the same origin.
Agent-Auth header parameters:
httpsig: Authentication scheme (REQUIRED for all responses)identity: Boolean parameter (?1 = true) indicating agent identity is requiredauth-token: Bare token indicating authorization is requiredresource_token: String parameter containing a signed JWT issued by the resource (Section 6) that binds the agent and access request to the resource's identityauth_server: String parameter with the HTTPS URL of the authorization server (Section 9.3)user_interaction: String parameter with URL where the agent should direct the user for interaction (Section 9.9)algs: Inner list of supported HTTPSig algorithms (Section 10)
Resources MAY include both Agent-Auth and WWW-Authenticate headers to support multiple authentication protocols:
HTTP/1.1 401 Unauthorized
Agent-Auth: httpsig; auth-token; resource_token="eyJhbGc..."
WWW-Authenticate: Bearer realm="resource.example", scope="data.read"Agent tokens enable agent delegates to prove delegated identity from an agent server. This section describes the token format, claims, and acquisition process.
Agent tokens enable identity delegation by binding an agent delegate's signing key to the agent server's authoritative identity. An agent server and agent delegate share the same agent identifier (the agent claim), but prove that identity differently:
- Agent server: Uses published JWKS directly (no agent token needed)
- Agent delegate: Presents an agent token signed by the agent server
This delegation model enables distributed application instances to share a single agent identity while using ephemeral keys that can rotate frequently without affecting refresh tokens (see Section 5.6).
Agent tokens MUST be signed JWTs using the JWS Compact Serialization format.
The JOSE header MUST include:
typ(REQUIRED): MUST be"agent+jwt"(media type:application/agent+jwt)alg(REQUIRED): Signature algorithm from the agent server's JWKSkid(REQUIRED): Key ID identifying the signing key in the agent server's JWKS
iss(REQUIRED): The agent server's HTTPS URL (also the agent identifier)sub(REQUIRED): Agent delegate identifier. Identifies the delegated workload or installation, not the specific instance. Examples:- Server workload:
spiffe://trust-domain/service/api - Mobile app installation:
app-installation-uuid-xyz - Desktop app installation:
desktop-app-install-abc - This identifier persists across restarts and key rotations
- Server workload:
exp(REQUIRED): Expiration timestamp (Unix time)cnf(REQUIRED): Confirmation object containing:jwk(REQUIRED): JSON Web Key - the agent delegate's public signing key
aud(OPTIONAL): Intended audience(s) - restricts which resources or auth servers can accept this agent token. May be a string (single audience) or an array of strings (multiple audiences)- Additional claims: Agent servers MAY include custom claims for delegation policies (future work)
JOSE Header:
{
"typ": "agent+jwt",
"alg": "EdDSA",
"kid": "agent-server-key-1"
}Payload:
{
"iss": "https://agent.example",
"sub": "spiffe://example.com/workload/api-service",
"exp": 1730218200,
"cnf": {
"jwk": {
"kty": "OKP",
"crv": "Ed25519",
"x": "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo"
}
}
}Agent delegates obtain agent tokens from their agent server. The specifics of this interaction are out of scope for this specification and may vary based on deployment needs. For common patterns and examples, see Appendix C: Agent Token Acquisition Patterns.
Key management options:
Agent delegates SHOULD rotate keys frequently. Two common approaches:
-
Ephemeral keys (recommended for simplicity): Generate fresh key pair at startup, keep in memory only. When delegate restarts, generate new key and request new agent token with same
sub. Eliminates need for secure key storage. -
Persisted keys: Store key securely, rotate based on policy (time-based, event-based, etc.). Request new agent token after rotation with same
sub.
In both cases, the new agent token uses the same sub (agent delegate identifier), allowing refresh tokens to remain valid across key rotations.
Security considerations:
- Agent servers SHOULD issue short-lived tokens to enable frequent key rotation
- Agent servers SHOULD track issued tokens by
subfor delegation management - Agent servers MAY require additional authentication or authorization before issuing tokens
- Agent delegates SHOULD request new agent tokens before expiration to maintain service continuity
- Agent delegates using persisted keys MUST store private keys securely
When an agent presents Signature-Key: sig=jwt;jwt="<agent-token>", the recipient MUST validate:
- Parse the JWT and extract the JOSE header
- Verify
typis"agent+jwt" - Extract
kidfrom the JOSE header - Extract
iss(agent) from the payload - Fetch the agent server's JWKS (from metadata at
iss) - Match the signing key by
kid - Verify the JWT signature using the matched public key
- Verify the
expclaim (current time MUST be less than expiration) - Verify the
subclaim is present (agent delegate identifier) - If
audclaim is present, verify the recipient's identifier is included in the audience - Extract the public key from
cnf.jwk - Verify that the HTTPSig request signature was created with the key from
cnf.jwk
Resource tokens enable resources to prove their identity and bind access requests to specific agents. This section describes the token format, claims, and validation process.
Resource tokens provide cryptographic proof of resource identity and bind access requests to both the requesting agent and the resource's identity. This prevents several attack scenarios:
- Confused deputy prevention: The
agentclaim binds the request to a specific agent, preventing an attacker from substituting a different resource in the authorization flow - MITM prevention: The resource's signature proves authenticity, preventing attackers from impersonating the resource
- Request integrity: The
agent_jkt(JWK Thumbprint) binds the request to the agent's current signing key, preventing token reuse with different keys
Auth servers verify resource tokens to confirm that legitimate resources are making authorization requests for specific agents.
Resource tokens MUST be signed JWTs using the JWS Compact Serialization format.
The JOSE header MUST include:
typ(REQUIRED): MUST be"resource+jwt"(media type:application/resource+jwt)alg(REQUIRED): Signature algorithm from the resource's JWKSkid(REQUIRED): Key ID identifying the signing key in the resource's JWKS
Encryption of resource tokens may be specified in a future version of this specification.
iss(REQUIRED): The resource's HTTPS URL identifieraud(REQUIRED): The auth server's HTTPS URL identifieragent(REQUIRED): The requesting agent's HTTPS URL identifieragent_jkt(REQUIRED): JWK Thumbprint of the agent's current signing key, calculated per RFC 7638 as BASE64URL(SHA-256(canonical JWK))exp(REQUIRED): Expiration timestamp (Unix time)- One of the following (REQUIRED):
scope(string): Space-separated scope values for the access requestauth_request_url(string): HTTPS URL to an Auth Request Document for complex authorization
JOSE Header:
{
"typ": "resource+jwt",
"alg": "EdDSA",
"kid": "resource-key-1"
}Payload:
{
"iss": "https://resource.example",
"aud": "https://auth.example",
"agent": "https://agent.example",
"agent_jkt": "NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs",
"exp": 1730221200,
"scope": "data.read data.write"
}When an agent presents a resource token, the auth server MUST validate:
- Parse the JWT and extract the JOSE header
- Verify
typis"resource+jwt" - Extract
kidfrom the JOSE header - Extract
iss(resource identifier) from the payload - Fetch the resource's metadata from
{iss}/.well-known/aauth-resource - Extract
jwks_urifrom the metadata - Fetch the resource's JWKS from
jwks_uri - Match the signing key by
kid - Verify the JWT signature using the matched public key
- Verify
audmatches the auth server's identifier - Verify
agentmatches the requesting agent's identifier - Verify
agent_jktmatches the JWK Thumbprint of the agent's current signing key - Verify
expclaim (current time MUST be less than expiration) - Extract and process the
scopeorauth_request_urlfor authorization evaluation
Auth tokens are proof-of-possession JWTs issued by auth servers that authorize agents to access specific resources. This section describes the token format and claims.
Auth tokens bind together:
- Agent identity: Which agent is authorized (via
agent) - Agent key: The agent's signing key (via
cnf.jwk) - Resource: What the agent can access (via
aud) - Authorization: What the agent can do (via
scopeor other claims) - User identity: Optionally, on whose behalf (via
suband identity claims)
Auth tokens MUST be signed JWTs using the JWS Compact Serialization format. Auth tokens MAY optionally be encrypted using JWE (JSON Web Encryption) to preserve privacy of token contents from the agent.
Signed (unencrypted) auth tokens:
The JOSE header MUST include:
typ(REQUIRED): MUST be"auth+jwt"(media type:application/auth+jwt)alg(REQUIRED): Signature algorithm from the auth server's JWKSkid(REQUIRED): Key ID identifying the signing key in the auth server's JWKS
Encrypted auth tokens:
When a resource provides an encryption public key in an Auth Request Document (Section 11), the auth server MAY issue an encrypted auth token to preserve the privacy of token contents from the agent. The token is first signed as a JWS, then encrypted as a JWE using the resource's encryption public key.
The JWE header MUST include:
typ(REQUIRED): MUST be"auth+jwt"(media type:application/auth+jwt)alg(REQUIRED): Key encryption algorithm (e.g.,ECDH-ES+A256KW,RSA-OAEP-256)enc(REQUIRED): Content encryption algorithm (e.g.,A256GCM)kid(OPTIONAL): Key ID for the resource's encryption key (if provided in Auth Request Document)
The encrypted payload is the signed JWT (JWS). Only the resource possessing the corresponding private key can decrypt and validate the auth token. The agent treats the encrypted token as opaque and presents it to the resource via the Signature-Key header.
iss(REQUIRED): The auth server's HTTPS URLaud(REQUIRED): The resource identifier this token authorizes access toagent(REQUIRED ifaudis not the agent identifier): The agent's HTTPS URL (from agent identity). When the agent uses the auth server for SSO (Single Sign-On) to authenticate users to itself,audis the agent identifier and this claim is omitted.exp(REQUIRED): Expiration time (Unix timestamp)cnf(REQUIRED): Confirmation claim object containing:jwk(REQUIRED): JSON Web Key - the agent's public signing key (copied from agent token or agent JWKS)
agent_delegate(OPTIONAL): Agent delegate identifier - present when the agent uses delegation (copied from agent token'ssub)scope(OPTIONAL): Space-separated authorized scopes (excludes identity scopes likeopenid,profile,emailwhich control token claims rather than resource access)act(OPTIONAL): Actor claim showing the delegation chain in token exchange scenarios. Contains information about the upstream agent that delegated access. See Section 9.10 for details on token exchange and theactclaim structure.- User identity claims (when
openidscope was requested):sub(REQUIRED if openid scope granted): User identifiername(OPTIONAL): User's full nameemail(OPTIONAL): User's email addressemail_verified(OPTIONAL): Email verification status (boolean)- Additional standard claims per OpenID Connect Core 1.0 Section 5.1
JOSE Header:
{
"typ": "auth+jwt",
"alg": "EdDSA",
"kid": "auth-server-key-1"
}Payload:
{
"iss": "https://auth.example",
"agent": "https://agent.example",
"agent_delegate": "mobile-app-install-xyz",
"aud": "https://resource.example",
"exp": 1730221200,
"scope": "data.read data.write",
"cnf": {
"jwk": {
"kty": "OKP",
"crv": "Ed25519",
"x": "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo"
}
},
"sub": "user-12345",
"name": "Alice Smith",
"email": "[email protected]",
"email_verified": true
}Payload:
{
"iss": "https://auth.example",
"agent": "https://agent.example",
"agent_delegate": "spiffe://example.com/workload/api-service",
"aud": "https://resource.example",
"exp": 1730221200,
"scope": "data.read",
"cnf": {
"jwk": {
"kty": "OKP",
"crv": "Ed25519",
"x": "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo"
}
}
}When an agent presents Signature-Key: sig=jwt;jwt="<auth-token>", the resource MUST validate:
For encrypted auth tokens (JWE format):
- Parse the token and extract the JOSE header
- Verify
typis"auth+jwt" - Identify that the token is encrypted (header contains
algfor key encryption andencfor content encryption) - Decrypt the JWE using the resource's private encryption key
- Extract the decrypted JWT (JWS) from the JWE payload
- Continue with validation steps for signed tokens below
For signed auth tokens (JWS format) or after decrypting JWE:
- Parse the JWT and extract the JOSE header
- Verify
typis"auth+jwt" - Extract
kidfrom the JOSE header - Extract
issfrom the payload - Fetch the auth server's JWKS (from metadata)
- Match the signing key by
kid - Verify the JWT signature using the matched public key
- Verify the
expclaim (current time MUST be less than expiration) - Verify the
issmatches the trusted auth server - Verify the
audmatches the resource identifier being accessed - Verify the
agentclaim is present - Extract the public key from
cnf.jwk - Verify that the HTTPSig request signature was created with the key from
cnf.jwk - Verify the
scopeclaim (if present) authorizes the requested operation - Optionally enforce policies based on
agent,agent_delegate, orsub(user)
Metadata documents enable dynamic discovery of endpoints, capabilities, and keys. This section describes the metadata published by each participant type.
Agent servers MUST publish metadata at /.well-known/aauth-agent.
Required fields:
agent(string): The agent's HTTPS URLjwks_uri(string): URL to the agent's JSON Web Key Set
Required fields if agent requests user authorization:
redirect_uris(array of strings): Valid redirect URIs for authorization callbacksname(string): Human-readable agent namelogo_uri(string): URL to agent logopolicy_uri(string): URL to privacy policytos_uri(string): URL to terms of servicehomepage(string): Agent homepage URL
Example:
{
"agent": "https://agent.example",
"jwks_uri": "https://agent.example/jwks.json",
"redirect_uris": [
"https://agent.example/callback",
"https://agent.example/aauth/callback"
],
"name": "Example Agent",
"logo_uri": "https://agent.example/logo.png",
"policy_uri": "https://agent.example/privacy",
"tos_uri": "https://agent.example/tos",
"homepage": "https://agent.example"
}Auth servers MUST publish metadata at /.well-known/aauth-issuer.
Required fields:
issuer(string): The auth server's HTTPS URLjwks_uri(string): URL to the auth server's JSON Web Key Setagent_token_endpoint(string): Endpoint for auth requests, code exchange, token exchange, and refreshagent_auth_endpoint(string): Endpoint for user authentication and consent flowagent_signing_algs_supported(array): Supported HTTPSig algorithmsrequest_types_supported(array): Supported request_type values (e.g.,["auth", "code", "exchange", "refresh"])
Optional fields:
scopes_supported(array): Supported scopes
Example:
{
"issuer": "https://auth.example",
"jwks_uri": "https://auth.example/jwks.json",
"agent_token_endpoint": "https://auth.example/agent/token",
"agent_auth_endpoint": "https://auth.example/agent/auth",
"agent_signing_algs_supported": [
"ed25519",
"rsa-pss-sha512"
],
"request_types_supported": [
"auth",
"code",
"exchange",
"refresh"
],
"scopes_supported": [
"profile",
"email",
"data.read",
"data.write"
]
}Resources MUST publish metadata at /.well-known/aauth-resource.
Required fields:
resource(string): The resource's HTTPS URLjwks_uri(string): URL to the resource's JSON Web Key Setresource_token_endpoint(string): Endpoint where agents request resource tokens
Optional fields:
supported_scopes(array of strings): List of scope values supported by this resourcescope_descriptions(object): Dictionary mapping scope names to human-readable descriptions. Enables auth servers to display meaningful consent information to users without tight coupling between resource and auth server.
Example:
{
"resource": "https://resource.example",
"jwks_uri": "https://resource.example/jwks.json",
"resource_token_endpoint": "https://resource.example/resource/token",
"supported_scopes": ["data.read", "data.write", "data.delete"],
"scope_descriptions": {
"data.read": "Read access to your data and documents",
"data.write": "Create and update your data and documents",
"data.delete": "Permanently delete your data and documents"
}
}This section describes each step in the protocol flow in detail.
The agent makes a signed request to the resource including the Signature-Key header.
Example pseudonymous request:
GET /api/data HTTP/1.1
Host: resource.example
Signature-Input: sig=("@method" "@authority" "@path" "signature-key");created=1730217600
Signature: sig=:...signature bytes...:
Signature-Key: sig=hwk;kty="OKP";crv="Ed25519";x="JrQLj5P..."Example identified request (agent delegate):
GET /api/data HTTP/1.1
Host: resource.example
Signature-Input: sig=("@method" "@authority" "@path" "signature-key");created=1730217600
Signature: sig=:...signature bytes...:
Signature-Key: sig=jwt;jwt="eyJhbGc..."Example authorized request:
GET /api/data HTTP/1.1
Host: resource.example
Signature-Input: sig=("@method" "@authority" "@path" "signature-key");created=1730217600
Signature: sig=:...signature bytes...:
Signature-Key: sig=jwt;jwt="eyJhbGc..."If the resource requires a higher authentication level than provided, it responds with a 401 status and an Agent-Auth header.
Example: Signature required
HTTP/1.1 401 Unauthorized
Agent-Auth: httpsigExample: Identity required
HTTP/1.1 401 Unauthorized
Agent-Auth: httpsig; identity=?1Example: Authorization required
HTTP/1.1 401 Unauthorized
Agent-Auth: httpsig; auth-token; resource_token="eyJhbGciOiJFZERTQSIsInR5cCI6InJlc291cmNlK2p3dCIsImtpZCI6InJlc291cmNlLWtleS0xIn0.eyJpc3MiOiJodHRwczovL3Jlc291cmNlLmV4YW1wbGUiLCJhdWQiOiJodHRwczovL2F1dGguZXhhbXBsZSIsImFnZW50IjoiaHR0cHM6Ly9hZ2VudC5leGFtcGxlIiwiYWdlbnRfamt0IjoiTnpiTHNYaDh1RENjZC02TU53WEY0V183bm9XWEZaQWZIa3hac1JHQzlYcyIsImV4cCI6MTczMDIyMTIwMCwic2NvcGUiOiJkYXRhLnJlYWQgZGF0YS53cml0ZSJ9.signature"; auth_server="https://auth.example"When an agent knows the required scope or auth_request_url upfront (without first calling the protected resource), it can request a resource token directly from the resource's resource_token_endpoint.
Request:
The agent makes a signed POST request to the resource's resource_token_endpoint (discovered from resource metadata at /.well-known/aauth-resource).
Request parameters:
scope(CONDITIONAL): Space-separated scope values (REQUIRED ifauth_request_urlis not provided)auth_request_url(CONDITIONAL): HTTPS URL to an Auth Request Document (REQUIRED ifscopeis not provided)
Example request:
POST /resource/token HTTP/1.1
Host: resource.example
Content-Type: application/x-www-form-urlencoded
Signature-Input: sig=("@method" "@authority" "@path" "signature-key");created=1730217600
Signature: sig=:...signature bytes...:
Signature-Key: sig=jwks_uri;id="https://agent.example";kid="key-1"
scope=data.read+data.writeResponse:
The resource validates the agent's signature, creates a resource token binding the agent and access request to its identity, and returns it with the auth server identifier.
Response parameters:
resource_token(REQUIRED): The signed resource token (JWT)auth_server(REQUIRED): The HTTPS URL of the authorization serverexpires_in(OPTIONAL): Lifetime in seconds of the resource token
Example response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"resource_token": "eyJhbGciOiJFZERTQSIsInR5cCI6InJlc291cmNlK2p3dCIsImtpZCI6InJlc291cmNlLWtleS0xIn0.eyJpc3MiOiJodHRwczovL3Jlc291cmNlLmV4YW1wbGUiLCJhdWQiOiJodHRwczovL2F1dGguZXhhbXBsZSIsImFnZW50IjoiaHR0cHM6Ly9hZ2VudC5leGFtcGxlIiwiYWdlbnRfamt0IjoiTnpiTHNYaDh1RENjZC02TU53WEY0V183bm9XWEZaQWZIa3hac1JHQzlYcyIsImV4cCI6MTczMDIyMTIwMCwic2NvcGUiOiJkYXRhLnJlYWQgZGF0YS53cml0ZSJ9.signature",
"auth_server": "https://auth.example",
"expires_in": 300
}The agent makes a signed request to the auth server's agent_token_endpoint with request_type=auth.
Request parameters:
request_type(REQUIRED): Must beauth- Exactly one of the following (REQUIRED):
resource_token(string): The resource token obtained from a resource's Agent-Auth challenge or resource_token_endpoint. Used when requesting access to another resource.scope(string): Space-separated scope values. Used when the agent requests authorization to itself (agent identifier matches resource identifier) for simpler access requirements.auth_request_url(string): HTTPS URL to an Auth Request Document. Used when the agent requests authorization to itself (agent identifier matches resource identifier) for complex access requirements.
redirect_uri(REQUIRED): The callback URI for authorization code
Usage:
When an agent accesses another resource, it obtains a resource_token from that resource and presents it to the auth server. The resource token cryptographically binds the agent, resource, and access request.
When an agent requests authorization to itself (agent identifier matches resource identifier), it provides scope or auth_request_url directly. This pattern supports user authentication (SSO) and delegated API access. The returned auth token can be used both to verify user identity and by agent delegates to call the agent's APIs, solving the OIDC limitation where ID tokens and access tokens are separate. In this case, a resource token is unnecessary since the agent's HTTPSig signature already proves its identity.
Example request with resource_token:
POST /agent/token HTTP/1.1
Host: auth.example
Content-Type: application/x-www-form-urlencoded
Signature-Input: sig=("@method" "@authority" "@path" "signature-key");created=1730217600
Signature: sig=:...signature bytes...:
Signature-Key: sig=jwt;jwt="eyJhbGc..."
request_type=auth& \
resource_token=eyJhbGciOiJFZERTQSIsInR5cCI6InJlc291cmNlK2p3dCIsImtpZCI6InJlc291cmNlLWtleS0xIn0.eyJpc3MiOiJodHRwczovL3Jlc291cmNlLmV4YW1wbGUiLCJhdWQiOiJodHRwczovL2F1dGguZXhhbXBsZSIsImFnZW50IjoiaHR0cHM6Ly9hZ2VudC5leGFtcGxlIiwiYWdlbnRfamt0IjoiTnpiTHNYaDh1RENjZC02TU53WEY0V183bm9XWEZaQWZIa3hac1JHQzlYcyIsImV4cCI6MTczMDIyMTIwMCwic2NvcGUiOiJkYXRhLnJlYWQgZGF0YS53cml0ZSJ9.signature& \
redirect_uri=https://agent.example/callbackExample request with scope (agent as resource):
POST /agent/token HTTP/1.1
Host: auth.example
Content-Type: application/x-www-form-urlencoded
Signature-Input: sig=("@method" "@authority" "@path" "signature-key");created=1730217600
Signature: sig=:...signature bytes...:
Signature-Key: sig=jwks_uri;id="https://agent.example";kid="key-1"
request_type=auth& \
scope=profile+email& \
redirect_uri=https://agent.example/callbackThe auth server validates the request and responds based on policy.
Validation:
If resource_token was provided, the auth server MUST validate it (Section 6.5):
- Verify the JWT signature using the resource's JWKS
- Verify the
audclaim matches the auth server's identifier - Verify the
agentclaim matches the requesting agent's identifier - Verify the
agent_jktmatches the JWK Thumbprint of the agent's current signing key - Verify the token is not expired
- Extract the
scopeorauth_request_urlfrom the token for authorization evaluation
If scope or auth_request_url was provided directly (agent as resource), the auth server MUST:
- Verify the agent's HTTPSig signature proves the agent's identity
- Use the provided
scopeorauth_request_urldirectly for authorization evaluation - Verify the agent identifier is appropriate as the resource identifier for the requested access
Response:
Direct grant response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"auth_token": "eyJhbGc...",
"expires_in": 3600,
"refresh_token": "eyJhbGc..."
}User consent required response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"request_token": "eyJhbGciOiJub25lIn0.eyJleHAiOjE3MzAyMTgyMDB9.",
"expires_in": 600
}The request_token is an opaque value representing the pending auth request. The agent uses this at the agent_auth_endpoint to redirect the user for authentication and consent.
If the auth server responds with a request_token (indicating user consent is required), the agent directs the user to the agent_auth_endpoint for authentication and authorization.
Flow:
-
Agent receives request_token: After making an auth request (Section 9.3), the auth server responds with:
{ "request_token": "eyJhbGciOiJub25lIn0.eyJleHAiOjE3MzAyMTgyMDB9." } -
Agent redirects user: The agent redirects the user to the
agent_auth_endpointfrom auth server metadata (Section 8.2), including therequest_tokenand aredirect_urifor callback:https://auth.example/agent/auth?request_token=eyJhbGciOiJub25lIn0.eyJleHAiOjE3MzAyMTgyMDB9.&redirect_uri=https://agent.example/callback -
User authenticates and consents: At the auth server:
- User authenticates (if not already authenticated)
- Auth server displays the authorization request details (resource, scopes, agent identity)
- User reviews and grants or denies consent
- Auth server generates an authorization code bound to the request_token and redirect_uri
-
Auth server redirects back: The auth server redirects the user back to the agent's
redirect_uri:HTTP/1.1 303 See Other Location: https://agent.example/callback?code=SplxlOBeZQQYbYS6WxSbIA
-
Agent exchanges code for tokens: The agent makes an HTTPSig request to the
agent_token_endpoint(Section 9.6) with the authorization code:POST /agent/token HTTP/1.1 Host: auth.example Content-Type: application/x-www-form-urlencoded Signature-Input: sig=("@method" "@authority" "@path" "signature-key");created=1730217600 Signature: sig=:...signature bytes...: Signature-Key: sig=jwt;jwt="eyJhbGc..." request_type=code& \ code=SplxlOBeZQQYbYS6WxSbIA& \ redirect_uri=https://agent.example/callback
-
Auth server issues tokens: The auth server validates the code and agent signature, then responds with tokens:
{ "auth_token": "eyJhbGc...", "expires_in": 3600, "refresh_token": "eyJhbGc..." }
Parameters:
state(OPTIONAL): Opaque value used by the agent to maintain state between the authorization request and callback
Security considerations:
- The
request_tokenMUST be short-lived (recommended: 10 minutes) - The
redirect_uriMUST match the value provided in the initial auth request - Authorization codes MUST be single-use and short-lived (recommended: 60 seconds)
The agent exchanges the authorization code for an auth token by making a signed request to the agent_token_endpoint with request_type=code.
Request parameters:
request_type(REQUIRED): Must becodecode(REQUIRED): The authorization code
Example request:
POST /agent/token HTTP/1.1
Host: auth.example
Content-Type: application/x-www-form-urlencoded
Signature-Input: sig=("@method" "@authority" "@path" "signature-key");created=1730217600
Signature: sig=:...signature bytes...:
Signature-Key: sig=jwt;jwt="eyJhbGc..."
request_type=code&code=AUTH_CODE_123Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"auth_token": "eyJhbGc...",
"expires_in": 3600,
"refresh_token": "eyJhbGc..."
}When the auth token expires, the agent requests a new token using the refresh token by making a signed request to the agent_token_endpoint with request_type=refresh.
Request parameters:
request_type(REQUIRED): Must berefreshrefresh_token(REQUIRED): The refresh token
Example request:
POST /agent/token HTTP/1.1
Host: auth.example
Content-Type: application/x-www-form-urlencoded
Signature-Input: sig=("@method" "@authority" "@path" "signature-key");created=1730217600
Signature: sig=:...signature bytes...:
Signature-Key: sig=jwt;jwt="eyJhbGc..."
request_type=refresh&refresh_token=eyJhbGc...Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"auth_token": "eyJhbGc...",
"expires_in": 3600
}Note: A new
refresh_tokenis not included because the existing refresh token remains valid. In AAuth, every refresh request is cryptographically signed and the refresh token is bound to the agent's instance identifier, eliminating the security rationale for rotation.
The agent makes a signed request to the resource with the auth token.
GET /api/data HTTP/1.1
Host: resource.example
Signature-Input: sig=("@method" "@authority" "@path" "signature-key");created=1730217600
Signature: sig=:...signature bytes...:
Signature-Key: sig=jwt;jwt="eyJhbGc..."The resource validates the auth token and signature, then returns the requested data if authorized.
When a resource requires user interaction (login, SSO, OAuth flow, or consent for downstream access), the resource returns a user_interaction parameter directing the agent to facilitate the interaction.
Agent-Auth response:
HTTP/1.1 401 Unauthorized
Agent-Auth: httpsig; user_interaction="https://resource-r.example/auth-flow?session=xyz789&request=abc"; resource_token="eyJhbGc..."; auth_server="https://auth2.example"Parameters:
user_interaction(string): URL at the resource where the agent should direct the userresource_token: The downstream resource tokenauth_server: The authorization server for the downstream resource
Flow:
-
Agent receives challenge: The agent extracts the
user_interactionURL from the Agent-Auth header -
Agent redirects user: The agent redirects the user to the
user_interactionURL, appending areturn_urlparameter:HTTP/1.1 303 See Other Location: https://resource-r.example/auth-flow?session=xyz789&request=abc&return_url=https://agent-a.example/callback
-
Resource interacts with user: The resource hosts the interaction endpoint and:
- Validates the request context (session parameter)
- Redirects the user to the auth server with the resource's identity
- Receives authorization from the auth server
- Stores the authorization result keyed by the session
-
User returns to agent: The resource redirects the user back to the
return_urlprovided by the agent -
Agent retries request: The agent makes the original request again with the same session context. The resource now has authorization and can process the request.
Security considerations:
- Resources MUST validate that
return_urluses HTTPS unless in development environments - Agents MUST NOT include sensitive data in the
return_urlquery parameters - Resources MUST expire session state after reasonable timeout and failed attempts
Token exchange enables autonomous multi-hop resource access. When a resource needs to call a downstream resource to fulfill a request, it acts as an agent to obtain the necessary authorization. The resource presents the upstream auth token to the downstream auth server, which validates the authorization chain and issues a new auth token.
When this applies:
A resource acts as an agent when it:
- Receives a request from an agent with an auth token
- Needs to access a downstream resource to fulfill the request
- Receives an Agent-Auth challenge from the downstream resource
- Makes a token exchange request to obtain authorization for the downstream resource
Request parameters:
request_type(REQUIRED): Must beexchangeresource_token(REQUIRED): The resource token from the downstream resource's Agent-Auth challenge
The upstream auth token MUST be presented via the Signature-Key header using sig=jwt;jwt="<upstream-auth-token>".
Example request:
POST /agent/token HTTP/1.1
Host: auth2.example
Content-Type: application/x-www-form-urlencoded
Signature-Input: sig=("@method" "@authority" "@path" "signature-key");created=1730217600
Signature: sig=:...signature bytes...:
Signature-Key: sig=jwt;jwt="eyJhbGc..."
request_type=exchange& \
resource_token=eyJhbGciOiJFZERTQSIsInR5cCI6InJlc291cmNlK2p3dCIsImtpZCI6InJlc291cmNlLWtleS0xIn0.eyJpc3MiOiJodHRwczovL3Jlc291cmNlMi5leGFtcGxlIiwiYXVkIjoiaHR0cHM6Ly9hdXRoMi5leGFtcGxlIiwiYWdlbnQiOiJodHRwczovL3Jlc291cmNlMS5leGFtcGxlIiwiYWdlbnRfamt0IjoiTnpiTHNYaDh1RENjZC02TU53WEY0V183bm9XWEZaQWZIa3hac1JHQzlYcyIsImV4cCI6MTczMDIyMTIwMCwic2NvcGUiOiJkYXRhLnJlYWQifQ.signatureResponse:
HTTP/1.1 200 OK
Content-Type: application/json
{
"auth_token": "eyJhbGc...",
"expires_in": 3600
}The auth token is bound to the resource's signing key (presented in the Signature-Key header) and includes an act claim showing the delegation chain.
Auth server validation:
The downstream auth server (Auth Server 2) MUST:
- Validate the request signature: Verify the HTTPSig signature using the key in the Signature-Key header
- Validate the resource token (Section 6.5):
- Verify the JWT signature using the downstream resource's JWKS
- Verify the
audclaim matches the downstream auth server's identifier - Verify the
agentclaim matches the requesting resource's identifier - Verify the
agent_jktmatches the JWK Thumbprint of the requesting resource's signing key - Verify the token is not expired
- Extract the
scopeorauth_request_urlfor authorization
- Validate the upstream token (presented in the
Signature-Keyheader withscheme=jwt):- Verify the JWT signature using the upstream auth server's (Auth Server 1) published JWKS
- Verify the token has not expired
- Verify the
audclaim matches the requesting resource
- Establish trust: Verify that Auth Server 1 is a trusted auth server (federation trust relationship)
- Authorize the exchange: Verify that the requested scope from the resource token is appropriate given the upstream authorization
- Bind to requester's key: Issue an auth token with the
cnfclaim matching the key presented in the Signature-Key header - Include delegation chain: Include an
act(actor) claim showing the upstream agent
Auth token claims:
The resulting auth token MUST include:
iss: Auth Server 2's identifiersub: The user identifier from the upstream token (maintained through the chain)aud: The downstream resource (Resource 2)agent: The resource acting as agent (Resource 1)cnf: Confirmation claim binding the token to Resource 1's signing keyact: Actor claim showing the delegation chainexp,iat,nbf: Standard time claims- Additional claims as appropriate (scopes, identity claims, etc.)
Actor (act) claim:
The act claim represents the party that delegated authority to the current agent. It is a JSON object containing:
agent(REQUIRED): The HTTPS URL of the upstream agent (from the upstream token'sagentclaim)agent_delegate(OPTIONAL): The upstream agent delegate identifier (from the upstream token'sagent_delegateclaim, if present)sub(OPTIONAL): The user identifier (from the upstream token'ssubclaim, if present and different from the current token'ssub)act(OPTIONAL): Nested actor claim for multi-hop delegation chains beyond two levels
This enables downstream resources to verify the complete delegation chain and make authorization decisions based on the full context of who initiated the request and which intermediaries were involved.
Example act claim:
{
"agent": "https://resource1.example",
"agent_delegate": "api-service-instance-abc",
"sub": "user-12345"
}Security considerations:
- Federation trust required: Auth Server 2 must have an established trust relationship with Auth Server 1 to validate upstream tokens
- Scope narrowing: The downstream scope should typically be narrower than or equal to the upstream authorization
- Chain depth limits: Auth servers MAY enforce limits on delegation chain depth to prevent abuse
- User context preservation: The
subclaim MUST be maintained through the chain to preserve user identity - Refresh tokens: Exchange requests do not return refresh tokens; the resource must re-exchange when tokens expire
Comparison with user_interaction:
For scenarios involving user consent across multiple resources, the user_interaction mechanism (Section 9.9) provides a complementary solution that bubbles authorization requirements up to the user. Token exchange is specifically for autonomous multi-hop scenarios where user interaction is not required or feasible.
The following request_type values are reserved for future work and are not defined in this version of the specification:
Device Authorization Flow:
request_type=device_auth- Initiate device authorization flow- May return
auth_token(direct grant) ordevice_code+user_code+verification_uri(user interaction needed)
- May return
request_type=device_code- Poll or exchange device_code for auth_token
CIBA (Client Initiated Backchannel Authentication):
request_type=backchannel_auth- Initiate backchannel authentication- May return
auth_token(direct grant) orauth_req_id(authentication in progress)
- May return
request_type=backchannel_poll- Poll with auth_req_id for auth_token
Auth servers MAY advertise supported request types in metadata using the request_types_supported field.
AAuth uses HTTP Message Signing (HTTPSig) as defined in RFC 9421. This section provides a profile for AAuth implementations.
All requirements in this section apply equally to AAuth receivers, which include both Authorization Servers and Resource Servers. When this section refers to "the receiver," it means any server verifying HTTP Message Signatures in an AAuth context.
All AAuth requests MUST include the Signature-Key header, and signature-key MUST always be a covered component in the HTTP Message Signature. Requests missing the Signature-Key header or not covering signature-key in the signature MUST be rejected.
The Signature-Key header provides the keying material required to verify the HTTP signature. Key discovery mechanisms are defined in the Signature-Key specification.
Structure:
Signature-Key is an RFC 8941 Structured Fields Dictionary. The dictionary:
- MUST contain exactly one member
- The dictionary member name is the signature label
- The dictionary member value is an Inner List whose parameters describe key discovery
AAuth Profile:
AAuth supports one signature per request. Multiple signatures are out of scope.
Note: AAuth defines a single end-to-end signature between the client and the AAuth receiver (Authorization Server or Resource Server). Intermediaries or hop-by-hop signatures MUST NOT add, remove, or modify AAuth signature material.
Supported schemes:
scheme=hwk- Header Web Key (pseudonymous, no identity)scheme=jwks_uri- Identified signer (explicit identity with JWKS discovery)scheme=x509- X.509 certificate chain (explicit identity via PKI)scheme=jwt- JWT containing confirmation key (agent-token or auth-token)
Example:
Signature-Input: sig=("@method" "@authority" "@path" "signature-key");created=1730217600
Signature: sig=:MEQCIAZg1fF0...:
Signature-Key: sig=hwk;kty="OKP";crv="Ed25519";x="JrQLj5P..."
Receivers MUST perform these steps:
- Parse
Signature-Keyas a Structured Fields Dictionary - Verify
Signature-Keycontains exactly one dictionary member; otherwise reject - Let the dictionary member name be Lk
- Parse
Signature-Inputand verify it contains exactly one label Ls; otherwise reject - Parse
Signatureand verify it contains exactly one label; otherwise reject - Verify that Lk, Ls, and the label in
Signatureare identical; if any mismatch occurs, reject
This algorithm ensures unambiguous correlation of the signature label across all three headers
Implementations MUST support:
ed25519(EdDSA using Curve25519)
Implementations MAY support additional algorithms from the HTTP Signature Algorithms Registry established by RFC 9421.
Unless the server specifies otherwise (see Section 10.3.3), HTTP Message Signatures in AAuth MUST cover the following components:
Always required:
@method: The HTTP request method@authority: The request authority (see Section 10.3.2)@path: The request pathsignature-key: The Signature-Key header value. Coveringsignature-keyintegrity-protects the key discovery inputs and prevents intermediaries from swapping or mutating the key reference without invalidating the signature
Conditional:
@query: MUST be included if and only if the request target contains a query string (indicated by the presence of?)@queryMUST NOT be included when no query string is present
Optional:
nonce: SHOULD be included for non-idempotent requests (see Section 10.5)
Each AAuth receiver MUST be configured with one or more canonical authorities. A canonical authority consists of:
- The host (DNS name or IP address)
- The port, if non-default for the scheme
The canonical authority represents the authority value that callers are expected to use when making requests.
When computing the signature base, the receiver MUST use the configured canonical authority as the value of @authority. The receiver MUST NOT derive @authority from request headers such as Host, Forwarded, X-Forwarded-Host, or similar headers.
If the receiver's local routing or configuration indicates that the request was not received under an expected canonical authority, the receiver MUST reject the request.
Note: Implementations that are reachable under multiple authorities (e.g., multiple DNS names or load-balanced endpoints) MAY select among configured canonical authorities based on local routing information, provided the selected authority is one the receiver has been configured to accept.
Any AAuth server (resource, agent, or authorization server) MAY require additional covered components beyond the defaults by publishing the additional_signature_components property in its server metadata.
{
"additional_signature_components": ["content-type", "content-digest"]
}When present in server metadata, clients making signed requests to that server MUST include the specified components in the signature.
Requirements for body-related components (content-type, content-digest) apply only to requests that contain a body. When content-digest is required, it MUST conform to RFC 9530.
Servers that require content-digest accept the implementation complexity of raw body handling for signature verification.
The Signature-Input header MUST include:
created: Signature creation timestamp (Unix time)
The created timestamp MUST NOT be more than 60 seconds in the past or future relative to the receiver's current time, unless the receiver's policy specifies a different tolerance.
The created parameter provides time-based bounds on signature validity and limits the window for replay attacks. However, the created timestamp alone does not prevent multiple replays of the same signed request within the validity window. For stronger replay protection on non-idempotent operations, receivers SHOULD require the nonce component (see Section 10.5).
AAuth defines an OPTIONAL nonce mechanism for stronger replay protection beyond time-based validation.
Nonce header:
- Header field name:
Nonce - Value format: base64url encoding (no padding) of at least 96 bits (12 bytes) of cryptographic entropy
- Example:
Nonce: Y3VyaW91c2x5Y3VyaW91cw
When to use nonces:
- Clients SHOULD include a
Nonceheader for non-idempotent requests (POST, PUT, DELETE, PATCH) - Receivers SHOULD require nonces for state-changing operations
- Clients MAY omit nonces for idempotent operations (GET, HEAD) where replay is acceptable
Nonce signature coverage:
When a Nonce header is present in the request, it MUST be included as a covered component in the HTTP Message Signature.
Receiver validation: When a receiver requires or accepts nonces:
- Verify the
Nonceheader is covered by the signature - Verify the nonce has sufficient entropy (at least 96 bits)
- Check that the nonce has not been used previously within the replay window (determined by the
createdtimestamp tolerance) - Store the nonce in a replay cache to prevent reuse
Replay cache scoping: Receivers SHOULD scope their replay cache at minimum by:
- Canonical authority (the
@authorityvalue) - Public key identifier (derived from the
Signature-Keyheader) - Nonce value
This scoping ensures nonces are unique per (authority, key, nonce) tuple within the time window, preventing replay attacks without requiring global nonce tracking.
The following examples demonstrate signature coverage for different request patterns. Examples 1-4 show the default covered components; Example 5 shows server-specific requirements. All examples use scheme=hwk for brevity; the same component coverage applies to scheme=jwks_uri, scheme=x509, and scheme=jwt.
Example 1: GET request without query or body
GET /api/data HTTP/1.1
Host: resource.example
Signature-Input: sig=("@method" "@authority" "@path" "signature-key");created=1730217600
Signature: sig=:MEQCIAZg1fF0...:
Signature-Key: sig=hwk;kty="OKP";crv="Ed25519";x="JrQLj5P..."Example 2: GET request with query, no body
GET /api/data?user=alice&limit=10 HTTP/1.1
Host: resource.example
Signature-Input: sig=("@method" "@authority" "@path" "@query" "signature-key");created=1730217600
Signature: sig=:MEQCIAZg1fF0...:
Signature-Key: sig=hwk;kty="OKP";crv="Ed25519";x="JrQLj5P..."Example 3: POST request with body (default coverage)
POST /api/data HTTP/1.1
Host: resource.example
Content-Type: application/json
Signature-Input: sig=("@method" "@authority" "@path" "signature-key");created=1730217600
Signature: sig=:MEQCIAZg1fF0...:
Signature-Key: sig=hwk;kty="OKP";crv="Ed25519";x="JrQLj5P..."
{"action":"update","value":42}Example 4: POST request with nonce (recommended for non-idempotent operations)
POST /api/data HTTP/1.1
Host: resource.example
Content-Type: application/json
Nonce: Y3VyaW91c2x5Y3VyaW91cw
Signature-Input: sig=("@method" "@authority" "@path" "nonce" "signature-key");created=1730217600
Signature: sig=:MEQCIAZg1fF0...:
Signature-Key: sig=hwk;kty="OKP";crv="Ed25519";x="JrQLj5P..."
{"action":"update","value":42}Example 5: POST request with body integrity (server-specific requirement)
When a server requires body integrity via additional_signature_components: ["content-type", "content-digest"]:
POST /api/data HTTP/1.1
Host: resource.example
Content-Type: application/json
Content-Digest: sha-256=:X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=:
Signature-Input: sig=("@method" "@authority" "@path" "content-type" "content-digest" "signature-key");created=1730217600
Signature: sig=:MEQCIAZg1fF0...:
Signature-Key: sig=hwk;kty="OKP";crv="Ed25519";x="JrQLj5P..."
{"action":"update","value":42}This section describes how to obtain the public key for verifying HTTP Message Signatures based on the Signature-Key header.
General Procedure:
Receivers MUST first perform the label selection algorithm described in Section 10.1.1. After successfully extracting and validating the signature label:
- Extract the
schemeparameter from theSignature-Keydictionary member - Follow the scheme-specific verification procedure below
For scheme=hwk (Header Web Key - Pseudonymous):
- Extract key parameters directly from the dictionary member (kty, crv, x, etc.)
- Reconstruct the public key from the parameters
- Verify the HTTPSig signature using the reconstructed key
For scheme=jwks_uri (JWKS URI Discovery - Identified Signer):
- REQUIRED parameters:
id(signer identifier as HTTPS URL),well-known(metadata document name),kid(key identifier) - Discovery procedure:
- Extract
id,well-known, andkidfrom the dictionary member - Fetch metadata from
{id}/.well-known/{well-known}via HTTPS - Parse as JSON metadata document
- Extract
jwks_uriproperty from metadata - Fetch JWKS from
jwks_urivia HTTPS - Match the key by
kid - Verify the HTTPSig signature using the matched public key
- Extract
For scheme=x509 (X.509 Certificate Chain):
- Extract
x5u(certificate URL) andx5t(certificate thumbprint) from the dictionary member - Check cache for certificate with matching
x5tthumbprint - If cached certificate found and still valid, skip to step 6
- Fetch the PEM file from the
x5uURL - Parse and validate the X.509 certificate chain:
- Verify chain of trust to a trusted root CA
- Check certificate validity (not expired, not revoked via CRL/OCSP)
- Validate certificate policies and constraints
- Verify
x5tmatches BASE64URL(SHA256(DER_bytes_of_leaf_certificate))
- Extract the public key from the end-entity certificate
- Verify the HTTPSig signature using the extracted public key
- Cache the certificate indexed by
x5tfor future requests
For scheme=jwt (Agent Token or Auth Token):
When Signature-Key uses scheme=jwt, the JWT MUST be validated first according to the relevant AAuth JWT profile before the cnf.jwk claim can be trusted for HTTPSig verification.
- Extract the JWT from the Signature-Key header
- Parse the JWT and determine token type from
typin JOSE header - Validate the JWT completely according to its type:
- If
typis"agent+jwt": Follow all validation steps in Section 5.7 - If
typis"auth+jwt": Follow all validation steps in Section 7.7 - This includes verifying the JWT signature, issuer, audience, expiration, and all required claims
- If
- Only after successful JWT validation, extract the public key from the JWT's
cnf.jwkclaim - Verify the HTTPSig signature using the extracted public key
The two-step validation provides distinct security properties:
- JWT validation establishes the token's issuer, audience, expiration, and authorization semantics
- HTTPSig verification proves proof-of-possession of the private key corresponding to
cnf.jwk
Both validations MUST succeed for the request to be authenticated. This requirement applies equally to Authorization Servers and Resource Servers.
Status: This section describes the Auth Request Document format, which is expected to be defined in a separate specification. The semantics are outlined here; the complete schema and additional features will be detailed in a dedicated document.
The Auth Request Document provides a structured format for conveying rich authorization requirements. When a resource needs to request authorization from an agent, it can:
- Inline simple requirements using the
scopeparameter in Agent-Auth headers - Reference complex requirements using the
auth_request_urlparameter pointing to an Auth Request Document URL
The auth_request_url parameter appears in Agent-Auth headers where resources use it to point agents to detailed authorization requirements. For token exchange scenarios, the auth_request_url can specify downstream authorization requirements that the downstream auth server will need to validate.
An Auth Request Document is a JSON document retrieved via HTTPS that describes:
- Resource identification: Which resource is requesting authorization
- Scopes: What access is being requested
- Authorization context: Additional details about the request (purpose, data accessed, duration, conditions)
- User-facing descriptions: Human-readable explanations for consent screens
- Exchange requirements: For token exchange scenarios, specifies downstream resource access needs
- Encryption public key: (OPTIONAL) A JWK (JSON Web Key) containing the resource's public encryption key. When present, the auth server MAY encrypt the auth token using this key to preserve privacy of token contents from the agent. Only the resource can decrypt the token using its corresponding private key.
- Auth Request Documents MUST be served over HTTPS
- Documents SHOULD be signed to enable offline verification (format TBD in separate specification)
- Documents SHOULD include expiration times to prevent stale authorization requests
The complete Auth Request Document specification will define:
- JSON schema for the document format
- Signing and verification mechanisms
- Caching and validation rules
- Additional authorization context fields
- Internationalization for user-facing descriptions
AAuth reuses the OAuth 2.0 error response format and error codes (RFC 6749 Section 5.2) where applicable.
Error responses follow the OAuth 2.0 structure and MUST be returned with an appropriate HTTP status code (typically 400 or 401) and a JSON body or as query parameters in a redirect response.
error(REQUIRED): A single ASCII error codeerror_description(OPTIONAL): Human-readable additional informationerror_uri(OPTIONAL): A URI with more information about the error
Example:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": "invalid_request",
"error_description": "Missing required parameter: redirect_uri"
}AAuth defines the following error codes in addition to those defined by OAuth 2.0:
The HTTP Message Signature is missing, malformed, or verification failed. This includes cases where:
- The
Signature,Signature-Input, orSignature-Keyheaders are missing - The signature does not cover the required components
- The signature verification fails using the public key from
Signature-Key - The
createdtimestamp is outside the acceptable time window
When the signature is missing required components, the response SHOULD include a required_components field listing the components the resource requires:
{
"error": "invalid_signature",
"error_description": "Signature missing required components",
"required_components": ["@method", "@authority", "@path", "signature-key", "content-type", "content-digest"]
}The agent token is missing, malformed, expired, or signature verification failed.
The resource token is missing, malformed, expired, or signature verification failed.
The auth token is missing, malformed, expired, or signature verification failed.
The key binding verification failed. The public key used to sign the request does not match the key bound in the token (via cnf or agent_jkt claim).
- All participants use HTTP Message Signing for message integrity and replay protection
- Agent tokens, auth tokens, and resource tokens are all proof-of-possession tokens
- Tokens are reusable for their valid lifetime; replay prevention is achieved through per-request signatures
- Agent server, auth server, and resource key rotation is achieved by updating the JWKS at each origin's
jwks_uri - Agent delegates rotate their keys frequently (ephemeral keys at restart or persisted keys per policy) by obtaining new agent tokens
- Resource identity: Resources have provable identity via published JWKS and issue signed resource tokens to cryptographically bind access requests to their identity
- Confused deputy prevention: Resource tokens include the
agentclaim, binding each access request to a specific agent. This prevents an attacker from substituting a different resource identifier in the authorization flow. - MITM prevention: Resource tokens are signed by the resource using its private key. Auth servers verify the signature using the resource's JWKS, proving the authorization request originated from the legitimate resource, not an attacker impersonating it.
- Request integrity: The
agent_jktclaim in resource tokens binds the access request to the agent's current signing key (JWK Thumbprint per RFC 7638), preventing token reuse with different keys - Refresh tokens are bound to:
- Agent server: agent identifier (
agentclaim) only - Agent delegate: agent identifier (
agentclaim) +sub(agent delegate identifier)
- Agent server: agent identifier (
- Refresh tokens do not require rotation due to proof-of-possession binding and per-request signatures
This specification registers the following identifiers in their respective IANA registries.
Registry: Well-Known URIs (RFC 8615)
URI suffix: aauth-agent
- Change controller: IETF
- Specification document: This specification, Section 8.1
- Related information: Metadata document for AAuth agent servers
URI suffix: aauth-issuer
- Change controller: IETF
- Specification document: This specification, Section 8.2
- Related information: Metadata document for AAuth authorization servers
URI suffix: aauth-resource
- Change controller: IETF
- Specification document: This specification, Section 8.3
- Related information: Metadata document for AAuth resources
Registry: Media Types
Type name: application
- Subtype name:
agent+jwt - Required parameters: None
- Optional parameters: None
- Encoding considerations: Binary (JWT, base64url-encoded)
- Security considerations: See Section 13 of this specification
- Interoperability considerations: None
- Published specification: This specification, Section 5.2
- Applications that use this media type: AAuth agent delegates
- Additional information: JWT type value for agent tokens
- Person & email address to contact for further information: Dick Hardt, [email protected]
- Intended usage: COMMON
- Restrictions on usage: None
- Change controller: IETF
Type name: application
- Subtype name:
auth+jwt - Required parameters: None
- Optional parameters: None
- Encoding considerations: Binary (JWT, base64url-encoded)
- Security considerations: See Section 13 of this specification
- Interoperability considerations: None
- Published specification: This specification, Section 7.2
- Applications that use this media type: AAuth auth servers and resource servers
- Additional information: JWT type value for auth tokens
- Person & email address to contact for further information: Dick Hardt, [email protected]
- Intended usage: COMMON
- Restrictions on usage: None
- Change controller: IETF
Type name: application
- Subtype name:
resource+jwt - Required parameters: None
- Optional parameters: None
- Encoding considerations: Binary (JWT, base64url-encoded)
- Security considerations: See Section 13 of this specification
- Interoperability considerations: None
- Published specification: This specification, Section 6.2
- Applications that use this media type: AAuth resources and auth servers
- Additional information: JWT type value for resource tokens
- Person & email address to contact for further information: Dick Hardt, [email protected]
- Intended usage: COMMON
- Restrictions on usage: None
- Change controller: IETF
Registry: HTTP Field Names (RFC 9110)
Field name: Agent-Auth
- Status: permanent
- Specification document: This specification, Section 4
- Comments: Response header indicating AAuth authentication and authorization requirements
Registry: JSON Web Token (JWT) Type Values
Type value: agent+jwt
- Abbreviation for MIME Type:
application/agent+jwt - Change controller: IETF
- Specification document: This specification, Section 5.2
Type value: auth+jwt
- Abbreviation for MIME Type:
application/auth+jwt - Change controller: IETF
- Specification document: This specification, Section 7.2
Type value: resource+jwt
- Abbreviation for MIME Type:
application/resource+jwt - Change controller: IETF
- Specification document: This specification, Section 6.2
Registry: JSON Web Token Claims (RFC 7519)
Claim name: agent
- Claim description: Agent identifier (HTTPS URL)
- Change controller: IETF
- Specification document: This specification, Section 6.3
Registry: AAuth Parameters (new registry)
This specification establishes a new IANA registry for AAuth protocol parameters used in requests and responses.
Registration procedure: Specification Required
Parameters registered by this specification:
Parameter name: request_type
- Parameter usage location: token request
- Change controller: IETF
- Specification document: This specification, Section 9.3
- Description: Type of request (auth, code, refresh, device_auth, backchannel_auth, etc.)
Parameter name: request_token
- Parameter usage location: authorization request
- Change controller: IETF
- Specification document: This specification, Section 9.4
- Description: Opaque token representing a pending authorization request
Parameter name: auth_token
- Parameter usage location: token response
- Change controller: IETF
- Specification document: This specification, Section 9.4
- Description: AAuth authorization token (JWT)
AAuth-specific error codes are defined in Section 12.2. These error codes extend the OAuth 2.0 error response framework for AAuth-specific validation failures including signature validation, agent token validation, and key binding verification.
The registration of these error codes in an appropriate IANA registry is to be determined based on whether AAuth establishes its own error registry or extends an existing OAuth error registry.
Dick Hardt Hellō Identity Email: [email protected] URI: https://github.com/DickHardt