1

I'm using the new React template, which is part of the .NET Core 3 release. This template uses Microsoft.AspNetCore.ApiAuthorization.IdentityServer to integrate ASP.NET Core Identity, IdentityServer and React for user registration, authentication and authorization.

This works really well for simple scenarios, but I find the documentation for a bit more complex scenarios confusing. This is mainly because there are a lot of different cogs now, and it's hard to figure out where to look.

What I want to do is the following: I want to add a custom claim to the user (say, IsAdmin: true). This claim should be available in the .NET Core HttpContext in the ApiController (as part of the user's claim principal) for auth purposes, and it should be somewhere that React can read this claim (this would probably be the identitytoken/jwt), to provide a good user experience.

What would be a good way to accomplish this?

Nick Muller
  • 2,003
  • 1
  • 16
  • 43
  • 1
    Do you want the claims to appear in access token as well? – Aparna Gadgil Nov 08 '19 at 16:32
  • @AparnaGadgil That would probably be best. I think that's the easiest way to get it in the User Principal for the current request, right? – Nick Muller Nov 08 '19 at 16:34
  • Yes correct! I have added my answer below to get custom claims in access code. – Aparna Gadgil Nov 08 '19 at 16:38
  • Hi Nick, Just wondering if you managed to sort this out. I'm having exactly the same issue trying to work out how to add custom claims or role claims down to the client? – TheLearningDev Dec 17 '19 at 04:53
  • For more background information take a look at the answers [here](https://stackoverflow.com/questions/53976553/identityserver4-role-based-authorization-for-web-api-with-asp-net-core-identity). –  Dec 17 '19 at 11:19

2 Answers2

2

I think you should check ApiResource configuration. Whatever claims you add in UserClaims property of ApiResource configuration, those claims will appear in access token. e.g

 public IEnumerable<ApiResource> GetApiResources()
 {
      return new List<ApiResource>
      {
            new ApiResource("api1")
            {
                UserClaims = new[] { "CustomClaim1", "CustomClaim2"},
            }, 
       }
 }

In above code, access code will contain CustomClaim1 and CustomClaim2. Hence if you don't mention them, they won't appear in access token. Hope this helps!

Aparna Gadgil
  • 410
  • 4
  • 9
  • Thanks! But do you have any clue how I accomplish that with the ApiAuthorization integration package I mentioned? It seems the ApiResource is generated here, and I'm not sure how to customize it: https://github.com/aspnet/AspNetCore/blob/v3.0.0/src/Identity/ApiAuthorization.IdentityServer/src/IdentityServerBuilderConfigurationExtensions.cs – Nick Muller Nov 08 '19 at 16:38
  • And this class does the actual building of the ApiResource: https://github.com/aspnet/AspNetCore/blob/v3.0.0/src/Identity/ApiAuthorization.IdentityServer/src/Options/ApiResourceBuilder.cs – Nick Muller Nov 08 '19 at 16:38
  • Have you checked this documentation? - https://learn.microsoft.com/en-us/aspnet/core/security/authentication/social/additional-claims?view=aspnetcore-3.0 – Aparna Gadgil Nov 08 '19 at 16:45
2

You can use IProfileService to add custom claims to JWT token :

public class MyProfileService : IProfileService
{
    public MyProfileService()
    { }

    public Task GetProfileDataAsync(ProfileDataRequestContext context)
    {

        var claims = new List<Claim>()
        {

            new Claim(ClaimTypes.Role, "Admin")
        };
        context.IssuedClaims.AddRange(claims);
        return Task.CompletedTask;
    }

    public Task IsActiveAsync(IsActiveContext context)
    {
        // await base.IsActiveAsync(context);
        return Task.CompletedTask;
    }
}

Concern about the length of ID Token , by default the claims won't include in ID token , instead it will get claims from OIDC's userinfo endpoint . You can:

  1. Get the claims from user.profile in React template , it will automatically send request to userinfo endpoint with id token .

  2. Or you can set AlwaysIncludeUserClaimsInIdToken to true in client options when registering client in Identity Server 4 , but i'm afraid you need to not use ApiAuthorization service, the full power of IdentityServer is still available to customize authentication to suit your needs.

Nan Yu
  • 26,101
  • 9
  • 68
  • 148
  • I think your comment about not using the `ApiAuthorization` might just hit the nail on the head. I think it's not documented well enough atm (at least for me), so it might just be easier to use IdentityServer directly instead of via this abstraction. IdentityServer itself is documented much much better. – Nick Muller Nov 11 '19 at 08:57
  • Yes , `ApiAuthorization` just configures IdentityServer to use template supported configuration , but the configuration is not fully customize compare to Identity server provided configuration – Nan Yu Nov 11 '19 at 09:04
  • Hi Nan do you happen to have an example of how you got this working I cannot get my custom claim to appear on the user.profile in the react template – TheLearningDev Dec 17 '19 at 04:55
  • Do you register the IProfileService in statup.cs ?services.AddTransient(); – Nan Yu Dec 17 '19 at 05:10
  • answer is incomplete, however it does work. Adding registration to the answer would help. – Michael Brown Aug 01 '22 at 21:04