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

## RevocationCutoffChecker Class

Refuses a token issued before a revocation cutoff recorded against its subject or its session\.

```csharp
public class RevocationCutoffChecker : Abblix.Oidc.Server.Features.Tokens.Revocation.IRevocationCutoffChecker
```

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

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

### Remarks
Applies only to tokens this server minted\. A cutoff names a principal in this server's own namespace,
while the validator that consults this also sees tokens minted elsewhere \- a client's
`private_key_jwt` assertion \(RFC 7523 Section 3, where `sub` is the `client_id`\), an
assertion from a federated issuer under the jwt\-bearer grant, a request object, a software statement\.
Their subjects are strings from other namespaces, so matching one against our cutoff would refuse a
stranger's token for a revocation that has nothing to do with it \- and under `client_credentials`
this server's own `sub` is a `client_id` too, so the two namespaces genuinely collide\.

Measured against `iat` rather than `auth_time`. Both are OPTIONAL in general (RFC 7519
Section 4.1.6), but this server issues `iat` on every token it mints - RFC 9068 Section 2.2 makes it
REQUIRED for the `at+jwt` profile its access tokens use - while `auth_time` is REQUIRED only
when `max_age` was requested or it was asked for as an essential claim (OpenID Connect Core 1.0
Section 2). A check built on the second would pass silently for most tokens, which is worse than no
check. A token arriving without `iat` is left alone: there is nothing to measure, and refusing it
would revoke on the strength of a claim that was never there.

A cutoff therefore has two sides, and the token side alone would be a control that can be walked
around: `iat` is stamped afresh by every authorization, so a browser session the revocation never
reached would mint a replacement past the cutoff on the first attempt and on every attempt after.
[IsSessionRefusedAsync\(AuthSession\)](https://www.abblix.com/en/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Features.Tokens.Revocation.RevocationCutoffChecker#Abblix.Oidc.Server.Features.Tokens.Revocation.RevocationCutoffChecker.IsSessionRefusedAsync(Abblix.Oidc.Server.Features.UserAuthentication.AuthSession) 'Abblix\.Oidc\.Server\.Features\.Tokens\.Revocation\.RevocationCutoffChecker\.IsSessionRefusedAsync\(Abblix\.Oidc\.Server\.Features\.UserAuthentication\.AuthSession\)') is the other side, consulted wherever a session is about to be used:
by the authorization endpoint before it reuses one, and by the token endpoint before it redeems a grant
authorized from one.

The comparison is against the whole second the token declares. A JWT's `iat` is a whole number of
seconds, so a token minted in the same second as a revocation reads as older than it and is refused. That
errs towards refusing a token the revocation did not mean to catch, which is the direction to err in.
Clock differences between instances run the other way and are not bounded by the token, which is what
[RevocationCutoffSkew](https://www.abblix.com/en/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Common.Configuration.OidcOptions#Abblix.Oidc.Server.Common.Configuration.OidcOptions.RevocationCutoffSkew 'Abblix\.Oidc\.Server\.Common\.Configuration\.OidcOptions\.RevocationCutoffSkew') answers - on this side only. The session side takes no
tolerance, because there the same widening would refuse the fresh sign-in a user answers the refusal
with, and the retry lands in the same window.
### Constructors

## RevocationCutoffChecker\(ILogger\<RevocationCutoffChecker\>, IRevocationCutoffRegistry, IIssuerProvider, IOptions\<OidcOptions\>, IClientInfoProvider, ISubjectTypeConverter\) Constructor {#Abblix.Oidc.Server.Features.Tokens.Revocation.RevocationCutoffChecker.RevocationCutoffChecker(Microsoft.Extensions.Logging.ILogger_Abblix.Oidc.Server.Features.Tokens.Revocation.RevocationCutoffChecker_,Abblix.Oidc.Server.Features.Storages.IRevocationCutoffRegistry,Abblix.Oidc.Server.Features.Issuer.IIssuerProvider,Microsoft.Extensions.Options.IOptions_Abblix.Oidc.Server.Common.Configuration.OidcOptions_,Abblix.Oidc.Server.Features.ClientInformation.IClientInfoProvider,Abblix.Oidc.Server.Features.PairwiseIdentifiers.ISubjectTypeConverter)}

Refuses a token issued before a revocation cutoff recorded against its subject or its session\.

```csharp
public RevocationCutoffChecker(Microsoft.Extensions.Logging.ILogger<Abblix.Oidc.Server.Features.Tokens.Revocation.RevocationCutoffChecker> logger, Abblix.Oidc.Server.Features.Storages.IRevocationCutoffRegistry cutoffRegistry, Abblix.Oidc.Server.Features.Issuer.IIssuerProvider issuerProvider, Microsoft.Extensions.Options.IOptions<Abblix.Oidc.Server.Common.Configuration.OidcOptions> options, Abblix.Oidc.Server.Features.ClientInformation.IClientInfoProvider clientInfoProvider, Abblix.Oidc.Server.Features.PairwiseIdentifiers.ISubjectTypeConverter subjectTypeConverter);
```
#### 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')[RevocationCutoffChecker](https://www.abblix.com/en/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Features.Tokens.Revocation.RevocationCutoffChecker 'Abblix\.Oidc\.Server\.Features\.Tokens\.Revocation\.RevocationCutoffChecker')[&gt;](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.logging.ilogger-1 'Microsoft\.Extensions\.Logging\.ILogger\`1') {#Abblix.Oidc.Server.Features.Tokens.Revocation.RevocationCutoffChecker.RevocationCutoffChecker(Microsoft.Extensions.Logging.ILogger_Abblix.Oidc.Server.Features.Tokens.Revocation.RevocationCutoffChecker_,Abblix.Oidc.Server.Features.Storages.IRevocationCutoffRegistry,Abblix.Oidc.Server.Features.Issuer.IIssuerProvider,Microsoft.Extensions.Options.IOptions_Abblix.Oidc.Server.Common.Configuration.OidcOptions_,Abblix.Oidc.Server.Features.ClientInformation.IClientInfoProvider,Abblix.Oidc.Server.Features.PairwiseIdentifiers.ISubjectTypeConverter).logger}

Records a refusal, so a revoked token is distinguishable from an expired one\.

###### `cutoffRegistry` [IRevocationCutoffRegistry](https://www.abblix.com/en/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Features.Storages.IRevocationCutoffRegistry 'Abblix\.Oidc\.Server\.Features\.Storages\.IRevocationCutoffRegistry') {#Abblix.Oidc.Server.Features.Tokens.Revocation.RevocationCutoffChecker.RevocationCutoffChecker(Microsoft.Extensions.Logging.ILogger_Abblix.Oidc.Server.Features.Tokens.Revocation.RevocationCutoffChecker_,Abblix.Oidc.Server.Features.Storages.IRevocationCutoffRegistry,Abblix.Oidc.Server.Features.Issuer.IIssuerProvider,Microsoft.Extensions.Options.IOptions_Abblix.Oidc.Server.Common.Configuration.OidcOptions_,Abblix.Oidc.Server.Features.ClientInformation.IClientInfoProvider,Abblix.Oidc.Server.Features.PairwiseIdentifiers.ISubjectTypeConverter).cutoffRegistry}

The registry of subject\- and session\-level revocation cutoffs\.

###### `issuerProvider` [IIssuerProvider](https://www.abblix.com/en/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Features.Issuer.IIssuerProvider 'Abblix\.Oidc\.Server\.Features\.Issuer\.IIssuerProvider') {#Abblix.Oidc.Server.Features.Tokens.Revocation.RevocationCutoffChecker.RevocationCutoffChecker(Microsoft.Extensions.Logging.ILogger_Abblix.Oidc.Server.Features.Tokens.Revocation.RevocationCutoffChecker_,Abblix.Oidc.Server.Features.Storages.IRevocationCutoffRegistry,Abblix.Oidc.Server.Features.Issuer.IIssuerProvider,Microsoft.Extensions.Options.IOptions_Abblix.Oidc.Server.Common.Configuration.OidcOptions_,Abblix.Oidc.Server.Features.ClientInformation.IClientInfoProvider,Abblix.Oidc.Server.Features.PairwiseIdentifiers.ISubjectTypeConverter).issuerProvider}

Names this server, so a cutoff is only measured against tokens it minted\.

###### `options` [Microsoft\.Extensions\.Options\.IOptions&lt;](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.options.ioptions-1 'Microsoft\.Extensions\.Options\.IOptions\`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.ioptions-1 'Microsoft\.Extensions\.Options\.IOptions\`1') {#Abblix.Oidc.Server.Features.Tokens.Revocation.RevocationCutoffChecker.RevocationCutoffChecker(Microsoft.Extensions.Logging.ILogger_Abblix.Oidc.Server.Features.Tokens.Revocation.RevocationCutoffChecker_,Abblix.Oidc.Server.Features.Storages.IRevocationCutoffRegistry,Abblix.Oidc.Server.Features.Issuer.IIssuerProvider,Microsoft.Extensions.Options.IOptions_Abblix.Oidc.Server.Common.Configuration.OidcOptions_,Abblix.Oidc.Server.Features.ClientInformation.IClientInfoProvider,Abblix.Oidc.Server.Features.PairwiseIdentifiers.ISubjectTypeConverter).options}

Carries the tolerance the comparison allows for clock differences\.

###### `clientInfoProvider` [IClientInfoProvider](https://www.abblix.com/en/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Features.ClientInformation.IClientInfoProvider 'Abblix\.Oidc\.Server\.Features\.ClientInformation\.IClientInfoProvider') {#Abblix.Oidc.Server.Features.Tokens.Revocation.RevocationCutoffChecker.RevocationCutoffChecker(Microsoft.Extensions.Logging.ILogger_Abblix.Oidc.Server.Features.Tokens.Revocation.RevocationCutoffChecker_,Abblix.Oidc.Server.Features.Storages.IRevocationCutoffRegistry,Abblix.Oidc.Server.Features.Issuer.IIssuerProvider,Microsoft.Extensions.Options.IOptions_Abblix.Oidc.Server.Common.Configuration.OidcOptions_,Abblix.Oidc.Server.Features.ClientInformation.IClientInfoProvider,Abblix.Oidc.Server.Features.PairwiseIdentifiers.ISubjectTypeConverter).clientInfoProvider}

Resolves the client a token names, so a pairwise pseudonym can be opened
            back into the subject a host would revoke\.

###### `subjectTypeConverter` [ISubjectTypeConverter](https://www.abblix.com/en/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Features.PairwiseIdentifiers.ISubjectTypeConverter 'Abblix\.Oidc\.Server\.Features\.PairwiseIdentifiers\.ISubjectTypeConverter') {#Abblix.Oidc.Server.Features.Tokens.Revocation.RevocationCutoffChecker.RevocationCutoffChecker(Microsoft.Extensions.Logging.ILogger_Abblix.Oidc.Server.Features.Tokens.Revocation.RevocationCutoffChecker_,Abblix.Oidc.Server.Features.Storages.IRevocationCutoffRegistry,Abblix.Oidc.Server.Features.Issuer.IIssuerProvider,Microsoft.Extensions.Options.IOptions_Abblix.Oidc.Server.Common.Configuration.OidcOptions_,Abblix.Oidc.Server.Features.ClientInformation.IClientInfoProvider,Abblix.Oidc.Server.Features.PairwiseIdentifiers.ISubjectTypeConverter).subjectTypeConverter}

Opens that pseudonym\.

### Remarks
Applies only to tokens this server minted\. A cutoff names a principal in this server's own namespace,
while the validator that consults this also sees tokens minted elsewhere \- a client's
`private_key_jwt` assertion \(RFC 7523 Section 3, where `sub` is the `client_id`\), an
assertion from a federated issuer under the jwt\-bearer grant, a request object, a software statement\.
Their subjects are strings from other namespaces, so matching one against our cutoff would refuse a
stranger's token for a revocation that has nothing to do with it \- and under `client_credentials`
this server's own `sub` is a `client_id` too, so the two namespaces genuinely collide\.

Measured against `iat` rather than `auth_time`. Both are OPTIONAL in general (RFC 7519
Section 4.1.6), but this server issues `iat` on every token it mints - RFC 9068 Section 2.2 makes it
REQUIRED for the `at+jwt` profile its access tokens use - while `auth_time` is REQUIRED only
when `max_age` was requested or it was asked for as an essential claim (OpenID Connect Core 1.0
Section 2). A check built on the second would pass silently for most tokens, which is worse than no
check. A token arriving without `iat` is left alone: there is nothing to measure, and refusing it
would revoke on the strength of a claim that was never there.

A cutoff therefore has two sides, and the token side alone would be a control that can be walked
around: `iat` is stamped afresh by every authorization, so a browser session the revocation never
reached would mint a replacement past the cutoff on the first attempt and on every attempt after.
[IsSessionRefusedAsync\(AuthSession\)](https://www.abblix.com/en/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Features.Tokens.Revocation.RevocationCutoffChecker#Abblix.Oidc.Server.Features.Tokens.Revocation.RevocationCutoffChecker.IsSessionRefusedAsync(Abblix.Oidc.Server.Features.UserAuthentication.AuthSession) 'Abblix\.Oidc\.Server\.Features\.Tokens\.Revocation\.RevocationCutoffChecker\.IsSessionRefusedAsync\(Abblix\.Oidc\.Server\.Features\.UserAuthentication\.AuthSession\)') is the other side, consulted wherever a session is about to be used:
by the authorization endpoint before it reuses one, and by the token endpoint before it redeems a grant
authorized from one.

The comparison is against the whole second the token declares. A JWT's `iat` is a whole number of
seconds, so a token minted in the same second as a revocation reads as older than it and is refused. That
errs towards refusing a token the revocation did not mean to catch, which is the direction to err in.
Clock differences between instances run the other way and are not bounded by the token, which is what
[RevocationCutoffSkew](https://www.abblix.com/en/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Common.Configuration.OidcOptions#Abblix.Oidc.Server.Common.Configuration.OidcOptions.RevocationCutoffSkew 'Abblix\.Oidc\.Server\.Common\.Configuration\.OidcOptions\.RevocationCutoffSkew') answers - on this side only. The session side takes no
tolerance, because there the same widening would refuse the fresh sign-in a user answers the refusal
with, and the retry lands in the same window.
### Methods

## RevocationCutoffChecker\.CheckAsync\(JsonWebTokenPayload\) Method {#Abblix.Oidc.Server.Features.Tokens.Revocation.RevocationCutoffChecker.CheckAsync(Abblix.Jwt.JsonWebTokenPayload)}

The refusal a cutoff calls for on this token, or `null` when no cutoff reaches it\.

```csharp
public System.Threading.Tasks.Task<Abblix.Jwt.JwtValidationError?> CheckAsync(Abblix.Jwt.JsonWebTokenPayload payload);
```
#### Parameters

###### `payload` [JsonWebTokenPayload](https://www.abblix.com/en/docs/api/abblix-jwt/Abblix.Jwt.JsonWebTokenPayload 'Abblix\.Jwt\.JsonWebTokenPayload') {#Abblix.Oidc.Server.Features.Tokens.Revocation.RevocationCutoffChecker.CheckAsync(Abblix.Jwt.JsonWebTokenPayload).payload}

The payload of a token that has already passed signature and lifetime checks\.

Implements [CheckAsync\(JsonWebTokenPayload\)](https://www.abblix.com/en/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Features.Tokens.Revocation.IRevocationCutoffChecker#Abblix.Oidc.Server.Features.Tokens.Revocation.IRevocationCutoffChecker.CheckAsync(Abblix.Jwt.JsonWebTokenPayload) 'Abblix\.Oidc\.Server\.Features\.Tokens\.Revocation\.IRevocationCutoffChecker\.CheckAsync\(Abblix\.Jwt\.JsonWebTokenPayload\)')

#### Returns
[System\.Threading\.Tasks\.Task&lt;](https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task-1 'System\.Threading\.Tasks\.Task\`1')[JwtValidationError](https://www.abblix.com/en/docs/api/abblix-jwt/Abblix.Jwt.JwtValidationError 'Abblix\.Jwt\.JwtValidationError')[&gt;](https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task-1 'System\.Threading\.Tasks\.Task\`1')  
A validation error when the token is refused, otherwise `null`\.

## RevocationCutoffChecker\.IsSessionRefusedAsync\(AuthSession\) Method {#Abblix.Oidc.Server.Features.Tokens.Revocation.RevocationCutoffChecker.IsSessionRefusedAsync(Abblix.Oidc.Server.Features.UserAuthentication.AuthSession)}

Whether a cutoff refuses this authentication session, so nothing may mint against it\.

```csharp
public System.Threading.Tasks.Task<bool> IsSessionRefusedAsync(Abblix.Oidc.Server.Features.UserAuthentication.AuthSession session);
```
#### Parameters

###### `session` [AuthSession](https://www.abblix.com/en/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Features.UserAuthentication.AuthSession 'Abblix\.Oidc\.Server\.Features\.UserAuthentication\.AuthSession') {#Abblix.Oidc.Server.Features.Tokens.Revocation.RevocationCutoffChecker.IsSessionRefusedAsync(Abblix.Oidc.Server.Features.UserAuthentication.AuthSession).session}

A session about to be used: one the authorization endpoint is considering
            reusing, or the one a grant presented at the token endpoint was authorized from\.

Implements [IsSessionRefusedAsync\(AuthSession\)](https://www.abblix.com/en/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Features.Tokens.Revocation.IRevocationCutoffChecker#Abblix.Oidc.Server.Features.Tokens.Revocation.IRevocationCutoffChecker.IsSessionRefusedAsync(Abblix.Oidc.Server.Features.UserAuthentication.AuthSession) 'Abblix\.Oidc\.Server\.Features\.Tokens\.Revocation\.IRevocationCutoffChecker\.IsSessionRefusedAsync\(Abblix\.Oidc\.Server\.Features\.UserAuthentication\.AuthSession\)')

#### 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` when the session must not be used\.

### Remarks
Without this the token side alone is half a control\. A cutoff refuses tokens already issued, and
`iat` is stamped afresh by every new authorization, so a browser session the revocation never
touched can mint a replacement that clears the cutoff on the first try \- and keeps doing so\.

Measured against [AuthenticationTime](https://www.abblix.com/en/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Features.UserAuthentication.AuthSession#Abblix.Oidc.Server.Features.UserAuthentication.AuthSession.AuthenticationTime 'Abblix\.Oidc\.Server\.Features\.UserAuthentication\.AuthSession\.AuthenticationTime'), not against a flag. A sign-in after
the suspension is lifted produces a later authentication time and passes, which is the same property
that lets a revoked subject sign in again with nothing to clean up. A boolean would refuse the fresh
session too, and since the host's new session carries the same subject the request would loop back
here for as long as the record is kept.
