0

I have a doubt on API securing with identity server4

IdentityResource

Name Claims
Roles role

APIResource

Name Scopes
testapi api1

APIScopes

Name Claims
api1 address

In Startup.cs

services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
                .AddJwtBearer("Bearer", opt =>
                {
                    opt.Audience = "testapi";

                    opt.Authority = "https://localhost:5001";
                    opt.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
                    {
                       ValidateAudience = true
                       
                    };
                });
//Policy "Apiscope" created 
services.AddAuthorization(opt =>
            {
                opt.AddPolicy("Apiscope", policy =>
                {
                    policy.RequireAuthenticatedUser();
                    policy.RequireClaim("Scope", "api1");
                    
                });

            });

services.AddAuthorization(opt =>
            {
                opt.AddPolicy("AdminUsers", policy =>
                {
                    policy.RequireAuthenticatedUser();
                    policy.RequireRole("admin");

                });

            });

In controller

[HttpPost]
        [Authorize(Policy = "AdminUsers")]
        public IActionResult GetAdminMessage()
        {
            return Ok("Hello Admin");
        }
  1. Is it possible access identity scope in .Net Core API? if yes, How to do?
  2. To get the role value, do I need to add in APIScopes of "api1" userclaims as "address,role" or can do it by above Q1 ?
  3. In Policy "AdminUser", I am checking role by adding "api1" (APIScopes) userclaims as "address,role" but I could not access GetAdminMessage(). How to achieve this?
leo
  • 451
  • 1
  • 3
  • 12

1 Answers1

0

Is it possible access identity scope in .Net Core API? if yes, How to do?

The claims in the IdentityResources goes into the ID-Token. The content of the ID-Token is "converted" into the ClaimsPrincipal User object when you login in the client (AddOpenIDConnect). After that the ID-token is not used.

To get the role value, do I need to add in APIScopes of "api1" userclaims as "address,role" or can do it by above Q1 ?

APIScopes are on the API Side. API's receives Access-Tokens and it contains the user claism from the ApiSCopes and ApiResources. The claims in the access-token is converted into the user object in the API (using the AddJwtBearer) and you can use the AddPolicy system to authorize the user.

In Policy "AdminUser", I am checking role by adding "api1" (APIScopes) userclaims as "address,role" but I could not access GetAdminMessage(). How to achieve this?

ASP.NET Core and IdentityServer have different opinions on what the claim types (names) should be, so you need to tell AddJwtBearer what the real name is of your role claim, by using:

    .AddJwtBearer(opt =>
    {
        ...
        opt.TokenValidationParameters.RoleClaimType = "roles";
        opt.TokenValidationParameters.NameClaimType = "name";

You can also add this at the top of the ConfigureServicesmethod:

public void ConfigureServices(IServiceCollection services)
{
    // By default, Microsoft has some legacy claim mapping that converts
    // standard JWT claims into proprietary ones. This removes those mappings.
    JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
    JwtSecurityTokenHandler.DefaultOutboundClaimTypeMap.Clear();

If that does not help ,you can also try add:

options.ClaimActions.MapUniqueJsonKey("role", "role");

To complement this answer, I wrote a blog post that goes into more detail about this topic: Troubleshooting JwtBearer authentication problems in ASP.NET Core and Debugging OpenID Connect claim problems in ASP.NET Core

Tore Nestenius
  • 16,431
  • 5
  • 30
  • 40
  • but its not working `services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme) .AddJwtBearer("Bearer", opt => { opt.TokenValidationParameters.RoleClaimType = "roles"; opt.TokenValidationParameters.NameClaimType = JwtClaimTypes.Name; //opt.TokenValidationParameters.NameClaimType = JwtClaimTypes.Scope; ` In access token role is existing **"role": "admin",** – leo Apr 28 '21 at 01:37
  • you write roles here opt.TokenValidationParameters.RoleClaimType = "roles";and you also write existing "role": "admin", ? role or roles? – Tore Nestenius Apr 28 '21 at 06:18
  • APIResource "testapi" has Scopes "api1" and userclaims as "role, name" I have changed roleClaimType = role but not working. `Services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme) .AddJwtBearer("Bearer", opt => { opt.TokenValidationParameters.RoleClaimType = "role"; opt.TokenValidationParameters.NameClaimType = JwtClaimTypes.Name; ` – leo Apr 28 '21 at 06:34
  • step #1 in troubleshooting this is to check what is actually inside the access token using jwt.io website.. step #2, is to check what claims are actually inside your ClaimPrincipal user object.... Feel free to post that to your question – Tore Nestenius Apr 28 '21 at 07:12
  • In my prev comment I already mentioned that access token has **"role": "admin"**, (cheked using jwt.io) . How to check the objects in ClaimPrincipal user object. I am printing the user calims by `return Ok( new JsonResult(from c in User.Claims select new { c.Type, c.Value }));` getting the result as `{Type: "http://schemas.microsoft.com/ws/2008/06/identity/claims/role", Value: "admin"}` – leo Apr 28 '21 at 07:28
  • Microsoft and OpenID-Connect have different opinion on what the claim names should be. Microsoft likes the URL format. See my updated answer. – Tore Nestenius Apr 28 '21 at 07:35
  • Modified but not working. options.ClaimActions I am not getting `.AddJwtBearer("Bearer", opt => { opt.Audience = "testapi"; opt.Authority = "https://localhost:5001"; opt.TokenValidationParameters = new TokenValidationParameters { ValidateAudience = true, RoleClaimType = "role", NameClaimType = JwtClaimTypes.Name }; });` – leo Apr 28 '21 at 07:54
  • You still see the http://schemas.microsoft.com/ws/2008/06/identity/claims/role" in the User object? you don't have any issue with casing? like role and Role? perhaps try to paste a copy of your access token and startup code and update your question? – Tore Nestenius Apr 28 '21 at 07:59
  • You write [Authorize(Policy = "AdminUsers")] but our policy is named opt.AddPolicy("AdminUser".... typo? – Tore Nestenius Apr 28 '21 at 08:06
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/231686/discussion-between-leo-and-tore-nestenius). – leo Apr 28 '21 at 08:13
  • policy.RequireClaim("role","admin"); solved my issue. Thanks – leo Apr 30 '21 at 02:28