Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Authorize Policy attribute always returns 403 forbidden using .net core Identity and JwtBearerAuthentication

Following this guide I was able to get authentication working using

Microsoft.AspNetCore.Identity.EntityFrameworkCore
Microsoft.AspNetCore.Authentication.JwtBearer

Now I'm trying to secure my api endpoints with either roles, or claims. I've tried both with the same result (403)

Using just [Authorize] works fine.

My code currently looks something like this:

Controller:

[Authorize(Policy = "RequireUserRole")]
// Also tried [Authorize(Roles="User")]
public string Get()
{   
  return "YO";
}

Startup:

services.AddIdentity<IdentityUser, IdentityRole>().AddEntityFrameworkStores<ApplicationContext>();
services.Configure<JWTSettings>(Configuration.GetSection("JWTSettings"));
services.AddAuthorization(options =>
{
        options.AddPolicy("RequireUserRole", policy => policy.RequireRole("User"));
});

...

app.UseIdentity();

var secretKey = Configuration.GetSection("JWTSettings:SecretKey").Value;
var issuer = Configuration.GetSection("JWTSettings:Issuer").Value;
var audience = Configuration.GetSection("JWTSettings:Audience").Value;
var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(secretKey));

app.UseJwtBearerAuthentication(new JwtBearerOptions
{
        AutomaticAuthenticate = true,
        AutomaticChallenge = true,
        TokenValidationParameters = new TokenValidationParameters
        {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = signingKey,

                // Validate the JWT Issuer (iss) claim
                ValidateIssuer = true,
                ValidIssuer = issuer,

                // Validate the JWT Audience (aud) claim
                ValidateAudience = true,
                ValidAudience = audience,

                ValidateLifetime = true
        }
});

app.UseMvcWithDefaultRoute();

and when I create the user I assign it to the role "User"

await _userManager.AddToRoleAsync(user, "User");

The role relationship is being created successfully, but the validation for the role when hitting the endpoint is failing.

Any help appreciated!

like image 642
Kolby Avatar asked Jun 14 '17 22:06

Kolby


People also ask

How does Authorize attribute work in ASP.NET Core?

Authorization in ASP.NET Core is controlled with AuthorizeAttribute and its various parameters. In its most basic form, applying the [Authorize] attribute to a controller, action, or Razor Page, limits access to that component to authenticated users. Now only authenticated users can access the Logout function.

How does the Authorize attribute work?

Web API provides a built-in authorization filter, AuthorizeAttribute. This filter checks whether the user is authenticated. If not, it returns HTTP status code 401 (Unauthorized), without invoking the action. We can apply the filter globally, at the controller level, or at the level of individual actions.

Where can the Authorize attribute can be applied?

You can place the Authorize attribute on a controller or on individual actions inside the controller. When we place the Authorize attribute on the controller itself, the authorize attribute applies to all of the actions inside.


1 Answers

The answer is in this mdsn blog post:

Authorizing based on roles is available out-of-the-box with ASP.NET Identity. As long as the bearer token used for authentication contains a roles element, ASP.NET Core’s JWT bearer authentication middleware will use that data to populate roles for the user.

So, a roles-based authorization attribute (like [Authorize(Roles = "Manager,Administrator")] to limit access to managers and admins) can be added to APIs and work immediately.

So I added an element to my access token object called roles:

private string GetAccessToken(string userRole)
{
    var payload = new Dictionary<string, object>
    {
        ...
        { "roles", userRole } 
    };
    return GetToken(payload);
}
like image 96
Kolby Avatar answered Oct 29 '22 21:10

Kolby