7

I'm building an API in .NET Core 1.1. I build a custom User object from HttpContext.User in a base controller that all of my other controllers inherit from, and I have authentication enabled by default (must be manually disabled with [AllowAnonymous] when necessary). The User object has an IsAdmin property. Right now I'm checking if the user is an admin at the top of each relevant function like below, but I feel like there must be a way to add a custom attribute to simplify and clean up this code.

For reference, User.IsAdmin is shorthand for this:

bool.Parse(HttpContext.User.FindFirst("IsAdmin")?.Value)

Instead of this:

[HttpGet]
public async Task<IActionResult> Get()
{
    if (!User.IsAdmin)
        return Forbid();

    // logic
}

I'd like this (or something similar):

[AdminOnly]
[HttpGet]
public async Task<IActionResult> Get()
{
    // logic
}

I tried looking at the source for [AuthorizeAttribute] to try to build from, but it's just a shell and I don't know where the real magic happens.

How can I accomplish this?

Lukasz Mk
  • 7,000
  • 2
  • 27
  • 41
vaindil
  • 7,536
  • 21
  • 68
  • 127
  • 4
    I suggest read the docs about policy based authorization, you basically use an attribute with a named policy then you define the policy in startup to require some role or claim or other rule https://learn.microsoft.com/en-us/aspnet/core/security/authorization/policies – Joe Audette Jan 07 '17 at 20:21
  • Check the answer from @blowdart (responsible for ASP.NET Core security), you shouldn't (or have the need) create your own attributes – Tseng Jan 07 '17 at 20:27
  • @JoeAudette Looks like that's what I need, not sure how I missed it. :/ [Claims-based auth](https://learn.microsoft.com/en-us/aspnet/core/security/authorization/claims#adding-claims-checks) will work, as I only need to verify that the claim is `true`. If you add that as an answer I'll accept it. – vaindil Jan 07 '17 at 20:33

1 Answers1

9

The solution suggested by @JoeAudette seems to be the best option.


Create your own policy in Startup.cs ConfigureServices():

services.AddAuthorization(options => 
    options.AddPolicy("PolicyName", p =>
    {
        p.RequireAuthenticatedUser();
        p.RequireClaim("IsAdmin", true); <- your criteria here (claim type, claim value) ???
        p.Build();
    })
);


Then just use it as an attribute:

[Authorize("PolicyName")]
Richard Garside
  • 87,839
  • 11
  • 80
  • 93
Lukasz Mk
  • 7,000
  • 2
  • 27
  • 41