In my program I want to
I check the 1st condition in startup with the following code:
services.AddAuthorization(options =>
{
// This policy checks if a user is registered in our Users table.
options.AddPolicy(
"UserIsRegistered",
new AuthorizationPolicyBuilder()
.AddRequirements(new RegistrationRequirement())
.Build());
});
I also add
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers().RequireAuthorization("UserIsRegistered");
});
and I define the RegistrationRequirement and the RegistrationAuthorizationHandler accordingly.
For the 2nd condition, I created an attribute CrudAuthorizeAttribute with its CrudAuthorizationHandler. Since I have one different police for each possible Crud action, I created a CrudPolicyProvider.
Then I registered everything in Startup:
services.AddTransient<IAuthorizationHandler, RegistrationAuthorizationHandler>();
services.AddTransient<IAuthorizationHandler, CrudAuthorizationHandler>();
services.AddTransient<IAuthorizationPolicyProvider, CrudPolicyProvider>();
Now I see when I am checking the 1st condition I'm getting the policy from CrudPolicyProvider but I expect this policy generator to provide policies only in the 2nd condition.
Therefore:
CrudPolicyProvider has to be used only with the CrudAttribute and nowhere else?IAuthorizationHandler)services.AddTransient<IAuthorizationPolicyProvider, FirstPolicyProvider>();
services.AddTransient<IAuthorizationPolicyProvider, SecondPolicyProvider>();
and use each one only when required?
GeneralPolicyProvider and inside this provider check which policies I have to provide each time depending on the situation I am? (something like using the POLICY_PREFIX here?).Thanks!
can I define two policy providers (as I can do with IAuthorizationHandler)and use each one only when required
You could. But the two separated policy providers won't be activated correspondingly. You might have multiple policy providers, but only one of them will be used at the same time. Also there's no magic when using IAuthorizationPolicyProvider.
define a single GeneralPolicyProvider .... check which policies I have to provide each time depending on the situation I am? (something like using the POLICY_PREFIX here?).
Yes. But you don't have to use Policy_Prefix everywhere. In that way you'll repeat yourself too many times.
A better way is to inject a IHttpContextAccessor service into GeneralPolicyProvider, such that you can check the current EndPoint/HttpContext at run-time, and then you can resolve the target Policy Provider dynamically.
An implementation looks like:
public class GenericPolicyProvider : IAuthorizationPolicyProvider
{
private readonly IHttpContextAccessor _httpContextAccessor;
private AuthorizationOptions _authZOpts { get; }
public DefaultAuthorizationPolicyProvider FallbackPolicyProvider { get; }
private IAuthorizationPolicyProvider _fstPolicyProvider {get;set;}
private IAuthorizationPolicyProvider _sndPolicyProvider {get;set;}
public GenericPolicyProvider(IHttpContextAccessor httpContextAccessor, IOptions<AuthorizationOptions> options)
{
this._httpContextAccessor = httpContextAccessor;
this._authZOpts = options.Value;
this.FallbackPolicyProvider = new DefaultAuthorizationPolicyProvider(options);
this._fstPolicyProvider = new FirstPolicyProvider(options.Value);
this._sndPolicyProvider = new SecondPolicyProvider(options.Value);
}
// use the target provider to provide policy
public Task<AuthorizationPolicy> GetPolicyAsync(string policyName)
{
var targetPolicyProvider = this.GetPolicyProvider(policyName);
return targetPolicyProvider.GetPolicyAsync(policyName);
}
// get the target provider dynamically
private IAuthorizationPolicyProvider GetPolicyProvider(string policyName)
{
var httpContext = this._httpContextAccessor.HttpContext;
if(httpContext==null) throw new Exception("HttpContext must not be null");
// now you get the HttpContext
// check HttpContext to determine which policy provider should be used
// ...
// or check endpoint,e.g. get a mark filter by endpoint.Metadata.GetMetadata<...>()
var endpoint = httpContext.GetEndpoint();
var someMarker = endpoint.Metadata.GetMetadata<SomeMarker>();
// in short, resolve the policy provider dynamically:
if(shouldUseFirstPolicyProvider())
return this._fstPolicyProvider;
else if(shouldUseSecondPolicyProvider())
return this._sndPolicyProvider;
else
return this.FallbackPolicyProvider;
}
...
}
Finally, don't forget to register this GenericPolicyProvider in Startup.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With