#### [Abblix\.Jwt](https://www.abblix.com/en/docs/api/abblix-jwt 'index')
### [Abblix\.Jwt](https://www.abblix.com/en/docs/api/abblix-jwt/Abblix.Jwt 'Abblix\.Jwt')

## ClockSkew Struct

How far a token's timestamps may sit either side of this clock and still be honoured\.

```csharp
public readonly record struct ClockSkew : System.IEquatable<Abblix.Jwt.ClockSkew>
```

Implements [System\.IEquatable&lt;](https://learn.microsoft.com/en-us/dotnet/api/system.iequatable-1 'System\.IEquatable\`1')[ClockSkew](https://www.abblix.com/en/docs/api/abblix-jwt/Abblix.Jwt.ClockSkew 'Abblix\.Jwt\.ClockSkew')[&gt;](https://learn.microsoft.com/en-us/dotnet/api/system.iequatable-1 'System\.IEquatable\`1')

### Remarks

The two directions are separate numbers because only one of them is governed by anything. FAPI
2.0 Security Profile section 5.3.2.1 speaks exclusively of `iat` and `nbf` "in the
future"; `exp` appears nowhere in that section, so how long a token stays usable past its
stated end is this library's question to answer and a profile's to leave alone.

They travel as one type so that a caller passing a tolerance passes both halves or neither. A
value carrying one half is indistinguishable from a deliberate asymmetry, which is what the
profile below expresses on purpose.
### Fields

## ClockSkew\.Fapi2 Field {#Abblix.Jwt.ClockSkew.Fapi2}

What FAPI 2\.0 Security Profile section 5\.3\.2\.1 asks a server to accept: an `iat` or
`nbf` "between 0 and 10 seconds in the future"\.

```csharp
public static readonly ClockSkew Fapi2;
```

#### Field Value
[ClockSkew](https://www.abblix.com/en/docs/api/abblix-jwt/Abblix.Jwt.ClockSkew 'Abblix\.Jwt\.ClockSkew')

### Remarks
The asymmetry is the specification's, not a choice made here\. That sentence speaks only of
the future direction, so nothing in it extends the life of a token past the `exp` its
own issuer chose \- which is a deadline this server has no reason to move\.

## ClockSkew\.Fapi2Ceiling Field {#Abblix.Jwt.ClockSkew.Fapi2Ceiling}

The furthest anything may be dated under FAPI 2\.0 Security Profile section 5\.3\.2\.1, which
requires a server to "reject JWTs with an `iat` or `nbf` timestamp greater than 60
seconds in the future"\.

```csharp
public static readonly TimeSpan Fapi2Ceiling;
```

#### Field Value
[System\.TimeSpan](https://learn.microsoft.com/en-us/dotnet/api/system.timespan 'System\.TimeSpan')

### Remarks
A bound on whatever a caller asks for, which is why it is separate from [Fapi2](https://www.abblix.com/en/docs/api/abblix-jwt/Abblix.Jwt.ClockSkew#Abblix.Jwt.ClockSkew.Fapi2 'Abblix\.Jwt\.ClockSkew\.Fapi2')
rather than folded into it\. Note 3 of that section says the number is in the document "to
prevent implementations switching off `iat` and `nbf` checks completely", so it
belongs to the profile: a deployment outside one answers to RFC 7523 Section 3, which names
no bound at all\.

The quoted sentence governs the forward direction; holding the backward one to the same
number is this server's decision rather than the specification's\. A profile distrusting a
clock past some point one way has no reason to trust it further the other, and the alternative
is a ceiling that reads as a bound on the tolerance while leaving half of it unbounded\.

## ClockSkew\.None Field {#Abblix.Jwt.ClockSkew.None}

No tolerance in either direction, and what a caller gets by saying nothing\.

```csharp
public static readonly ClockSkew None;
```

#### Field Value
[ClockSkew](https://www.abblix.com/en/docs/api/abblix-jwt/Abblix.Jwt.ClockSkew 'Abblix\.Jwt\.ClockSkew')

### Remarks
A default that granted time would widen an expiry check for every caller that never asked \-
including one enforcing a deadline of its own, which is what most callers of this type are
doing\. A tolerance is granted deliberately or not at all: a deployment\-wide answer belongs to
the security profile a host opts into, and a number a profile requires is the profile's to
supply\.
### Properties

## ClockSkew\.Future Property {#Abblix.Jwt.ClockSkew.Future}

How far into the future a timestamp may reach and still be honoured: how far off a token's
`nbf` or `iat` may be dated\. This is the direction FAPI 2\.0 section 5\.3\.2\.1 speaks
of, and the only one any specification here bounds\.

```csharp
public System.TimeSpan Future { get; init; }
```

#### Property Value
[System\.TimeSpan](https://learn.microsoft.com/en-us/dotnet/api/system.timespan 'System\.TimeSpan')

## ClockSkew\.Past Property {#Abblix.Jwt.ClockSkew.Past}

How far into the past a timestamp may reach and still be honoured: how long a token stays
usable after the `exp` it carries\.

```csharp
public System.TimeSpan Past { get; init; }
```

#### Property Value
[System\.TimeSpan](https://learn.microsoft.com/en-us/dotnet/api/system.timespan 'System\.TimeSpan')
### Methods

## ClockSkew\.BoundedBy\(Nullable\<TimeSpan\>\) Method {#Abblix.Jwt.ClockSkew.BoundedBy(System.Nullable_System.TimeSpan_)}

This tolerance with neither direction exceeding [ceiling](https://www.abblix.com/en/docs/api/abblix-jwt/Abblix.Jwt.ClockSkew#Abblix.Jwt.ClockSkew.BoundedBy(System.Nullable_System.TimeSpan_).ceiling 'Abblix\.Jwt\.ClockSkew\.BoundedBy\(System\.Nullable\<System\.TimeSpan\>\)\.ceiling'), or unchanged
where there is no ceiling to hold it to\.

```csharp
public Abblix.Jwt.ClockSkew BoundedBy(System.Nullable<System.TimeSpan> ceiling);
```
#### Parameters

###### `ceiling` [System\.Nullable&lt;](https://learn.microsoft.com/en-us/dotnet/api/system.nullable-1 'System\.Nullable\`1')[System\.TimeSpan](https://learn.microsoft.com/en-us/dotnet/api/system.timespan 'System\.TimeSpan')[&gt;](https://learn.microsoft.com/en-us/dotnet/api/system.nullable-1 'System\.Nullable\`1') {#Abblix.Jwt.ClockSkew.BoundedBy(System.Nullable_System.TimeSpan_).ceiling}

The furthest either direction may reach, or null for no bound\.

#### Returns
[ClockSkew](https://www.abblix.com/en/docs/api/abblix-jwt/Abblix.Jwt.ClockSkew 'Abblix\.Jwt\.ClockSkew')

## ClockSkew\.WhyRefused\(DateTimeOffset, Nullable\<DateTimeOffset\>, Nullable\<DateTimeOffset\>, Nullable\<DateTimeOffset\>\) Method {#Abblix.Jwt.ClockSkew.WhyRefused(System.DateTimeOffset,System.Nullable_System.DateTimeOffset_,System.Nullable_System.DateTimeOffset_,System.Nullable_System.DateTimeOffset_)}

Why a token's timestamps are refused at [now](https://www.abblix.com/en/docs/api/abblix-jwt/Abblix.Jwt.ClockSkew#Abblix.Jwt.ClockSkew.WhyRefused(System.DateTimeOffset,System.Nullable_System.DateTimeOffset_,System.Nullable_System.DateTimeOffset_,System.Nullable_System.DateTimeOffset_).now 'Abblix\.Jwt\.ClockSkew\.WhyRefused\(System\.DateTimeOffset, System\.Nullable\<System\.DateTimeOffset\>, System\.Nullable\<System\.DateTimeOffset\>, System\.Nullable\<System\.DateTimeOffset\>\)\.now'), or null where this tolerance
admits them\.

```csharp
public string? WhyRefused(System.DateTimeOffset now, System.Nullable<System.DateTimeOffset> notBefore, System.Nullable<System.DateTimeOffset> expiresAt, System.Nullable<System.DateTimeOffset> issuedAt);
```
#### Parameters

###### `now` [System\.DateTimeOffset](https://learn.microsoft.com/en-us/dotnet/api/system.datetimeoffset 'System\.DateTimeOffset') {#Abblix.Jwt.ClockSkew.WhyRefused(System.DateTimeOffset,System.Nullable_System.DateTimeOffset_,System.Nullable_System.DateTimeOffset_,System.Nullable_System.DateTimeOffset_).now}

The instant the timestamps are judged against\.

###### `notBefore` [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.Jwt.ClockSkew.WhyRefused(System.DateTimeOffset,System.Nullable_System.DateTimeOffset_,System.Nullable_System.DateTimeOffset_,System.Nullable_System.DateTimeOffset_).notBefore}

When the token says it starts, if it says\.

###### `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.Jwt.ClockSkew.WhyRefused(System.DateTimeOffset,System.Nullable_System.DateTimeOffset_,System.Nullable_System.DateTimeOffset_,System.Nullable_System.DateTimeOffset_).expiresAt}

When the token says it ends, if it says\.

###### `issuedAt` [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.Jwt.ClockSkew.WhyRefused(System.DateTimeOffset,System.Nullable_System.DateTimeOffset_,System.Nullable_System.DateTimeOffset_,System.Nullable_System.DateTimeOffset_).issuedAt}

When the token says it was minted, if it says\.

#### Returns
[System\.String](https://learn.microsoft.com/en-us/dotnet/api/system.string 'System\.String')

### Remarks
The comparison belongs here rather than to whoever validates, because more than one caller
asks it: a token is checked once against the tolerance it arrived under, and again wherever a
tighter one turns out to apply\. Two copies would part company on the boundaries, which is
where they are least likely to be noticed \- expiry is compared with `<=`, so a token
exactly its whole tolerance past the end is already expired, while one exactly the whole
tolerance ahead is still accepted\.

The order is deliberate: a token both post\-dated and expired answers "not yet valid", which
is what its sender meant to send and what tells them so\.
### Operators

## ClockSkew\.implicit operator ClockSkew\(TimeSpan\) Operator {#Abblix.Jwt.ClockSkew.op_ImplicitAbblix.Jwt.ClockSkew(System.TimeSpan)}

One number means the same tolerance either way, so a caller holding a single window assigns
it directly\.

```csharp
public static Abblix.Jwt.ClockSkew implicit operator Abblix.Jwt.ClockSkew(System.TimeSpan symmetric);
```
#### Parameters

###### `symmetric` [System\.TimeSpan](https://learn.microsoft.com/en-us/dotnet/api/system.timespan 'System\.TimeSpan') {#Abblix.Jwt.ClockSkew.op_ImplicitAbblix.Jwt.ClockSkew(System.TimeSpan).symmetric}

The tolerance to apply either way\.

#### Returns
[ClockSkew](https://www.abblix.com/en/docs/api/abblix-jwt/Abblix.Jwt.ClockSkew 'Abblix\.Jwt\.ClockSkew')

### Remarks
Implicit because the conversion loses nothing and cannot fail: a caller with one number has
said what both halves are\. The asymmetry belongs to a profile that prescribes one, never to
a value somebody typed \- a host naming one window means it in each direction, and having to
spell that out is the sort of ceremony that gets one half set and the other forgotten\.
