Skip to content
This repository has been archived by the owner on Dec 13, 2018. It is now read-only.

Add IAuthorizationHandlerProvider interface #1176

Closed
rposener opened this issue Apr 11, 2017 · 16 comments
Closed

Add IAuthorizationHandlerProvider interface #1176

rposener opened this issue Apr 11, 2017 · 16 comments

Comments

@rposener
Copy link

Is it possible to Map Policies to Requirements at Runtime? E.g. I would like to secure parts of an app using policies ("Job Maintenance") but allow administrative user in my app to map them to certain requirements (stored in DB) and updated during runtime. For example ("In Partners Group" or "Is Manager of Job") might be mapped to the "Job Maintenance" policy.

Is there a way to provide this kind of mapping during runtime? Or change the ones that are currently loaded except to restart the app?

@rposener
Copy link
Author

Looks like I can just implement my own IAuthorizationPolicyProvider and register it. Will give this a shot. Would be good to see this updated on docs.microsoft.com

@blowdart
Copy link
Member

For your example you wouldn't need to head down that route, you'd just go off to your database during the evaluation of the policy, and pull down the group members, and the job manager during HandleRequirementAsync().

@rposener
Copy link
Author

Not sure I follow - how do I allow an admin user change what the requirements are to meet a certain policy? E.g. I secure an area of the app to "Job Maintenance" policy. But don't want to hard code that it's always the "Manager of the Job" or the "Partners in the Group". I want the Administrative User of my app to make those decisions for their company.

@blowdart
Copy link
Member

So you still apply the Job maintenance policy to the area.

Then have a single requirement for that policy.

In that requirement go off to the database, figure out what the actual requirements are, and evaluate them.

@rposener
Copy link
Author

If I'm following - why use the AuthorizationService at all? What's the point if I'm create my own policy, requirement, and mapping them together myself. Guess I'm missing the point here. The IAuthorizationPolicyProvider is registered to the services with TryAdd for a reason is it not?

Seems that what you are suggesting violates SRP - a requirement that then has to act as a policy and map which requirements must be met and then also evaluate all those requirements? Requirements should be re-usable, and making a huge requirement to evaluate what requirements really diminishes reuse.

@blowdart
Copy link
Member

You could go either way. The Provider was there because people weren't happy with just have policies. It gives the somewhat limited ability to, for example, build policies based on policy name, replacing the parameters in custom attributes folks used before.

As for SRP, well that's a choice :) But unless you're restricting to a preset list of requirements in your database you're going to have to build them on the fly anyway, from whatever your ruleset requests, which makes them not reusable. Depends on the complexity of the rules.

@rposener
Copy link
Author

Ok - so I could implement multiple handlers - each needing to check the database to see if it's an enabled handler for the policy. Sees a bit useless to have them check if they are even needed though. I guess I'm expecting that to be able to be configured in the overall security configuration.

Just thinking about this...
If I go the handler route, I will have a Handler to Every Requirement for every way I want to evaluate it. E.g. If I want to secure jobs by resource (e.g. user is the job's manager), but have 4 different policies for various parts of the job, I would end up with 4 handlers that do the exact same check, but must first check the database to see if that intersection of handler & requirement is even enabled.

Option 1...
I could use the same requirement (basically a "HasAccess" requirement). And assign the same to multiple policies. At that point, I just need a factory type method, where I can control which handlers are used in evaluation of the policy?

I see: IAuthorizationHandlerContextFactory which gets close, but does not have a means to get at the policy, so even using that cannot do this.

Option 2...
Use 1 requirement per policy. Then create a single Resource base type, that can use to specify what the policy name is to the handler. Then in each handler I will need to inject a singleton which is a mapping of policies and handlers. If the handler is not active in the mapping do nothing. If the handler is, then evaluate from some other injected class that has a core set of requirement evaluations, so I can have a single place for how to check if some one is the job manager, even though many different handlers will need that.

That sounds like an awful lot of duplicative framework code across the handlers. Sure seems like a really valuable mapping is missing from this framework.

I think where this missing mapping lies is a means to filter the handlers within the AuthorizeAsync method of the DefaultAuthorizationService. Perhaps that's the custom bit I need to implement, not injecting a IEnumerable into the constructor, but something like a IAuthorizationHandlerProvider that has a method to return Handlers specific to a set of requirements and optionally Policy, instead of just all handlers for the requirement.

@HaoK
Copy link
Member

HaoK commented Apr 12, 2017

I would recommend the IAuthorizationPolicyProvider, while it was added for the specific scenario @blowdart refers to, its intent is to do exactly what you describe (dynamically map a policy name to requirements at runtime)

@rposener
Copy link
Author

So, what I think I will try is the following:

  • Multiple Policies, all using 1 Requirement "Has Access"
  • Custom AuthorizationService which injects IAuthorizationHandlerProvider.
  • The HandlerProvider will operate over an injected mapping to determine which Handlers are enabled for the Policy.

That way I can map which handlers are available to check for access to a specific area (secured by a specific policy) in my application, with each handler gaining full re-use (e.g. the check for is the user in this role, or is the user the manager of this resource).

Any downside to that approach?

@rposener
Copy link
Author

@HaoK the difference from IAuthorizationPolicyProvider and creating a IAuthorizationHandlerProvider going to be that I will end up having to meet all requirements (AND) instead of giving my user many ways to meet the requirement (OR).

Per my requirement, I'm looking for the OR (Job Manager) or (Partner Role) can satisfy the policy.

@HaoK
Copy link
Member

HaoK commented Apr 12, 2017

Ah yes, if you want OR behavior, that's a concern for how a particular requirement is handled. Implementing your own custom service implementation seems fine for filtering which handlers get executed to prevent hitting the db.

This doesn't seem like an unreasonable abstraction for us to add in 2.0 actually, we should consider adding that ourselves @blowdart

@blowdart
Copy link
Member

Fair enough, make it so Mr @HaoK :)

@rposener
Copy link
Author

Thanks @HaoK and @blowdart - I will go this route. Appreciate the input and look forward to seeing where it ends up in 2.0.

@HaoK
Copy link
Member

HaoK commented Apr 12, 2017

@rposener there's also another option you can consider.

You can have each requirement also be a handler, and if they are all really HasAccess where if any of them ever succeed you want to pass, then you can have that implementation succeed EVERY requirement in the the request, then you would just need to implement Success short circuiting in your custom authorization service.

Basically execute every handler, but check if you can shortcircuit returning true if all the requirements have been met after running each handler.

Not sure I like this route better, but it should also work.

@HaoK HaoK self-assigned this Apr 12, 2017
@HaoK HaoK added this to the 2.0.0-preview1 milestone Apr 12, 2017
@rposener
Copy link
Author

@HaoK I see what you mean - just have the handler go ahead and mark the other requirements as succeeded. Effectively turning the AND to an OR. Only down side is that it will break in the event I did need to add a AND to the policy. Not sure I like that either.

@Eilon Eilon modified the milestones: 2.0.0-preview1, 2.0.0-preview2 Apr 20, 2017
@HaoK HaoK changed the title Can you map Policy to Requirements at Runtime? Add IAuthorizationHandlerProvider interface Apr 27, 2017
@HaoK
Copy link
Member

HaoK commented May 26, 2017

e940cdb

@HaoK HaoK closed this as completed May 26, 2017
@HaoK HaoK added 3 - Done and removed 2 - Working labels May 26, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants