#### [Abblix\.Oidc\.Server](https://www.abblix.com/en/docs/api/abblix-oidc-server 'index')
### [Abblix\.Oidc\.Server\.Features\.ReplayPrevention](https://www.abblix.com/en/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Features.ReplayPrevention 'Abblix\.Oidc\.Server\.Features\.ReplayPrevention')

## DistributedJwtReplayCache Class

Distributed cache implementation of [IJwtReplayCache](https://www.abblix.com/en/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Features.ReplayPrevention.IJwtReplayCache 'Abblix\.Oidc\.Server\.Features\.ReplayPrevention\.IJwtReplayCache') for JWT replay protection\.
Uses [Microsoft\.Extensions\.Caching\.Distributed\.IDistributedCache](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.caching.distributed.idistributedcache 'Microsoft\.Extensions\.Caching\.Distributed\.IDistributedCache') to store JTIs, enabling multi\-instance deployments\.

```csharp
public class DistributedJwtReplayCache : Abblix.Oidc.Server.Features.ReplayPrevention.IJwtReplayCache
```

Inheritance [System\.Object](https://learn.microsoft.com/en-us/dotnet/api/system.object 'System\.Object') → DistributedJwtReplayCache

Implements [IJwtReplayCache](https://www.abblix.com/en/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Features.ReplayPrevention.IJwtReplayCache 'Abblix\.Oidc\.Server\.Features\.ReplayPrevention\.IJwtReplayCache')

### Remarks
This implementation stores JTIs with automatic expiration matching the JWT's lifetime\.
Works with Redis, SQL Server, NCache, or any IDistributedCache implementation\.
Clock skew buffer is configurable via [ClockSkew](https://www.abblix.com/en/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Common.Configuration.JwtBearerOptions#Abblix.Oidc.Server.Common.Configuration.JwtBearerOptions.ClockSkew 'Abblix\.Oidc\.Server\.Common\.Configuration\.JwtBearerOptions\.ClockSkew')\.
### Constructors

## DistributedJwtReplayCache\(ILogger\<DistributedJwtReplayCache\>, IDistributedCache, IOptionsMonitor\<OidcOptions\>, TimeProvider\) Constructor {#Abblix.Oidc.Server.Features.ReplayPrevention.DistributedJwtReplayCache.DistributedJwtReplayCache(Microsoft.Extensions.Logging.ILogger_Abblix.Oidc.Server.Features.ReplayPrevention.DistributedJwtReplayCache_,Microsoft.Extensions.Caching.Distributed.IDistributedCache,Microsoft.Extensions.Options.IOptionsMonitor_Abblix.Oidc.Server.Common.Configuration.OidcOptions_,System.TimeProvider)}

Distributed cache implementation of [IJwtReplayCache](https://www.abblix.com/en/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Features.ReplayPrevention.IJwtReplayCache 'Abblix\.Oidc\.Server\.Features\.ReplayPrevention\.IJwtReplayCache') for JWT replay protection\.
Uses [Microsoft\.Extensions\.Caching\.Distributed\.IDistributedCache](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.caching.distributed.idistributedcache 'Microsoft\.Extensions\.Caching\.Distributed\.IDistributedCache') to store JTIs, enabling multi\-instance deployments\.

```csharp
public DistributedJwtReplayCache(Microsoft.Extensions.Logging.ILogger<Abblix.Oidc.Server.Features.ReplayPrevention.DistributedJwtReplayCache> logger, Microsoft.Extensions.Caching.Distributed.IDistributedCache cache, Microsoft.Extensions.Options.IOptionsMonitor<Abblix.Oidc.Server.Common.Configuration.OidcOptions> options, System.TimeProvider timeProvider);
```
#### Parameters

###### `logger` [Microsoft\.Extensions\.Logging\.ILogger&lt;](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.logging.ilogger-1 'Microsoft\.Extensions\.Logging\.ILogger\`1')[DistributedJwtReplayCache](https://www.abblix.com/en/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Features.ReplayPrevention.DistributedJwtReplayCache 'Abblix\.Oidc\.Server\.Features\.ReplayPrevention\.DistributedJwtReplayCache')[&gt;](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.logging.ilogger-1 'Microsoft\.Extensions\.Logging\.ILogger\`1') {#Abblix.Oidc.Server.Features.ReplayPrevention.DistributedJwtReplayCache.DistributedJwtReplayCache(Microsoft.Extensions.Logging.ILogger_Abblix.Oidc.Server.Features.ReplayPrevention.DistributedJwtReplayCache_,Microsoft.Extensions.Caching.Distributed.IDistributedCache,Microsoft.Extensions.Options.IOptionsMonitor_Abblix.Oidc.Server.Common.Configuration.OidcOptions_,System.TimeProvider).logger}

Logger for recording replay detection events\.

###### `cache` [Microsoft\.Extensions\.Caching\.Distributed\.IDistributedCache](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.caching.distributed.idistributedcache 'Microsoft\.Extensions\.Caching\.Distributed\.IDistributedCache') {#Abblix.Oidc.Server.Features.ReplayPrevention.DistributedJwtReplayCache.DistributedJwtReplayCache(Microsoft.Extensions.Logging.ILogger_Abblix.Oidc.Server.Features.ReplayPrevention.DistributedJwtReplayCache_,Microsoft.Extensions.Caching.Distributed.IDistributedCache,Microsoft.Extensions.Options.IOptionsMonitor_Abblix.Oidc.Server.Common.Configuration.OidcOptions_,System.TimeProvider).cache}

The distributed cache for storing JTIs\.

###### `options` [Microsoft\.Extensions\.Options\.IOptionsMonitor&lt;](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.options.ioptionsmonitor-1 'Microsoft\.Extensions\.Options\.IOptionsMonitor\`1')[OidcOptions](https://www.abblix.com/en/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Common.Configuration.OidcOptions 'Abblix\.Oidc\.Server\.Common\.Configuration\.OidcOptions')[&gt;](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.options.ioptionsmonitor-1 'Microsoft\.Extensions\.Options\.IOptionsMonitor\`1') {#Abblix.Oidc.Server.Features.ReplayPrevention.DistributedJwtReplayCache.DistributedJwtReplayCache(Microsoft.Extensions.Logging.ILogger_Abblix.Oidc.Server.Features.ReplayPrevention.DistributedJwtReplayCache_,Microsoft.Extensions.Caching.Distributed.IDistributedCache,Microsoft.Extensions.Options.IOptionsMonitor_Abblix.Oidc.Server.Common.Configuration.OidcOptions_,System.TimeProvider).options}

JWT Bearer options for configurable settings like clock skew\.

###### `timeProvider` [System\.TimeProvider](https://learn.microsoft.com/en-us/dotnet/api/system.timeprovider 'System\.TimeProvider') {#Abblix.Oidc.Server.Features.ReplayPrevention.DistributedJwtReplayCache.DistributedJwtReplayCache(Microsoft.Extensions.Logging.ILogger_Abblix.Oidc.Server.Features.ReplayPrevention.DistributedJwtReplayCache_,Microsoft.Extensions.Caching.Distributed.IDistributedCache,Microsoft.Extensions.Options.IOptionsMonitor_Abblix.Oidc.Server.Common.Configuration.OidcOptions_,System.TimeProvider).timeProvider}

Provides access to the current time\.

### Remarks
This implementation stores JTIs with automatic expiration matching the JWT's lifetime\.
Works with Redis, SQL Server, NCache, or any IDistributedCache implementation\.
Clock skew buffer is configurable via [ClockSkew](https://www.abblix.com/en/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Common.Configuration.JwtBearerOptions#Abblix.Oidc.Server.Common.Configuration.JwtBearerOptions.ClockSkew 'Abblix\.Oidc\.Server\.Common\.Configuration\.JwtBearerOptions\.ClockSkew')\.
### Methods

## DistributedJwtReplayCache\.TryAddAsync\(string, Nullable\<DateTimeOffset\>\) Method {#Abblix.Oidc.Server.Features.ReplayPrevention.DistributedJwtReplayCache.TryAddAsync(string,System.Nullable_System.DateTimeOffset_)}

Records a fresh jti, returning `true` only on the first call for that
value\. The single\-call shape is atomic\-by\-contract: implementations are
expected to use the backend's compare\-and\-set primitive so concurrent
presenters of the same jti cannot both observe a miss and both succeed\.

```csharp
public System.Threading.Tasks.Task<bool> TryAddAsync(string jti, System.Nullable<System.DateTimeOffset> expiresAt);
```
#### Parameters

###### `jti` [System\.String](https://learn.microsoft.com/en-us/dotnet/api/system.string 'System\.String') {#Abblix.Oidc.Server.Features.ReplayPrevention.DistributedJwtReplayCache.TryAddAsync(string,System.Nullable_System.DateTimeOffset_).jti}

The JWT ID \(jti claim\) to record\.

###### `expiresAt` [System\.Nullable&lt;](https://learn.microsoft.com/en-us/dotnet/api/system.nullable-1 'System\.Nullable\`1')[System\.DateTimeOffset](https://learn.microsoft.com/en-us/dotnet/api/system.datetimeoffset 'System\.DateTimeOffset')[&gt;](https://learn.microsoft.com/en-us/dotnet/api/system.nullable-1 'System\.Nullable\`1') {#Abblix.Oidc.Server.Features.ReplayPrevention.DistributedJwtReplayCache.TryAddAsync(string,System.Nullable_System.DateTimeOffset_).expiresAt}

Latest moment a same\-jti replay could still pass the iat\-window check; the
cache entry only needs to persist that long\. `null` defers to the
implementation's default TTL\.

Implements [TryAddAsync\(string, Nullable&lt;DateTimeOffset&gt;\)](https://www.abblix.com/en/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Features.ReplayPrevention.IJwtReplayCache#Abblix.Oidc.Server.Features.ReplayPrevention.IJwtReplayCache.TryAddAsync(string,System.Nullable_System.DateTimeOffset_) 'Abblix\.Oidc\.Server\.Features\.ReplayPrevention\.IJwtReplayCache\.TryAddAsync\(string, System\.Nullable\<System\.DateTimeOffset\>\)')

#### Returns
[System\.Threading\.Tasks\.Task&lt;](https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task-1 'System\.Threading\.Tasks\.Task\`1')[System\.Boolean](https://learn.microsoft.com/en-us/dotnet/api/system.boolean 'System\.Boolean')[&gt;](https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task-1 'System\.Threading\.Tasks\.Task\`1')  
`true` if the jti was newly recorded \(proof is fresh\); `false` if
            it was already present \(replay detected\)\.

### Remarks

Atomic-capable backends close the race natively: Redis `SET … NX EX`
(via `StackExchange.Redis`), SQL `INSERT … ON CONFLICT DO NOTHING`,
Memcached `add`, in-memory `ConcurrentDictionary.TryAdd`.

The default implementation
[DistributedJwtReplayCache](https://www.abblix.com/en/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Features.ReplayPrevention.DistributedJwtReplayCache 'Abblix\.Oidc\.Server\.Features\.ReplayPrevention\.DistributedJwtReplayCache') uses
[Microsoft\.Extensions\.Caching\.Distributed\.IDistributedCache](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.caching.distributed.idistributedcache 'Microsoft\.Extensions\.Caching\.Distributed\.IDistributedCache'),
which exposes only Get + Set and no compare-and-set primitive. It therefore
provides only a probabilistic guarantee: two concurrent presenters of the
same jti can both observe a miss before either writes. The race window is
bounded by the cache round-trip and RFC 9449 §11.1 accepts probabilistic
replay defence — but hosts that need strict atomicity should override the
registration with a backend-aware implementation that bypasses
[Microsoft\.Extensions\.Caching\.Distributed\.IDistributedCache](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.caching.distributed.idistributedcache 'Microsoft\.Extensions\.Caching\.Distributed\.IDistributedCache') and
talks to the chosen backend's atomic primitive directly.
