Table of Contents

Class DefaultDPoPProofValidator

Namespace
Fdyay.IdentityServer.Validation
Assembly
Fdyay.IdentityServer.Core.dll

Supports all classes in the .NET class hierarchy and provides low-level services to derived classes. This is the ultimate base class of all .NET classes; it is the root of the type hierarchy.

public class DefaultDPoPProofValidator : IDPoPProofValidator
Inheritance
DefaultDPoPProofValidator
Implements
Inherited Members

Remarks

Duende 8.0.1's DefaultDPoPProofValidator, measured: the same steps, protected and virtual, in the same order — header, signature, then payload (ath, jti, htm, htu, iat, freshness, replay) — and the same descriptions word for word: they reach clients as the token endpoint's error_description and the resource endpoints' challenge, and a client written against one server reads the same words from the other. A host with one rule of its own overrides that step and keeps every other.

The signature is verified before anything the proof claims is read for meaning — an unverified proof's jti is an attacker's string, and recording it would let anyone fill the replay cache.

Where ours differs: the signature is held to SupportedSigningAlgorithms as well as the header, a replay raises DPoPProofReplayDetectedEvent, and a nonce that fails to unprotect for any reason other than not being ours is not swallowed.

Constructors

DefaultDPoPProofValidator(IOptions<IdentityServerOptions>, IReplayCache, IEventService, TimeProvider, IDataProtectionProvider)

Creates the validator.

public DefaultDPoPProofValidator(IOptions<IdentityServerOptions> options, IReplayCache replayCache, IEventService events, TimeProvider time, IDataProtectionProvider dataProtection)

Parameters

options IOptions<IdentityServerOptions>

The server's options, for the DPoP signing algorithms, proof lifetime and clock skews.

replayCache IReplayCache

Where proof identifiers are remembered, so a proof is accepted once.

events IEventService

Where a detected replay is raised as an event.

time TimeProvider

The clock proofs and nonces are held to.

dataProtection IDataProtectionProvider

Creates the protector server-issued nonces are made and read with.

Exceptions

ArgumentNullException

dataProtection is null.

Properties

DataProtector

The protector nonces are made and read with.

protected IDataProtector DataProtector { get; }

Property Value

IDataProtector

Options

The server's options.

protected IdentityServerOptions Options { get; }

Property Value

IdentityServerOptions

ReplayCache

Where proof identifiers are remembered.

protected IReplayCache ReplayCache { get; }

Property Value

IReplayCache

TimeProvider

The clock proofs and nonces are held to.

protected TimeProvider TimeProvider { get; }

Property Value

TimeProvider

Methods

CreateNonce(DPoPProofValidationContext, DPoPProofValidationResult)

A nonce for now: the time, protected, so only this server (or its farm) can have made it.

protected virtual string CreateNonce(DPoPProofValidationContext context, DPoPProofValidationResult result)

Parameters

context DPoPProofValidationContext
result DPoPProofValidationResult

Returns

string

Remarks

Stateless, as Duende's is: nothing is stored, and any instance sharing the key ring can check it.

GetUnixTimeFromNonceAsync(DPoPProofValidationContext, DPoPProofValidationResult)

When the proof's nonce was issued, in seconds since the epoch, or zero when it is not one this server issued.

protected virtual ValueTask<long> GetUnixTimeFromNonceAsync(DPoPProofValidationContext context, DPoPProofValidationResult result)

Parameters

context DPoPProofValidationContext
result DPoPProofValidationResult

Returns

ValueTask<long>

HashOf(string)

The base64url SHA-256 of an access token, as ath carries it (RFC 9449 §4.2).

public static string HashOf(string accessToken)

Parameters

accessToken string

Returns

string

IsExpired(DPoPProofValidationContext, DPoPProofValidationResult, TimeSpan, long)

Whether a time is out of the proof's window: further ahead than clockSkew, or older than ProofTokenValidityDuration by more than it. Duende's, in whole seconds.

protected virtual bool IsExpired(DPoPProofValidationContext context, DPoPProofValidationResult result, TimeSpan clockSkew, long issuedAtTime)

Parameters

context DPoPProofValidationContext
result DPoPProofValidationResult
clockSkew TimeSpan
issuedAtTime long

Returns

bool

ValidateAsync(DPoPProofValidationContext, CancellationToken)

Validates the proof in context against the request it names.

public Task<DPoPProofValidationResult> ValidateAsync(DPoPProofValidationContext context, CancellationToken cancellationToken = default)

Parameters

context DPoPProofValidationContext
cancellationToken CancellationToken

Returns

Task<DPoPProofValidationResult>

Exceptions

ArgumentNullException

context is null.

ValidateFreshnessAsync(DPoPProofValidationContext, DPoPProofValidationResult)

Holds the proof to the clock or clocks its client's DPoPValidationMode names.

protected virtual Task ValidateFreshnessAsync(DPoPProofValidationContext context, DPoPProofValidationResult result)

Parameters

context DPoPProofValidationContext
result DPoPProofValidationResult

Returns

Task

ValidateHeaderAsync(DPoPProofValidationContext, DPoPProofValidationResult)

The proof's header: typ, alg, its key, and the access token's cnf against that key.

protected virtual Task ValidateHeaderAsync(DPoPProofValidationContext context, DPoPProofValidationResult result)

Parameters

context DPoPProofValidationContext
result DPoPProofValidationResult

Returns

Task

ValidateIatAsync(DPoPProofValidationContext, DPoPProofValidationResult)

The client's clock: its iat, within the client's skew.

protected virtual Task ValidateIatAsync(DPoPProofValidationContext context, DPoPProofValidationResult result)

Parameters

context DPoPProofValidationContext
result DPoPProofValidationResult

Returns

Task

ValidateNonceAsync(DPoPProofValidationContext, DPoPProofValidationResult)

This server's clock, read back out of a nonce it issued.

protected virtual Task ValidateNonceAsync(DPoPProofValidationContext context, DPoPProofValidationResult result)

Parameters

context DPoPProofValidationContext
result DPoPProofValidationResult

Returns

Task

Remarks

Every way a nonce can be wrong — absent, not ours, stale — is answered the way RFC 9449 §8 answers it: use_dpop_nonce, with one that is right.

ValidatePayloadAsync(DPoPProofValidationContext, DPoPProofValidationResult, CancellationToken)

The proof's claims: ath, jti, htm, htu and iat, then freshness and replay.

protected virtual Task ValidatePayloadAsync(DPoPProofValidationContext context, DPoPProofValidationResult result, CancellationToken cancellationToken = default)

Parameters

context DPoPProofValidationContext
result DPoPProofValidationResult
cancellationToken CancellationToken

Returns

Task

ValidateReplayAsync(DPoPProofValidationContext, DPoPProofValidationResult, CancellationToken)

Refuses a proof presented before; remembers this one for as long as a second use could succeed.

protected virtual Task ValidateReplayAsync(DPoPProofValidationContext context, DPoPProofValidationResult result, CancellationToken cancellationToken = default)

Parameters

context DPoPProofValidationContext
result DPoPProofValidationResult
cancellationToken CancellationToken

Returns

Task

ValidateSignatureAsync(DPoPProofValidationContext, DPoPProofValidationResult)

The proof's signature, by the key it carries.

protected virtual Task ValidateSignatureAsync(DPoPProofValidationContext context, DPoPProofValidationResult result)

Parameters

context DPoPProofValidationContext
result DPoPProofValidationResult

Returns

Task