Skip to content

Add DPoP (RFC 9449) proof creation and server-side validation#3443

Merged
MZOLN merged 19 commits into
devfrom
kecaruso/dpop
Apr 22, 2026
Merged

Add DPoP (RFC 9449) proof creation and server-side validation#3443
MZOLN merged 19 commits into
devfrom
kecaruso/dpop

Conversation

@MZOLN
Copy link
Copy Markdown
Contributor

@MZOLN MZOLN commented Apr 10, 2026

Summary

PBI 3549154: Implement dPoP validation primitives in Wilson

Adds Microsoft.IdentityModel.Dpop — a new package implementing DPoP (Demonstrating Proof-of-Possession) per RFC 9449.

Provides both client-side proof creation and server-side proof validation with no System.Net.Http dependency.

What's included

Core types:

  • DPoPProof — client-side: creates signed DPoP proof JWTs with htm, htu, iat, jti, ath, and optional nonce claims
  • DPoPProofValidator — server-side: validates DPoP proofs per RFC 9449 §4.3 (all 12 steps), returns structured DPoPValidationResult
  • DPoPValidationOptions — configurable algorithms, lifetime, clock skew, nonce, and IJtiReplayCache plug-in
  • DPoPValidationResult — sealed result type with factory methods (Success, Failed, NonceRequired)

Interface: IJtiReplayCache — plug-in point for jti-based replay detection

Design decisions

  • Replay protection is layered: iat freshness (MUST per RFC) is always enforced; nonce (MAY) and jti tracking ("can") are opt-in via ExpectedNonce and JtiReplayCache
  • ath uses ASCII encoding with strict EncoderFallback.ExceptionFallback per RFC 9449 §4.2
  • JWK thumbprint strips Alg, Kid, Use per RFC 7638 §3.2 (only required members)
  • DPoPProofValidator is virtual

Multi-TFM support

Targets $(SrcTargets) from common.props. Uses #if guards matching Wilson conventions:

  • #if NET6_0_OR_GREATERSHA256.HashData, RandomNumberGenerator.Fill

  • #if NETCryptographicOperations.FixedTimeEquals

  • #if NET8_0_OR_GREATERTimeProvider

  • JsonWebKey.RepresentAsAsymmetricPublicJwkForDpop(): RSA branch was including Alg, Kid, Use in the JWK — these must be excluded per RFC 7638 §3.2 for
    correct thumbprint computation

Tests

47 tests covering all RFC §4.3 validation steps, edge cases (expired proof, wrong algorithm, symmetric key rejection, private key detection, replay cache, RSA + EC keys,
nonce handling). Tests excluded on net462 (#if !NET462) due to missing ECCurve/RSA.Create(int) APIs.

Code quality

  • PublicAPI.Shipped.txt / PublicAPI.Unshipped.txt with per-TFM files (no RS0016 suppression)
  • GlobalSuppressions.cs with targeted member-level suppressions (CA1031, CA2227, CA1805)
  • CancellationToken forwarded end-to-end through ValidateTokenAsync
  • XML doc comments on all public members

PBI 3549154: Implement dPoP validation primitives in Wilson

@MZOLN MZOLN requested a review from a team as a code owner April 10, 2026 17:58
Comment thread src/Microsoft.IdentityModel.Dpop/DPoPConstants.cs
Comment thread test/Microsoft.IdentityModel.Dpop.Tests/DpopTests.cs Outdated
Comment thread test/Microsoft.IdentityModel.Dpop.Tests/DpopTests.cs Outdated
Comment thread src/Microsoft.IdentityModel.Dpop/DPoPProof.cs Outdated
Comment thread src/Microsoft.IdentityModel.Dpop/DPoPProofValidator.cs Outdated
Comment thread src/Microsoft.IdentityModel.Dpop/DPoPProofValidator.cs Outdated
Comment thread src/Microsoft.IdentityModel.Dpop/DPoPProofValidator.cs Outdated
Comment thread src/Microsoft.IdentityModel.Dpop/DPoPProofValidator.cs Outdated
Comment thread src/Microsoft.IdentityModel.Dpop/DPoPProofValidator.cs Outdated
Comment thread src/Microsoft.IdentityModel.Dpop/DPoPValidationOptions.cs Outdated
Comment thread src/Microsoft.IdentityModel.Dpop/DPoPValidationOptions.cs Outdated
Comment thread src/Microsoft.IdentityModel.Dpop/DPoPValidationOptions.cs
Comment thread src/Microsoft.IdentityModel.Dpop/DPoPValidationOptions.cs
Comment thread src/Microsoft.IdentityModel.Dpop/DPoPValidationOptions.cs
Comment thread src/Microsoft.IdentityModel.Dpop/DPoPProofValidator.cs Outdated
Comment thread src/Microsoft.IdentityModel.Dpop/DPoPProof.cs Outdated
Copy link
Copy Markdown
Member

@bgavrilMS bgavrilMS left a comment

Choose a reason for hiding this comment

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

Too much public API. Creation APIs for proofs are not needed .

Comment thread test/Microsoft.IdentityModel.Dpop.Tests/DpopTests.cs
Comment thread test/Microsoft.IdentityModel.Dpop.Tests/DpopTests.cs Outdated
Copy link
Copy Markdown
Contributor

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

Adds a new Microsoft.IdentityModel.Dpop package to Wilson that implements DPoP (RFC 9449) proof creation and server-side validation, plus updates to Microsoft.IdentityModel.Tokens to support cnf.jkt and DPoP-specific JWK/header serialization.

Changes:

  • Introduces the Microsoft.IdentityModel.Dpop library (proof creation, validation, options/result types, replay-cache interface).
  • Adds a new Microsoft.IdentityModel.Dpop.Tests test project with unit tests and an (skipped) integration test.
  • Updates Microsoft.IdentityModel.Tokens for DPoP support (minimal JWK header representation, cnf.jkt, JSON serialization support).

Reviewed changes

Copilot reviewed 38 out of 38 changed files in this pull request and generated 13 comments.

Show a summary per file
File Description
Wilson.sln Adds the new DPoP library and test projects to the main solution.
buildConfiguration.xml Includes the new DPoP projects in build/test project lists.
test/Microsoft.IdentityModel.Dpop.Tests/Microsoft.IdentityModel.Dpop.Tests.csproj New test project for DPoP.
test/Microsoft.IdentityModel.Dpop.Tests/DpopTests.cs Adds basic proof/validation tests and a skipped Keycloak integration test.
test/Microsoft.IdentityModel.Dpop.Tests/DPoPProofValidatorTests.cs Adds detailed validator tests covering many RFC scenarios.
src/Microsoft.IdentityModel.Tokens/Properties/AssemblyInfo.cs Grants internals visibility to the new DPoP assembly.
src/Microsoft.IdentityModel.Tokens/Microsoft.IdentityModel.Tokens.csproj Adds RS0016 suppression (PublicApiAnalyzer).
src/Microsoft.IdentityModel.Tokens/JsonWebKey.cs Adds DPoP-specific minimal public JWK representation and modifies existing JWK serialization.
src/Microsoft.IdentityModel.Tokens/Json/JsonSerializerPrimitives.cs Adds JsonNode support when writing objects.
src/Microsoft.IdentityModel.Tokens/ConfirmationClaimTypes.cs Adds jkt confirmation claim constant + UTF8 bytes span.
src/Microsoft.IdentityModel.Tokens/Cnf.cs Adds parsing + property for cnf.jkt.
src/Microsoft.IdentityModel.Dpop/Microsoft.IdentityModel.Dpop.csproj New DPoP library project definition including PublicAPI analyzer files.
src/Microsoft.IdentityModel.Dpop/IJtiReplayCache.cs Adds replay cache abstraction for jti replay detection.
src/Microsoft.IdentityModel.Dpop/GlobalSuppressions.cs Adds targeted suppressions for analyzer warnings in validator/options.
src/Microsoft.IdentityModel.Dpop/DPoPValidationResult.cs Adds structured result type for server-side validation outcomes.
src/Microsoft.IdentityModel.Dpop/DPoPValidationOptions.cs Adds configurable server-side validation settings (algorithms, lifetime, nonce, replay cache, TimeProvider).
src/Microsoft.IdentityModel.Dpop/DPoPProofValidator.cs Implements server-side validation + helper methods for binding/hash/thumbprint.
src/Microsoft.IdentityModel.Dpop/DPopProofOptions.cs Adds proof creation options (signing creds, nonce, TimeProvider, etc.).
src/Microsoft.IdentityModel.Dpop/DPoPProof.cs Implements client-side DPoP proof JWT creation.
src/Microsoft.IdentityModel.Dpop/DPoPErrorCodes.cs Adds RFC 9449 error code constants.
src/Microsoft.IdentityModel.Dpop/DPoPConstants.cs Adds DPoP protocol/header/token-type constants.
src/Microsoft.IdentityModel.Dpop/DPoPClaimTypes.cs Adds DPoP claim name constants.
src/Microsoft.IdentityModel.Dpop/PublicAPI.Unshipped.txt Adds the public surface area listing for the DPoP package (non-TFM file).
src/Microsoft.IdentityModel.Dpop/PublicAPI.Shipped.txt Adds (empty) shipped API baseline file for the DPoP package (non-TFM file).
src/Microsoft.IdentityModel.Dpop/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt Adds per-TFM public API file (currently empty).
src/Microsoft.IdentityModel.Dpop/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt Adds per-TFM shipped API file (currently empty).
src/Microsoft.IdentityModel.Dpop/PublicAPI/net462/PublicAPI.Unshipped.txt Adds per-TFM public API file (currently empty).
src/Microsoft.IdentityModel.Dpop/PublicAPI/net462/PublicAPI.Shipped.txt Adds per-TFM shipped API file (currently empty).
src/Microsoft.IdentityModel.Dpop/PublicAPI/net472/PublicAPI.Unshipped.txt Adds per-TFM public API file (currently empty).
src/Microsoft.IdentityModel.Dpop/PublicAPI/net472/PublicAPI.Shipped.txt Adds per-TFM shipped API file (currently empty).
src/Microsoft.IdentityModel.Dpop/PublicAPI/net6.0/PublicAPI.Unshipped.txt Adds per-TFM public API file (currently empty).
src/Microsoft.IdentityModel.Dpop/PublicAPI/net6.0/PublicAPI.Shipped.txt Adds per-TFM shipped API file (currently empty).
src/Microsoft.IdentityModel.Dpop/PublicAPI/net8.0/PublicAPI.Unshipped.txt Adds per-TFM public API entries for TimeProvider members.
src/Microsoft.IdentityModel.Dpop/PublicAPI/net8.0/PublicAPI.Shipped.txt Adds per-TFM shipped API file (currently empty).
src/Microsoft.IdentityModel.Dpop/PublicAPI/net9.0/PublicAPI.Unshipped.txt Adds per-TFM public API entries for TimeProvider members.
src/Microsoft.IdentityModel.Dpop/PublicAPI/net9.0/PublicAPI.Shipped.txt Adds per-TFM shipped API file (currently empty).
src/Microsoft.IdentityModel.Dpop/PublicAPI/net10.0/PublicAPI.Unshipped.txt Adds per-TFM public API entries for TimeProvider members.
src/Microsoft.IdentityModel.Dpop/PublicAPI/net10.0/PublicAPI.Shipped.txt Adds per-TFM shipped API file (currently empty).
Comments suppressed due to low confidence (1)

src/Microsoft.IdentityModel.Dpop/DPoPProof.cs:152

  • There are stray non-printable characters (a standalone carriage return) after the closing brace. Please remove it to avoid mixed line-ending / formatting issues in source control and analyzers.
        return Convert.ToBase64String(bytes);
    }
}



Comment thread src/Microsoft.IdentityModel.Tokens/JsonWebKey.cs
Comment thread src/Microsoft.IdentityModel.Dpop/DPoPProof.cs Outdated
Comment thread src/Microsoft.IdentityModel.Dpop/DPoPProofValidator.cs Outdated
Comment thread src/Microsoft.IdentityModel.Dpop/DPopProofOptions.cs Outdated
Comment thread test/Microsoft.IdentityModel.Dpop.Tests/DpopTests.cs Outdated
Comment thread test/Microsoft.IdentityModel.Dpop.Tests/DpopTests.cs Outdated
Comment thread test/Microsoft.IdentityModel.Dpop.Tests/DpopTests.cs Outdated
Comment thread test/Microsoft.IdentityModel.Dpop.Tests/DPoPProofValidatorTests.cs
This was referenced May 21, 2026
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.

4 participants