Skip to content

aauth-dev/dotnet-samples

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

224 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AAuth SDK for .NET

CI NuGet NuGet Downloads

🚧 Draft Specification — The AAuth protocol is under active development. APIs and wire formats may change as the spec evolves. See aauth-spec/ for the current draft. This SDK is not yet spec-complete — open an issue to give feedback or report bugs.

The AAuth protocol SDK for .NET — agent-to-resource authorization with cryptographic proof-of-possession. Visit aauth.dev for the full protocol documentation, tutorials, and community resources.

What is AAuth?

AAuth is a four-party authorization protocol for AI agents. Every HTTP request carries a cryptographic signature — there are no bearer tokens. See the protocol spec for full details.

The four parties are:

  • Agent — signs every outbound HTTP request (RFC 9421) and presents keying material in the Signature-Key header.
  • Resource — verifies the signature, optionally challenges with a resource_token to demand a person-scoped auth_token.
  • Person Server (PS) — represents the user; manages missions, federates to AS, issues aa-auth+jwt proving the person delegated access.
  • Access Server (AS) — issues auth tokens; enforces resource access policy.

Agent Provider (AP) is a supporting role that issues aa-agent+jwt tokens binding an agent's signing key to its identity.

The SDK supports all four signing modes (hwk, jwks_uri, jwt, jkt-jwt), the full three-party challenge/exchange flow (autonomous and deferred user-consent), signature verification middleware, resource & auth token builders, JWKS / metadata discovery, and a Blazor GuidedTour walk-through. See the SDK documentation for complete usage guides.

Access Modes

AAuth supports four resource access modes. Each adds parties and capabilities, and they build on one another — adoption is incremental. Run make demo (no Docker) to start every service plus both UIs, then follow the demo column below. For the live-Keycloak federated experience, use make demo-keycloak.

Mode Parties When to Use Signing See it in the demos
Identity-Based Agent + Resource Replacing API keys with cryptographic identity hwk / jwks_uri GuidedTour → flow 2 · Identity-based; SampleApp → /hwk and /jwks-uri
Resource-Managed (two-party) Agent + Resource Resource manages authorization itself (interaction, OAuth/OIDC, internal policy) without an external PS or AS Any Workflow guide — the resource owns the consent step
PS-Asserted (three-party) Agent + Resource + PS Resource accepts identity claims (sub, email, tenant, groups, roles) from any Person Server jwt GuidedTour → flow 3 · PS-Asserted (Direct Grant) and 4 · PS-Asserted (Deferred); SampleApp → /jwt and /deferred
Federated (four-party) Agent + Resource + PS + AS Cross-domain access with the resource's own Access Server enforcing policy jwt GuidedTour → flow 6 · Federated (Four-Party); SampleApp → /federated. Live Keycloak consent: make demo-keycloak

GuidedTour runs on http://localhost:5400 and SampleApp on http://localhost:5240. See Getting Started for the full breakdown of each mode.

See It Run

Before writing any code, watch the protocol in action. The repo ships sample services and two interactive Blazor apps. The dev container has everything pre-configured; you can also run locally with the .NET 10 SDK.

make demo   # starts every service + the stub Access Server + both UIs

Then open the two UIs and click through the modes from the table above:

Guided Tour — http://localhost:5400

Step-by-step walk-through showing every HTTP exchange, header, and token claim across all protocol flows.

Guided Tour

Sample App — http://localhost:5240

Self-contained Blazor app with one page per AAuth flow (HWK, JWKS URI, JWT direct grant, deferred user consent, call-chain multi-agent delegation, four-party federated).

Sample App

For the live-Keycloak federated experience, run make demo-keycloak instead. See samples/README.md for the full list of sample projects and configuration options.

Dev container (recommended)

Open this repo in VS Code → Reopen in Container. The container provides .NET 10, the gh CLI, and the C# Dev Kit extensions.

Local setup

Install the .NET 10 SDK, then:

dotnet build AAuth.slnx

Quick Start

dotnet add package AAuth --prerelease

The simplest mode is pseudonymous (HWK) — the agent signs every request with an inline public key. No Agent Provider, no Person Server, no registration. The resource sees a stable key thumbprint it can use for rate-limiting or access control, but doesn't know the agent's identity.

using AAuth.Crypto;
using AAuth;

var key = AAuthKey.Generate(); // Ed25519 keypair

using var client = new AAuthClientBuilder(key)
    .UseHwk() // Pseudonymous mode: inline public key in Signature-Key header
    .Build();

var response = await client.GetAsync("https://resource.example/data");
// Request is signed per RFC 9421 — the resource verifies the signature
// using the public key from the Signature-Key: sig=hwk;jkt="...";jwk="..." header

Three-Party Flow (Agent → Resource → Person Server)

The PS-Asserted flow is the primary authorization model. The resource delegates authorization to the agent's Person Server, which prompts the user for consent:

sequenceDiagram
    participant Agent
    participant Resource
    participant PS as Person Server
    participant User

    Agent->>Resource: GET /data (signed, agent token)
    Resource-->>Agent: 401 + resource_token (aud=PS)
    Agent->>PS: POST /token (signed, resource_token)
    PS->>User: Consent prompt (scope, justification)
    User-->>PS: Grant consent
    PS-->>Agent: auth_token (aa-auth+jwt)
    Agent->>Resource: GET /data (signed, auth_token)
    Resource-->>Agent: 200 OK
Loading

On the agent side, building the client with WithChallengeHandling makes the entire 401 → exchange → retry cycle automatic — your code just makes the request:

using AAuth.Crypto;
using AAuth;

var key = AAuthKey.Generate();

// A hosted service acts as its own Agent Provider (self-issuing).
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() // automatic 401 → PS exchange → retry
    .Build();

var response = await client.GetAsync("https://resource.example/data");
// 1. Agent signs GET with agent token → Resource verifies, returns 401 + resource_token
// 2. ChallengeHandler POSTs resource_token to PS token endpoint
// 3. PS validates agent, prompts user for consent, issues auth_token
// 4. Agent retries GET signed with auth_token → Resource verifies → 200 OK

What happens step by step:

  1. Agent signs the request with its agent token (Signature-Key: sig=jwt;jwt="...")
  2. Resource verifies the signature, reads the ps claim, returns 401 with a resource_token (audience = PS URL)
  3. Agent POSTs the resource_token to the PS's token endpoint (signed request)
  4. PS validates the agent token, prompts the user for consent on the requested scope
  5. User grants consent; PS issues an auth_token (aa-auth+jwt) containing identity claims (sub, email, etc.)
  6. Agent retries the original request signed with the auth_token
  7. Resource verifies the auth token signature and claims → 200 OK

See Getting Started for a detailed walk-through, including deferred consent.

Building Servers

The snippets above are agent-side (the client). Hosting a party — a resource, or a self-issuing agent service — uses the SDK's server helpers. Start with the resource, since it's the party that issues the challenge.

Resource (Server-Side)

The resource verifies signatures, publishes metadata, and issues resource token challenges:

using AAuth.Crypto;
using AAuth;
using AAuth.Server.Challenge;
using AAuth.Server.Verification;
using AAuth.Server.Metadata;

var builder = WebApplication.CreateBuilder(args);
var resourceKey = AAuthKey.Generate();

// Register AAuth resource services
builder.Services.AddAAuthResource(options =>
{
    options.Issuer = "https://resource.example";
    options.SigningKeys = new() { ["resource-key-1"] = resourceKey };
    options.ScopeDescriptions = new() { ["read"] = "Read your data" };
});

var app = builder.Build();

// Serve /.well-known/aauth-resource.json + JWKS
app.MapAAuthWellKnown();

// Verify HTTP signatures and auth tokens from trusted Person Servers
app.UseAAuthVerification(new AAuthVerificationOptions
{
    ResourceIdentifier = "https://resource.example",
    RequireIssuerVerification = true,
    TrustedAuthTokenIssuers = new HashSet<string> { "https://ps.example" },
});

// Issue 401 + resource_token when agent presents only an agent token
app.UseAAuthChallenge(new ChallengeOptions
{
    ResourceSigningKey = resourceKey,
    ResourceKeyId = "resource-key-1",
    ResourceIdentifier = "https://resource.example",
});

The UseAAuthChallenge middleware (registered after verification) automatically returns 401 with an AAuth-Requirement header containing a resource token when the agent lacks an auth token. The TrustedAuthTokenIssuers allow-list restricts which Person Servers the resource will accept auth tokens from.

Self-Hosted Agent (Server-Side)

Hosted services act as their own Agent Provider — generate a key, publish metadata, and self-issue tokens:

using AAuth.Crypto;
using AAuth;
using AAuth.Server.Metadata;

var builder = WebApplication.CreateBuilder(args);
var key = AAuthKey.Generate();
const string Kid = "svc-key-1";
var issuer = "https://my-service.example";

var app = builder.Build();

// Publish agent metadata so resources can discover the JWKS
app.MapAAuthAgentWellKnown(new AAuthAgentMetadataOptions
{
    Issuer = issuer,
    SigningKeys = new Dictionary<string, AAuthKey> { [Kid] = key },
});

// Build signed client with automatic token refresh and challenge handling
using var client = AAuthClientBuilder.SelfIssuing(key)
    .As(issuer, "aauth:my-service@my-service.example")
    .WithKid(Kid)
    .WithPersonServer("https://ps.example")
    .WithChallengeHandling()
    .Build();

See the Server Guide for the full resource-side token issuance, Person Server, and Access Server code.

Documentation

Full SDK documentation lives in docs/:

Testing

dotnet test AAuth.slnx                # full suite (unit + conformance)
dotnet test tests/AAuth.Tests         # SDK unit + integration tests only
dotnet test tests/AAuth.Conformance   # spec conformance suite only

Repository Layout

Path Description
src/AAuth/ AAuth SDK library (the NuGet package)
docs/ SDK documentation — signing modes, workflows, server guides
samples/ Sample applications — WhoAmI, Orchestrator, AgentConsole, MockPersonServer, MockAgentProvider, GuidedTour, SampleApp
tests/ Unit, integration, and spec-conformance tests
aauth-spec/ Protocol specifications (draft-01) from dickhardt/AAuth

Spec Compatibility

This SDK targets draft-01 of the AAuth specifications:

Spec Draft
draft-hardt-oauth-aauth-protocol 01
draft-hardt-aauth-bootstrap 01
draft-hardt-aauth-r3 01

Pinned to source commit c090879 (2026-05-11). See SPEC-VERSION.md for details.

Contributing

  1. Open this repo in the dev container (ensures consistent tooling).
  2. Create a branch off main.
  3. Make your changes — run dotnet build AAuth.slnx and dotnet test AAuth.slnx before submitting.
  4. Open a pull request against main.

About

AAuth .NET SDK and Samples

Resources

License

Stars

Watchers

Forks

Contributors

Languages