I'm after the API that allows to apply [Authorize]
attribute from API rather than having it on controller's class/method.
Consider third party controller classes that come from dependency nuget package and I want to host them in my application and implement security for them. I know I can use
app.UseEndpoints(endpoints => { endpoints.MapControllers().RequireAuthorization(new AuthorizeAttribute("policy")); });
but this will configure ALL controllers and methods to be protected by policy
and I need to have control per class/method.
Mapping manually with
endpoints.MapPut("***").RequireAuthorization(new AuthorizeAttribute("someOtherPolicy"))
is also not an option since the mapping is already defined with [Microsoft.AspNetCore.Mvc.HttpPost, Microsoft.AspNetCore.Mvc.Route("api/someRoute")]
attributes on imported controllers.
Please advise
CodePudding user response:
In case you can determinate on which endpoint should be specific authorization policy applied, you can try following:
public class MyAuthorizationFilter: AuthorizeAttribute, IAsyncAuthorizationFilter
{
public MyAuthorizationFilter() : base()
{
//this.AuthenticationSchemes = "";
//this.Policy = "";
//this.Roles = "";
}
public Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
context.Result = new OkObjectResult("my custom policy was checked");
return Task.CompletedTask;
}
}
public static class DynamicAuthorizationPolicies
{
public static void RegisterMyFilters(this IServiceProvider serviceProvider)
{
var allEndpoints = serviceProvider
.GetService<IActionDescriptorCollectionProvider>()
?.ActionDescriptors
?.Items;
if (allEndpoints is null)
{
return;
}
foreach (var endpoint in allEndpoints)
{
// If you debug hier you will see that you can register
// differnt filters or attribute in different collections
// for the endpoint
if (/*endpoint match some requirement*/true)
{
var authorizeFilter = serviceProvider.GetService<MyAuthorizationFilter>();
var descriptor = new FilterDescriptor(authorizeFilter, FilterScope.Action);
endpoint.FilterDescriptors.Add(descriptor);
}
}
}
}
... and here is the usage:
public void ConfigureServices(IServiceCollection services)
{
// services.Add...
services.AddTransient<MyAuthorizationFilter>();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// app.Use....
app.ApplicationServices.RegisterMyFilters();
}