IConsentConstraintEnforcer Interface
Defense-in-depth backstop that asserts the anti-escalation invariant on the consent decision: the set granted by IUserConsentsProvider MUST be a subset of what the authorization request carried. This mirrors the strictly narrowing-only ITokenAuthorizationContextEvaluator at the token endpoint (RFC 8707 §2.2), giving the authorize-time consent path the same guarantee.
public interface IConsentConstraintEnforcerDerived
↳ 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 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
Asserts that the granted consent does not exceed the request, and returns the
authorization_details as the per-type validators left them.
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
The validated authorization request carrying the requested scopes,
resources and authorization_details.
granted ConsentDefinition
The consent decision produced by IUserConsentsProvider.
cancellationToken System.Threading.CancellationToken
Cancellation token.
Returns
System.Threading.Tasks.Task<System.Text.Json.Nodes.JsonArray>
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
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.