I am attempting to write a Policy-based Authorization Handler. The business logic of the handler needs to use the record id of the current request that is passed in through the default route.
[Authorize(Roles = "TaskAdmin", Policy = "RecordOwner")]
public IActionResult Index(int id) // <-- Need this id
{
// <snip>
return View();
}
Policy
Here is the class where I need to access the id route value.
public class RecordOwnerHandler : AuthorizationHandler<RecordOwnerRequirement>
{
private readonly ApplicationDbContext dbContext;
public RecordOwnerHandler(ApplicationDbContext dbContext)
{
this.dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, RecordOwnerRequirement requirement)
{
if (IsUserAuthorized(context))
{
context.Succeed(requirement);
}
//TODO: Use the following if targeting a version of
//.NET Framework older than 4.6:
// return Task.FromResult(0);
return Task.CompletedTask;
}
private bool IsUserAuthorized(AuthorizationHandlerContext context)
{
//****************************************
// Need the id here...
//****************************************
// Return the result
return true;
}
}
Startup
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
// *** Add policy for record owner ***
services.AddAuthorization(options =>
{
options.AddPolicy("RecordOwner", policy =>
policy.Requirements.Add(new RecordOwnerRequirement()));
});
// Add application services.
services.AddTransient<IEmailSender, EmailSender>();
// *** Register record owner handler with the DI container ***
services.AddTransient<IAuthorizationHandler, RecordOwnerHandler>();
services.AddMvc();
}
What I Tried
I tried using the
IHttpContextAccessoras a constructor parameter ofRecordOwnerHandler, butIHttpContextAccessor.HttpContextdoesn't seem to contain theRouteDataof the request.I did several Google searches to see if there was any info about how to do this and came up blank.
Then I dug through the source code for both Routing and Model Binding, but can't seem to find an abstraction that is meant for injecting route values into services.
I realize I could try to parse this info out of the URL, but I am hoping for a cleaner way to get the value.
So, how can I access route values and/or value provider data inside of a service in ASP.NET Core 2.0?