- Notifications
You must be signed in to change notification settings - Fork 587
AuthorizationHandlerContext responsibility split up & thread safety #879
Description
short background - we are currently bringing our ABAC approach forward, staying on the XACML path conceptually (architecture/flow) but replacing the language element part with "code" to make it more developer friendly (the "leave rules to business experts" thing didn't work out for us so far...)
first of all, thx for the great job with the authorization abstractions, without too much tweaking we were able to get "some kind of" PDP executing c# code (resp. ScriptCs scripts) running, in addition to the out of the box framework functionality we support
A. handler processing in parallel
B. direct routing of requirements to handlers (instead of iterating through all registered handlers)
C. triggering webhooks after approval (~ simplified obligation stuff)
D. pluggable evaluation strategies (~ combining algorithm) e.g. with fail fast (not going through all handlers every time)
E. auditing information for all succeeded/failed requirements (in order!)
what is preventing us from going straight ahead with the current (and not a patched) AspNetCore.Authorization implementation is the "not very customizable nature" of the AuthorizationHandlerContext with its two responsibilites - holding current state and evaluating it:
- one thing we propose is to introduce an interface like
public interface IAuthorizationEvaluator { bool HasFailed(AuthorizationHandlerContext context); bool HasSucceeded(AuthorizationHandlerContext context); } which is injected and used within the IAuthorizationService (instead of the HasFailed/HasSucceeded properties of the AuthorizationHandlerContext) to make the decisions (see D)
- we also vote for an additive (see E) & thread safe (see A) implementation of the Succeed/Fail calls within the AuthorizationHandlerContext (instead of _pendingRequirements.Remove),
public class AuthorizationHandlerContext { ... public ConcurrentQueue<IAuthorizationRequirement> FailedRequirements { get; } public ConcurrentQueue<IAuthorizationRequirement> SucceededRequirements { get; } public void Fail(IAuthorizationRequirement requirement = null) { FailedRequirements.Enqueue(requirement); } public void Succeed(IAuthorizationRequirement requirement) { if (requirement == null) { throw new ArgumentNullException(nameof(requirement)); } SucceededRequirements.Enqueue(requirement); } } an interface/base class for AuthorizationHandlerContext combined with a factory approach could be an alternative
looking forward to feedback and hopefully a chance to contribute :)