OdeToCode IC Logo

Evaluating ASP.NET Core Authorization Policies

Thursday, May 30, 2019

Let’s say you have the following authorization policy defined in the Configure method of your ASP.NET Core’s Startup class.

.AddAuthorization(options =>
{
    options.AddPolicy("IsLucky", builder =>
    {
        var random = new Random();
        builder.RequireAssertion(_ => random.Next(1, 100) < 75);
    });
})

This policy will grant access about ¾ of the time. It is easy to apply the policy to a controller or Razor page using the Authorize attribute.

[Authorize(Policy = "IsLucky")]
public class SecretsModel : PageModel
{
      // ...
}

But, what if you want to imperatively check the policy? For example, when building a navigation menu, you want to know if the user will be able to perform a given action or reach a specific resource before displaying links and command buttons in the UI. In this scenario, ask for an IAuthorizationService type object in any controller or Razor page. The auth service combines a claims principal and a policy name to let you know if the user authorization check succeeds.

For example, in the page model for a Razor page:

public class SecretsModel : PageModel
{
    public bool IsLucky { get; set; }
    private readonly IAuthorizationService authorization;

    public SecretsModel(IAuthorizationService authorization)
    {
        this.authorization = authorization;
    }

    public async Task OnGet()
    {
        var result = await authorization.AuthorizeAsync(User, "IsLucky");
        IsLucky = result.Succeeded;
    }
}

And then in the page itself:

@if(Model.IsLucky)
{
    <div>You got lucky!</div>
}
else
{
    <div>No luck for you :(</div>
}

Of course, having an authorization policy that uses a a random number generator is weird, but I'm hoping to work it into a "random access" policy joke someday.