Skip to content

IReplayCache Interface

Remembers the identifiers of single-use tokens so a second presentation of the same one can be told from the first. Every JWT profile that forbids replay needs this and needs it in the same shape - a DPoP proof (RFC 9449 Section 11.1), a client assertion (RFC 7523 Section 3) and a Security Event Token (RFC 8417 Section 2.2) differ in what they call the identifier and how long it stays interesting, never in the question they ask of the cache.

C#
public interface IReplayCache

Derived
ReplayCacheBase

Remarks

The contract is reserve-and-check in one call, so a caller cannot read, decide and write in three steps that another caller slips between. Whether the reservation is strictly atomic is the implementation's promise, not this interface's: the shipped DistributedReplayCache rides IDistributedCache, which exposes only Get and Set, so its answer is probabilistic within one cache round trip. A deployment that needs strict single-use takes a backend-native primitive behind this same interface, which is what ReplayCacheBase is for: it holds everything around the primitive and leaves the primitive itself to a subclass - Redis SET NX PX, SQL INSERT ... ON CONFLICT DO NOTHING, and their equivalents.

Methods

IReplayCache.TryReserveAsync(string, DateTimeOffset, CancellationToken) Method

Reserves an identifier, answering whether this is its first sighting.

C#
System.Threading.Tasks.Task<bool> TryReserveAsync(string identifier, System.DateTimeOffset expiresAt, System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));

Parameters

identifier System.String

What identifies the token. A profile whose identifier is unique only within a scope composes that scope into the value it passes - a SET's "jti" is unique per event feed (RFC 8417 Section 2.2), so its receiver reserves the issuer and the identifier together.

expiresAt System.DateTimeOffset

When the identifier stops being worth remembering, which is the last moment a replay of this token could still pass the caller's own freshness checks. Forgetting earlier would let that token replay; the implementation is free to remember longer.

cancellationToken System.Threading.CancellationToken

Cancels the cache round trip.

Returns

System.Threading.Tasks.Task<System.Boolean>
True when the identifier was newly reserved and the token is therefore fresh; false when it was already there, which is a replay.