Agent Token (sig=jwt)
June 3, 2026 · View on GitHub
Overview
The agent presents its full agent token inline. The resource (or Person Server) learns the agent's identity, issuer, and Person Server URL. See federated demo. Required for all Person Server flows.
When to Use
- Three-party flows (PS-asserted, federated) — REQUIRED by spec
- When the resource needs to discover the agent's Person Server (from the
psclaim) - When the resource needs verified agent identity with issuer attestation
Prerequisite: Agent must have an aa-agent+jwt — either self-issued (hosted services that publish their own JWKS) or obtained from an Agent Provider (CLI/desktop agents that enrol).
Code Example
Hosted service (self-issued):
using AAuth.Crypto;
using AAuth;
var key = AAuthKey.Generate();
using var client = AAuthClientBuilder.SelfIssuing(key)
.As("https://my-service.example", "aauth:my-service@my-service.example")
.WithKid("svc-key-1")
.WithPersonServer("https://ps.example")
.WithChallengeHandling()
.Build();
var response = await client.GetAsync("https://resource.example/data");
Advanced: Custom Token Building
For scenarios requiring additional claims, custom lifetimes, or non-standard flows,
use the full AgentTokenBuilder via WithTokenRefresh:
using var client = new AAuthClientBuilder(key)
.WithTokenRefresh((ctx, ct) => Task.FromResult(new AgentTokenBuilder
{
Issuer = "https://my-service.example",
Subject = "aauth:my-service@my-service.example",
KeyId = "svc-key-1",
Key = key,
PersonServer = "https://ps.example",
AdditionalClaims = new Dictionary<string, JsonNode?>
{
["attestation"] = "platform-verified",
},
}.Build()))
.WithChallengeHandling("https://ps.example")
.Build();
CLI/Desktop agent (AP-enrolled):
using AAuth.Agent;
using AAuth.Crypto;
using AAuth;
var keyStore = FileKeyStore.Default();
var key = await keyStore.LoadAsync(configuration["AAuth:LocalKeyHandle"]!);
var apRefreshEndpoint = configuration["AAuth:ApRefreshEndpoint"]!;
using var client = AAuthClientBuilder.Enrolled(key!)
.RefreshingFrom(apRefreshEndpoint, configuration["AAuth:LocalKeyHandle"]!)
.WithKeyStore(keyStore)
.WithChallengeHandling("https://ps.example")
.Build();
var response = await client.GetAsync("https://resource.example/data");
Manual Setup
var provider = new JwtSignatureKeyProvider(() => agentToken);
var handler = new AAuthSigningHandler(key, provider)
{
InnerHandler = new HttpClientHandler()
};
using var client = new HttpClient(handler);
What the Resource Sees
Signature-Key: sig=jwt;jwt="eyJhbGciOi..."- Resource decodes the JWT: finds
iss(agent's own URL or AP),sub(agent ID),cnf.jwk(bound key), optionallyps(Person Server URL) - Resource verifies: JWT signature (against issuer's JWKS via
{iss}/.well-known/aauth-agent.json) + request signature (againstcnf.jwk)
Verification
When the resource sees a ps claim, it can issue a resource token challenging the agent to get authorization from that PS. This is the entry point to PS-asserted and federated access.
Further Reading
- Call Chaining — multi-hop delegation with
UseJwtandupstream_token - Federated Demo
- PS-Asserted Access
- Bootstrap