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

## IConsentConstraintEnforcer Interface

Defense\-in\-depth backstop that asserts the anti\-escalation invariant on the consent decision:
the set granted by [IUserConsentsProvider](https://www.abblix.com/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Features.Consents.IUserConsentsProvider 'Abblix\.Oidc\.Server\.Features\.Consents\.IUserConsentsProvider') MUST be a subset of what the
authorization request carried\. This mirrors the strictly narrowing\-only
[ITokenAuthorizationContextEvaluator](https://www.abblix.com/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Endpoints.Token.Interfaces.ITokenAuthorizationContextEvaluator 'Abblix\.Oidc\.Server\.Endpoints\.Token\.Interfaces\.ITokenAuthorizationContextEvaluator') at
the token endpoint \(RFC 8707 §2\.2\), giving the authorize\-time consent path the same guarantee\.

```csharp
public interface IConsentConstraintEnforcer
```

Derived  
↳ [ConsentConstraintEnforcer](https://www.abblix.com/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Endpoints.Authorization.ConsentConstraintEnforcer 'Abblix\.Oidc\.Server\.Endpoints\.Authorization\.ConsentConstraintEnforcer')

### Remarks
Violating `granted ⊆ requested` is never a protocol\-level condition: the consent decision
frequently originates across the browser trust boundary, and a host whose
[IUserConsentsProvider](https://www.abblix.com/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Features.Consents.IUserConsentsProvider 'Abblix\.Oidc\.Server\.Features\.Consents\.IUserConsentsProvider') echoes browser\-supplied scopes / resources /
`authorization_details` without intersecting against the request would let a user escalate
their own grant\. The provider returning anything outside the request is a defect in the host's
code \(or browser tampering its provider failed to defend against\), so the enforcer fails loud
with an exception rather than masking it as a recoverable OAuth error \- it surfaces in the
debugger, fails the host's tests, and is logged as a server error in production while no
escalated grant is issued\.
### Methods

## IConsentConstraintEnforcer\.EnforceAsync\(ValidAuthorizationRequest, ConsentDefinition, CancellationToken\) Method {#Abblix.Oidc.Server.Endpoints.Authorization.IConsentConstraintEnforcer.EnforceAsync(Abblix.Oidc.Server.Endpoints.Authorization.Interfaces.ValidAuthorizationRequest,Abblix.Oidc.Server.Features.Consents.ConsentDefinition,System.Threading.CancellationToken)}

Asserts that the granted consent does not exceed the request, and returns the
`authorization_details` as the per\-type validators left them\.

```csharp
System.Threading.Tasks.Task<System.Text.Json.Nodes.JsonArray?> EnforceAsync(Abblix.Oidc.Server.Endpoints.Authorization.Interfaces.ValidAuthorizationRequest request, Abblix.Oidc.Server.Features.Consents.ConsentDefinition granted, System.Threading.CancellationToken cancellationToken);
```
#### Parameters

###### `request` [ValidAuthorizationRequest](https://www.abblix.com/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Endpoints.Authorization.Interfaces.ValidAuthorizationRequest 'Abblix\.Oidc\.Server\.Endpoints\.Authorization\.Interfaces\.ValidAuthorizationRequest') {#Abblix.Oidc.Server.Endpoints.Authorization.IConsentConstraintEnforcer.EnforceAsync(Abblix.Oidc.Server.Endpoints.Authorization.Interfaces.ValidAuthorizationRequest,Abblix.Oidc.Server.Features.Consents.ConsentDefinition,System.Threading.CancellationToken).request}

The validated authorization request carrying the requested scopes,
            resources and `authorization_details`\.

###### `granted` [ConsentDefinition](https://www.abblix.com/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Features.Consents.ConsentDefinition 'Abblix\.Oidc\.Server\.Features\.Consents\.ConsentDefinition') {#Abblix.Oidc.Server.Endpoints.Authorization.IConsentConstraintEnforcer.EnforceAsync(Abblix.Oidc.Server.Endpoints.Authorization.Interfaces.ValidAuthorizationRequest,Abblix.Oidc.Server.Features.Consents.ConsentDefinition,System.Threading.CancellationToken).granted}

The consent decision produced by [IUserConsentsProvider](https://www.abblix.com/docs/api/abblix-oidc-server/Abblix.Oidc.Server.Features.Consents.IUserConsentsProvider 'Abblix\.Oidc\.Server\.Features\.Consents\.IUserConsentsProvider')\.

###### `cancellationToken` [System\.Threading\.CancellationToken](https://learn.microsoft.com/en-us/dotnet/api/system.threading.cancellationtoken 'System\.Threading\.CancellationToken') {#Abblix.Oidc.Server.Endpoints.Authorization.IConsentConstraintEnforcer.EnforceAsync(Abblix.Oidc.Server.Endpoints.Authorization.Interfaces.ValidAuthorizationRequest,Abblix.Oidc.Server.Features.Consents.ConsentDefinition,System.Threading.CancellationToken).cancellationToken}

Cancellation token\.

#### 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\.Text\.Json\.Nodes\.JsonArray](https://learn.microsoft.com/en-us/dotnet/api/system.text.json.nodes.jsonarray 'System\.Text\.Json\.Nodes\.JsonArray')[&gt;](https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task-1 'System\.Threading\.Tasks\.Task\`1')  
The granted `authorization_details` as re\-validated, or `null` when the
            consent decision carried none\. A re\-validation that returns nothing leaves the granted set
            standing, so `null` never means "the validators emptied it"\.

#### Exceptions

[System\.InvalidOperationException](https://learn.microsoft.com/en-us/dotnet/api/system.invalidoperationexception 'System\.InvalidOperationException')  
Thrown when the granted set contains a scope,
            resource, resource scope or `authorization_details` entry absent from \- or broader than \-
            the request; and equally when the array leaving the per\-type re\-validation does, since that is
            the one the grant is built from\. Also thrown when an entry cannot be read as a JSON object,
            when one carries no `type`, and when the re\-validation answers with an empty set, which
            says every entry was removed and leaves nothing to issue a grant for\.

### Remarks
What this bounds is TYPES and shapes, and deliberately not cardinality: a per\-type validator
answering with several entries of a type the user did grant is accepted, because RFC 9396 offers
no comparator that would say whether three entries of a type narrow one\. A deployment that needs
that bound sets it inside the per\-type validator, which is the only place that knows what a
second entry of its own type means\.
