In the previous tutorial, we went over how to add JWT Authentication to our ASP.NET Core Application using Identity Server. Even though the out of the box implementation works great, there are times where we may want to add extra resources to our token such as roles and claims. This can be helpful for implementing some conditional behavior in both our client and server side application. Check out our git repo and courses on full stack development with technologies like React, Angular and ASP.NET Core.

Adding Claims To the JWT

In order the add Claims to the JWT token, you’re going to have to create a class that implements the IdentityServer4.Services.IProfileService interface. This is used to determine the profile data that is placed into the JWT.

public class IdentityClaimsProfileService : IProfileService
{

}

Now that you have the class, you’ll have the implement both GetProfileDataAsync() and IsActiveAsync(). You’ll have to define a ClaimsFactory as well as the UserManager for getting your user information.

private readonly IUserClaimsPrincipalFactory<ApplicationUser> _claimsFactory;
        private readonly UserManager<ApplicationUser> _userManager;

        public IdentityClaimsProfileService(UserManager<ApplicationUser> userManager, IUserClaimsPrincipalFactory<ApplicationUser> claimsFactory)
        {
            _userManager = userManager;
            _claimsFactory = claimsFactory;
        }

Once this is done, use the GetProfileDataAsync method to populate your JWT with the desired User information.

public async Task GetProfileDataAsync(ProfileDataRequestContext context)
        {
            var sub = context.Subject.GetSubjectId();
            var user = await _userManager.FindByIdAsync(sub);
            var principal = await _claimsFactory.CreateAsync(user);
            var roles = await _userManager.GetRolesAsync(user);
            var claims = principal.Claims.ToList();
            claims = claims.Where(claim => context.RequestedClaimTypes.Contains(claim.Type)).ToList();
            claims.Add(new Claim(JwtClaimTypes.GivenName, user.FirstName));
            claims.Add(new Claim(IdentityServerConstants.StandardScopes.Email, user.Email));
            foreach(string role in roles)
            {
                claims.Add(new Claim(JwtClaimTypes.Role, role));
            }
            
            context.IssuedClaims = claims;
        }

As you see here, I place the user’s email and firstname in the token. You can decode the JWT and use this inside of a Javascript or Native application to display the user info without having to do a constant fetch of user information.

Next, we’ll create an implementation of IsActiveAsync. This will check whether the user is valid in your database.

public async Task IsActiveAsync(IsActiveContext context)
        {
            var sub = context.Subject.GetSubjectId();
            var user = await _userManager.FindByIdAsync(sub);
            context.IsActive = user != null;
        }

Now that this is done, now you have to configure your application to use your custom implementation of IProfileService.

Inside of you Statup.cs file, you must use Dependency Injection to specify this implementation.

services.AddTransient<IProfileService, IdentityClaimsProfileService>();

Once this is done, you should get you JWT with all of your custom information.

JWT Decoded

JWT Decoded

Conclusion

Having custom tokens if a great way to add information for use in your SPA application such as React and Angular. Be wary of sending too much information because this can cause the token to be too large. If you’re interested in finding out more about JWT implementation, check out some of our courses or our git repo. Feel free to email me if you’re interested in learning more or becoming an affiliate.

Codebrains Newsletter

Get weekly dev news and tutorials.

Powered by ConvertKit