Skip to content

Phase 2: Resource server, signature verification, and three-party flow#6

Merged
dasiths merged 8 commits into
mainfrom
dasithw/phase-2
May 18, 2026
Merged

Phase 2: Resource server, signature verification, and three-party flow#6
dasiths merged 8 commits into
mainfrom
dasithw/phase-2

Conversation

@dasiths
Copy link
Copy Markdown
Collaborator

@dasiths dasiths commented May 18, 2026

Phase 2: .NET AAuth SDK — Resource server, verification, and three-party flow

Implements Phase 2 of the .NET AAuth SDK implementation plan. Phase 1 covered issuer-side primitives (keys, agent JWT, outbound RFC 9421 signing). Phase 2 adds receiver-side verification, resource/auth token issuance, discovery, and the full three-party challenge/exchange flow, plus a working WhoAmI sample.

SDK additions (src/AAuth/)

Area Types
HTTP signature verification AAuthVerifier, AAuthVerificationMiddleware, SignatureKeyParser
Tokens ResourceTokenBuilder, AuthTokenBuilder, TokenVerifier (sync + VerifyWithJwksAsync)
Headers AAuthRequirementHeader
Discovery MetadataClient, JwksClient (with caching + rate limiting), WellKnownEndpoints.MapAAuthResourceWellKnown
Agent flow AAuthTokenHolder, TokenExchangeClient, ChallengeHandler

EdDSA JWT signing/verification is implemented via BouncyCastle (native EdDSA isn't available on this .NET 10 runtime).

Samples

  • samples/WhoAmI/ — new ASP.NET Core minimal API that serves /.well-known/aauth-resource.json + /.well-known/jwks.json, verifies inbound signatures, mints a resource_token and returns 401 AAuth-Requirement when an agent token lacks the required person delegation, and returns 200 + claims when a valid PS-issued auth token is presented.
  • samples/AgentConsole/ — extended with --ps <url> to drive the full three-party flow via ChallengeHandler.

Tests

  • tests/AAuth.Tests/ — 92 tests covering every new public type plus Integration/WhoAmIFlowTests.cs, which uses WebApplicationFactory<Program> to host both WhoAmI and a mock PS in-process and routes traffic between them with a host-based message handler. Covers both identity-based and full three-party paths.
  • tests/AAuth.Conformance/ — 5 new spec-traceable test files for agent-token verification, Signature-Key header, RFC 9421 covered components, resource-token structure, and discovery endpoints. README section→file map updated.

Final run: Passed: 139, Failed: 0 (92 SDK + 47 conformance).

Other changes

  • AAuth.slnx updated to include samples/WhoAmI.
  • Root README.md rewritten with Phase 2 status banner, four-party primer, SDK component table, sample run instructions (identity-based + three-party), and a Testing section.
  • Removed obsolete hello-world/ placeholder project.

How to try it

dotnet build AAuth.slnx
dotnet test  AAuth.slnx

# Terminal 1
dotnet run --project samples/WhoAmI

# Terminal 2 — identity-based
dotnet run --project samples/AgentConsole -- http://localhost:5000
# Terminal 2 — three-party (needs a PS implementation)
dotnet run --project samples/AgentConsole -- http://localhost:5000 --ps https://your-ps.example

dasiths added 5 commits May 18, 2026 14:05
- Add AAuthUrl.IsHttpsOrLoopback helper; route all token builders and
  WellKnownEndpoints through it so loopback http:// (e.g. the WhoAmI
  sample's default issuer) is accepted without env-var escape hatches.
- AAuthVerifier gains MaxFutureSkew (default 5s); the freshness window
  for created is now asymmetric (MaxAge backwards, MaxFutureSkew
  forwards) instead of symmetric MaxAge in both directions.
- UseAAuthVerification now resolves AAuthVerifier from DI when none is
  passed explicitly, honouring DI-registered verifier instances.
- AAuthTokenHolder._token marked volatile to document release/acquire
  semantics for cross-thread token rotation.
- WhoAmI sample plumbs AAuth:SignatureWindow config through both the
  published metadata and the verifier's MaxAge; KeyId/Scope literals
  hoisted to ResourceKid/ResourceScope constants.
- Drop unused NSign.Client + NSign.BouncyCastle packages; reference
  BouncyCastle.Cryptography 2.6.2 directly on src/AAuth/AAuth.csproj.
- Add ThreePartyChallenge_Returns401WithResourceToken integration test
  that bypasses ChallengeHandler and asserts the raw 401 shape +
  resource_token claim set.
- Mark the in-process mock PS in WhoAmIFlowTests with a Phase 3 follow-
  up TODO to migrate to samples/MockPersonServer/ once it ships.
- Sync implementation-plan.md: tick Phase 2 DoD checkboxes, add a
  Phase 2 self-review hardening subsection, update Phase 1 NuGet
  pinning + Phase 2 sections to reflect NSign removal, AAuthRequirement
  parser merge, and AAuthSigningHandler composition.
Phase tags belong in the implementation plan, not in shipped assets that
describe the code's current behaviour. The lone surviving reference is
the TODO marker on the in-process mock PS in WhoAmIFlowTests, which
still points at the work tracked under Phase 3 \u00a73.1.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Implements Phase 2 of the .NET AAuth SDK by adding receiver-side verification, discovery/JWKS resolution, and the full three-party challenge/exchange flow with an end-to-end WhoAmI sample and expanded test coverage.

Changes:

  • Added inbound RFC 9421 signature verification (AAuthVerifier + ASP.NET middleware) and token verification (TokenVerifier with JWKS/metadata discovery).
  • Implemented resource/auth token issuance and the three-party challenge → exchange → retry flow (agent + server components).
  • Added WhoAmI sample plus extensive unit, conformance, and integration tests; updated solution and docs accordingly.
Show a summary per file
File Description
tests/AAuth.Tests/Tokens/TokenVerifierTests.cs Unit tests for token verification happy/negative paths.
tests/AAuth.Tests/Tokens/ResourceTokenBuilderTests.cs Unit tests for resource token claim shape and validation rules.
tests/AAuth.Tests/Tokens/AuthTokenBuilderTests.cs Unit tests for auth token required claims and validation.
tests/AAuth.Tests/Integration/WhoAmIFlowTests.cs In-process end-to-end identity-based + three-party flow integration tests.
tests/AAuth.Tests/HttpSig/SignatureKeyParserTests.cs Unit tests for Signature-Key JWT extraction and cnf.jwk parsing.
tests/AAuth.Tests/HttpSig/AAuthVerifierTests.cs Unit tests for RFC 9421 signing/verifying round-trip and rejection cases.
tests/AAuth.Tests/Headers/AAuthRequirementHeaderTests.cs Unit tests for AAuth-Requirement formatting/parsing.
tests/AAuth.Tests/Discovery/MetadataClientTests.cs Unit tests for metadata URL building and TTL caching behavior.
tests/AAuth.Tests/Discovery/JwksClientTests.cs Unit tests for JWKS kid resolution, caching, and refresh throttling.
tests/AAuth.Tests/Agent/AAuthTokenHolderTests.cs Unit test for mutable carrier-token holder behavior.
tests/AAuth.Tests/AAuth.Tests.csproj Adds WhoAmI project reference and ASP.NET testing package for integration hosting.
tests/AAuth.Conformance/ResourceTokens/ResourceTokenStructureTests.cs Spec-traceable conformance tests for resource token structure requirements.
tests/AAuth.Conformance/README.md Updates Phase 2 scope and section→file mapping for conformance suite.
tests/AAuth.Conformance/HttpSignatures/SignatureKeyHeaderTests.cs Conformance coverage for Signature-Key header requirements.
tests/AAuth.Conformance/HttpSignatures/CoveredComponentsTests.cs Conformance coverage for covered-component set and created freshness behavior.
tests/AAuth.Conformance/Discovery/WellKnownMetadataTests.cs Conformance coverage for resource discovery metadata + JWKS endpoints.
tests/AAuth.Conformance/AgentTokens/AgentTokenVerificationTests.cs Conformance coverage for verifier-side agent token verification clauses.
tests/AAuth.Conformance/AgentTokens/AgentTokenStructureTests.cs Updates notes to reflect verifier-side conformance now exists.
tests/AAuth.Conformance/AAuth.Conformance.csproj Adds ASP.NET testing dependency for in-process endpoint hosting.
src/AAuth/Tokens/TokenVerifier.cs Implements EdDSA JWT verification and JWKS-based key resolution flow.
src/AAuth/Tokens/ResourceTokenBuilder.cs Implements resource token minting with claim/URL/lifetime validation.
src/AAuth/Tokens/JwtWriter.cs Shared compact JWS assembly/signing helper for token builders.
src/AAuth/Tokens/AuthTokenBuilder.cs Implements auth token minting with required-claim and lifetime validation.
src/AAuth/Tokens/AgentTokenBuilder.cs Aligns URL validation to loopback-friendly helper and updates remarks.
src/AAuth/Server/WellKnownEndpoints.cs Adds endpoint mappers for resource metadata and JWKS well-known docs.
src/AAuth/HttpSig/SignatureKeyParser.cs Parses Signature-Key header and extracts cnf.jwk public key.
src/AAuth/HttpSig/SignatureKeyHeader.cs Formats/parses Signature-Key structured-field value for JWT carrier tokens.
src/AAuth/HttpSig/AAuthVerifier.cs Verifies the AAuth RFC 9421 signature base and created freshness window.
src/AAuth/HttpSig/AAuthVerificationMiddleware.cs ASP.NET middleware to enforce signature verification and expose parsed token.
src/AAuth/HttpSig/AAuthSigningHandler.cs Updates remarks around structured-field behavior and intermediaries.
src/AAuth/Headers/AAuthRequirementHeader.cs Formats/parses AAuth-Requirement challenge header values.
src/AAuth/Discovery/MetadataClient.cs Adds cached well-known metadata fetcher.
src/AAuth/Discovery/JwksClient.cs Adds cached/rate-limited JWKS fetcher and kid resolution.
src/AAuth/Crypto/KeyStore.cs Updates remarks (Windows restriction wording).
src/AAuth/Agent/TokenExchangeClient.cs Implements PS token exchange request/response handling.
src/AAuth/Agent/ChallengeHandler.cs Adds 401 challenge handling, exchange, carrier-token swap, and retry.
src/AAuth/Agent/AAuthTokenHolder.cs Adds mutable carrier token holder used across signing and challenge handlers.
src/AAuth/AAuthUrl.cs Centralized URL validation allowing https plus loopback http for local dev.
src/AAuth/AAuth.csproj Switches to direct BouncyCastle dependency and adds ASP.NET shared framework reference.
samples/WhoAmI/WhoAmI.csproj Converts sample to ASP.NET Core web SDK and references AAuth library.
samples/WhoAmI/Program.cs Implements WhoAmI resource server: discovery, signature verification, challenge, and auth-token verification.
samples/AgentConsole/Program.cs Extends console agent to support --ps and automatic three-party exchange flow.
README.md Rewrites docs to reflect Phase 2 capabilities, samples, and testing commands.
hello-world/Program.cs Removes obsolete placeholder project source.
AAuth.slnx Adds WhoAmI sample to the solution.
.devcontainer/post-create.sh Adds idempotent bash completion + git prompt setup for the devcontainer.
.devcontainer/Dockerfile Installs bash-completion in the devcontainer image.
.agent/plans/2026-05-13-dotnet-aauth-sdk/implementation-plan.md Updates Phase 2 decisions/DoD and records self-review hardening outcomes.

Copilot's findings

  • Files reviewed: 48/48 changed files
  • Comments generated: 11

Comment thread src/AAuth/HttpSig/AAuthVerificationMiddleware.cs Outdated
Comment thread src/AAuth/Tokens/TokenVerifier.cs
Comment thread src/AAuth/Tokens/TokenVerifier.cs Outdated
Comment thread src/AAuth/Discovery/MetadataClient.cs
Comment thread samples/WhoAmI/Program.cs
Comment thread src/AAuth/Tokens/ResourceTokenBuilder.cs
Comment thread src/AAuth/Tokens/AuthTokenBuilder.cs
Comment thread README.md Outdated
Comment thread .agent/plans/2026-05-13-dotnet-aauth-sdk/implementation-plan.md
Comment thread tests/AAuth.Conformance/AAuth.Conformance.csproj Outdated
- AAuthVerificationMiddleware: UseAAuthVerification now resolves
  AAuthVerifier from app.ApplicationServices (with a default-instance
  fallback) instead of relying on UseMiddleware to bind the dependency,
  matching the documented behaviour.
- TokenVerifier: align the iss URL policy with AAuthUrl.IsHttpsOrLoopback
  (so loopback issuers accepted by the builders also verify) and
  validate iss + discovered jwks_uri BEFORE any HTTP call to close the
  SSRF surface flagged in review.
- MetadataClient.FetchAsync: deep-clone the cached JsonObject on every
  return so a mutating consumer can't poison the shared cache entry.
- WhoAmI sample: wrap AAuthKey.FromJwk(cnf) in try/catch and emit a 401
  invalid_auth_token response on malformed cnf.jwk instead of a 500.
- ChallengeHandler: parse each AAuth-Requirement header value
  independently and select the first usable auth-token requirement,
  instead of comma-joining (which AAuthRequirementHeader.Parse rejects).
- ResourceTokenBuilder / AuthTokenBuilder: add explicit null guards on
  Key (and AgentConfirmationKey) so reflection/default! callers see a
  clear InvalidOperationException rather than NullReferenceException.
- README: fix aa-rsrc+jwt -> aa-resource+jwt typo for the resource
  token media type.
- implementation-plan.md: correct the well-known mapper name to
  MapAAuthResourceWellKnown and note that AAuthRequirementHeader uses a
  hand-rolled parser (not StructuredFieldValues).
- AAuth.Conformance.csproj: swap Microsoft.AspNetCore.Mvc.Testing for
  the lighter Microsoft.AspNetCore.TestHost package since only TestHost
  APIs (UseTestServer/GetTestServer) are used.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 48/48 changed files
  • Comments generated: 2

Comment thread src/AAuth/Agent/TokenExchangeClient.cs
Comment thread src/AAuth/Tokens/TokenVerifier.cs
- TokenExchangeClient: validate the PS-advertised token_endpoint with
  AAuthUrl.IsHttpsOrLoopback AND pin it to the same origin as the
  configured personServer before POSTing. Prevents a malicious or
  compromised PS metadata document from redirecting the signed
  exchange to an arbitrary host or downgrading it to plain http.
- TokenVerifier.VerifyWithJwksAsync: move the cheap, locally-verifiable
  invariants (alg, typ, dwk) ahead of MetadataClient.FetchAsync /
  JwksClient.ResolveKeyAsync so obviously-invalid tokens fail fast
  without triggering outbound discovery calls.
Copy link
Copy Markdown
Contributor

@dickhardt dickhardt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I read over the top level material, LGTM!

I'm not a .NET expert -- so have no opinion on the implementation.

Let us know when you are ready to have links to the libraries -- or create a PR in the www repo!

@dasiths dasiths merged commit a5f0ba8 into main May 18, 2026
@dasiths dasiths deleted the dasithw/phase-2 branch May 18, 2026 15:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants