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

## DistributedJwtReplayCache Class

Backward\-compat adapter from the legacy two\-step [IJwtReplayCache](https://www.abblix.com/en/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Features.JwtBearer.IJwtReplayCache 'Abblix\.Oidc\.Server\.Features\.JwtBearer\.IJwtReplayCache')
shape onto the canonical single\-call
[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\>\)')\. Delegates via
composition rather than inheritance so the deprecated contract stays
type\-isolated from the canonical one\.

```csharp
public sealed class DistributedJwtReplayCache : Abblix.Oidc.Server.Features.JwtBearer.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.JwtBearer.IJwtReplayCache 'Abblix\.Oidc\.Server\.Features\.JwtBearer\.IJwtReplayCache')

### Remarks

[IsReplayedAsync\(string\)](https://www.abblix.com/en/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Features.JwtBearer.DistributedJwtReplayCache#Abblix.Oidc.Server.Features.JwtBearer.DistributedJwtReplayCache.IsReplayedAsync(string) 'Abblix\.Oidc\.Server\.Features\.JwtBearer\.DistributedJwtReplayCache\.IsReplayedAsync\(string\)') probes the cache in read-only mode (no jti is
            recorded), and [MarkAsUsedAsync\(string, Nullable&lt;DateTimeOffset&gt;\)](https://www.abblix.com/en/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Features.JwtBearer.DistributedJwtReplayCache#Abblix.Oidc.Server.Features.JwtBearer.DistributedJwtReplayCache.MarkAsUsedAsync(string,System.Nullable_System.DateTimeOffset_) 'Abblix\.Oidc\.Server\.Features\.JwtBearer\.DistributedJwtReplayCache\.MarkAsUsedAsync\(string, System\.Nullable\<System\.DateTimeOffset\>\)') issues the canonical
            [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\>\)'). Concurrent
            presenters of the same jti can therefore both pass the read before either
            reaches the write — this is the same TOCTOU window the legacy API has
            always exposed and is the reason new code should consume `TryAddAsync`
            directly.
### Constructors

## DistributedJwtReplayCache\(IJwtReplayCache\) Constructor {#Abblix.Oidc.Server.Features.JwtBearer.DistributedJwtReplayCache.DistributedJwtReplayCache(Abblix.Oidc.Server.Features.ReplayPrevention.IJwtReplayCache)}

Backward\-compat adapter from the legacy two\-step [IJwtReplayCache](https://www.abblix.com/en/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Features.JwtBearer.IJwtReplayCache 'Abblix\.Oidc\.Server\.Features\.JwtBearer\.IJwtReplayCache')
shape onto the canonical single\-call
[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\>\)')\. Delegates via
composition rather than inheritance so the deprecated contract stays
type\-isolated from the canonical one\.

```csharp
public DistributedJwtReplayCache(Abblix.Oidc.Server.Features.ReplayPrevention.IJwtReplayCache canonical);
```
#### Parameters

###### `canonical` [IJwtReplayCache](https://www.abblix.com/en/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Features.ReplayPrevention.IJwtReplayCache 'Abblix\.Oidc\.Server\.Features\.ReplayPrevention\.IJwtReplayCache') {#Abblix.Oidc.Server.Features.JwtBearer.DistributedJwtReplayCache.DistributedJwtReplayCache(Abblix.Oidc.Server.Features.ReplayPrevention.IJwtReplayCache).canonical}

### Remarks

[IsReplayedAsync\(string\)](https://www.abblix.com/en/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Features.JwtBearer.DistributedJwtReplayCache#Abblix.Oidc.Server.Features.JwtBearer.DistributedJwtReplayCache.IsReplayedAsync(string) 'Abblix\.Oidc\.Server\.Features\.JwtBearer\.DistributedJwtReplayCache\.IsReplayedAsync\(string\)') probes the cache in read-only mode (no jti is
            recorded), and [MarkAsUsedAsync\(string, Nullable&lt;DateTimeOffset&gt;\)](https://www.abblix.com/en/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Features.JwtBearer.DistributedJwtReplayCache#Abblix.Oidc.Server.Features.JwtBearer.DistributedJwtReplayCache.MarkAsUsedAsync(string,System.Nullable_System.DateTimeOffset_) 'Abblix\.Oidc\.Server\.Features\.JwtBearer\.DistributedJwtReplayCache\.MarkAsUsedAsync\(string, System\.Nullable\<System\.DateTimeOffset\>\)') issues the canonical
            [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\>\)'). Concurrent
            presenters of the same jti can therefore both pass the read before either
            reaches the write — this is the same TOCTOU window the legacy API has
            always exposed and is the reason new code should consume `TryAddAsync`
            directly.
### Methods

## DistributedJwtReplayCache\.IsReplayedAsync\(string\) Method {#Abblix.Oidc.Server.Features.JwtBearer.DistributedJwtReplayCache.IsReplayedAsync(string)}

Checks if a JWT with the specified JTI has already been used\.

```csharp
public System.Threading.Tasks.Task<bool> IsReplayedAsync(string jti);
```
#### Parameters

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

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

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

#### 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')  
A task that completes with true if the JWT has already been used \(replay detected\);
false if this is the first time the JWT is being presented\.

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

Marks a JWT as used by storing its JTI in the cache until the specified expiration time\.

```csharp
public System.Threading.Tasks.Task MarkAsUsedAsync(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.JwtBearer.DistributedJwtReplayCache.MarkAsUsedAsync(string,System.Nullable_System.DateTimeOffset_).jti}

The JWT ID \(jti claim\) to mark as used\.

###### `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.JwtBearer.DistributedJwtReplayCache.MarkAsUsedAsync(string,System.Nullable_System.DateTimeOffset_).expiresAt}

The time at which the JWT expires\. The JTI will be stored until this time plus a small buffer\.
If null, a default expiration will be used\.

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

#### Returns
[System\.Threading\.Tasks\.Task](https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task 'System\.Threading\.Tasks\.Task')  
A task that completes when the JTI has been stored\.
