static void

ASP.Net Core Security

Nuget packages

Startup Configuration


Policy is a richer than simple Role-based authorization.

Configure in Startup.ConfigureServices

services.AddAuthorization(opts =>
	opts.AddPolicy("PolicyName", policy => policy.RequireRole("Administrator")

You can have several named policies, which your Authorize attribute can add together.

Policies can be more complex:

public void ConfigureServices(IServiceCollection services)
    services.AddAuthorization(options =>
        //a role
        options.AddPolicy("AdministratorOnly", policy => policy.RequireRole("Administrator"));
        //a specific claim with paramarray of acceptible values
        options.AddPolicy("EmployeeId", policy => policy.RequireClaim("EmployeeId""123""456"));
        //a custom requirement
        options.AddPolicy("Over21Only", policy => policy.Requirements.Add(new MinimumAgeRequirement(21)));

    services.AddMvc(config =>
        //For MVC config, build a policy (here, must be authenticated)
        var policy = new AuthorizationPolicyBuilder()
        //Add a global filter
        config.Filters.Add(new AuthorizeFilter(policy));

    //register the custom handlers that know what to do with custom requirements
    services.AddSingleton<IAuthorizationHandler, MinimumAgeHandler>();

Custom Requirements

Custom requirements have the IAuthorizationRequirement marker interface

public class MinimumAgeRequirement : IAuthorizationRequirement
    public MinimumAgeRequirement(int age)
        MinimumAge = age;

    public int MinimumAge { getset; }

And an handler (which must be registered in ConfigureServices). If there are 2 handlers for the same requirement, the request is authorized if either succeeds ("or").

public class MinimumAgeHandler : AuthorizationHandler<MinimumAgeRequirement>
    protected override void Handle(AuthorizationContext context, MinimumAgeRequirement requirement)
        //check the claim (and issuer). 
        if (!context.User.HasClaim(
            c => c.Type == ClaimTypes.Age &&
                 c.Issuer == ""))

        //find the claim
        var age = Convert.ToInt32(context.User.FindFirst(
            c => c.Type == ClaimTypes.Age && 
                 c.Issuer == "").Value);

        //test the claim
        if (age >= requirement.MinimumAge)
        //if fails, don't do anything


Old-style [Authorize] attribute and [AllowAnonymous] are still used (there's no Authorize(Users=...) though)

[Authorize(Roles = "Admin,Reader")] //classic style
[Authorize(Policy = "AdminPolicy")]
[Authorize(AuthenticationSchemes = "Cookie,Bearer")]

For login, create a ClaimsPrincipal and await HttpContext.Authentication.SignInAsync("Cookie", userPrincipal,new AuthenticationProperties...

Resource authorisation Conditional authorisation (for instance, user is only able to see their own files)


public class FileController : Controller
    private readonly IAuthorizationService _authorizationService;
    private readonly IFileService _fileService;

    public FileController(IAuthorizationService authorizationService, IFileService fileService)
        _authorizationService = authorizationService;
        _fileService = fileService;

    public async Task<IActionResultEdit(int id)
        var document = _fileService.Find(id);
        if (await _authorizationService.AuthorizeAsync(User, document, "EditPolicy"))
            return View(document);
        return new ChallengeResult();