5
votes

My problem: [Authorize(Roles = "L1")] and User.IsInRole("L1") are looking for the claim name "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" instead of "role"

In concrete: I have created an IdentityServer4 with the standard identity database by the following steps (http://docs.identityserver.io/en/release/quickstarts/6_aspnet_identity.html):

  • Create new Project
    • ASP.NET Core Web Application(.NET Core)
    • ASP.NET Core 1.1
    • Web Application
    • Change Authentication
      • Individual User Accounts
  • Add IdentityServer4.AspNetIdentity + Config.cs + ...

Then I have created a MVC-Client. The Authentication works fine. I get also a list of claims.

I am using the tables AspNetUsers, AspNetUserRoles and AspNetRoles in for the IdentityServer4 to configure role. The roles are added to the claims with the claim name "role".

If I try to authorize my controller actions in the MVC-Client it seems that the claim name for my roles is wrong.

How can I solve the conflict? Do I have to map "role" to "http://schemas.microsoft.com/ws/2008/06/identity/claims/role"?

Here is my controller in the MVC-Client:

[Route("api/[controller]")]
public class CompaniesController : Controller
{
    [HttpGet]
    //[Authorize(Roles = "L1")] // This looks for the claim http://schemas.microsoft.com/ws/2008/06/identity/claims/role instead of role
    public async Task<IEnumerable<Company>> GetCompaniesAsync()
    {
        var c = User.Identities.Count(); // 1
        var nameOfExptectedRoleClaimType = User.Identities.First().RoleClaimType; // http://schemas.microsoft.com/ws/2008/06/identity/claims/role
        var b0 = User.HasClaim(nameOfExptectedRoleClaimType, "L1"); // false
        var b1 = User.HasClaim("role", "L1"); // true
        var b2 = User.IsInRole("L1"); // false; looks for claim http://schemas.microsoft.com/ws/2008/06/identity/claims/role; used by [Authorize(Roles = "L1")]

        var companies = await _crmApi.GetCompaniesAsync();

        return companies;
    }
}

I have found this answer (https://stackoverflow.com/a/34226538/272357) but I do not know how to "register" CustomPrinciple.

1
The found answer does not work with asp.net-core because a UserManager with generic ClaimsPrinciple-Parameter doesn't exist in Microsoft.AspNetCore.Identity.Nikolaus

1 Answers

8
votes

I have found an answer for myself. I have to mention that I am using JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); to avoid the renaming of the claim names (see the code).

The resulting problem was that ClaimsPrinciple still looks for roles named with "http://schemas.microsoft.com/ws/2008/06/identity/claims/role".

This could be fixed indirectly with OpenIdConnectOptions.TokenValidationParameters.

public class Startup
{
  public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
  {
    // ...

    // Avoid claim mapping to old ms soap namespaces. Avoid replace "role" by "http://schemas.microsoft.com/ws/2008/06/identity/claims/role"
    JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

    app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
    {
      // ...

      // https://leastprivilege.com/2016/08/21/why-does-my-authorize-attribute-not-work/
      TokenValidationParameters = new TokenValidationParameters
      {
        NameClaimType = "name",
        RoleClaimType = "role", // The role claim type is named "role" instead of "http://schemas.microsoft.com/ws/2008/06/identity/claims/role"
      }

    });
  }
}