-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Description
Describe the bug
I have multiple authorization policies, each testing a specific business condition ( i.e. presence of a claim on the user).
The AuthorizationMiddleware is combining all the requirements into a single AuthorizationPolicy so when an endpoint is decorated with more than one Authorize attribute I cannot tell which of the original policies failed, there is no way to tie the failed requirement back to the original policy.
I need to send the user to a different endpoint depending upon which policy failed.
The IAuthorizationService instance only gets a list of requirements, it cannot work out the policy it came from.
The IPolicyEvaluator may get a list of pending requirements, but that's from the combined AuthorizationPolicy, cannot tie it back to the original policy. If a handler explicitly calls Fail(), the IAuthorizationService doesn't returns which requirement failed in it's Pending list, we're even more stuck!
The only thing I can think of is to iterate though all of the policies on the AuthorizationOptions and match the requirement by instance... assuming the only source of policies is AuthorizationOptions.
Possibilities I've considered
-
Override IPolicyEvaluator.
If the authorizations service returns a failed authorization resulr, try to find a matching AuthorizationPolicy for each pending requirements from the list of authorization policies in the AuthorizationOptions instance, comparing the requirement by object reference. If more than 1 pending requirement remains, which policy takes precedence. If a requirement instance is duplicated in more than 1 policy, I cannot workout which one. Add the failed policy to the HttpContext items so the scheme's ChallengeAsync/ForbidAsync handlers know what to do. -
Replace AuthorizationMiddleware
Execute policies from the endpoint metadata individually instead of combining. Supply the policy on the ChallengeAsync/ForbidAsync in the authentication properties
Duplicates all the logic from the existing AuthorizationMiddleware.
Inconsistent with the AuthorizationFilter implementation which appears to be hardcoded into AuthorizationApplicationModelProvider but if I'm using Endpoint Routing then it doesn't appear to matter.
Allows me to execute Policies that don't require an authenticated user before evaluating IAllowAnonymous logic.
Further technical details
- ASP.NET Core version: 3.0.0