If you’ve worked on Identity Server 4 surely you’ll notice there is a lack of tutorial on how to-do somethings. For example how to implement roles, and using azure active directory (AAD), splitting data to server and etc. For this tutorial we will tackle on how to implement roles on IdentityServer4 running on ASP.NET Identity setup.
Come on, let’s jump in!
First of all, you must have a .NET Core 3.1 SDK (Software Development Kit) installed in your computer and I also assumed you are currently running Windows 10 or some Linux with proper environment set.
And the IdentityServer4 package on which we will dive in. The IdentityServer as a whole has been one of the de-facto standard in large scale deploy-able authentication service for .NET driven ecosystem. It uses OpenID Connect and OAuth 2.0 as base technology.
So where do we start?
The first thing we need to do, is to fetch the official starter template for IdentityServer4. In order to do that we need execute the following code below:
The command above will install the IdentityServer4 template in your workstation.
After installing the official templates, we create and bootstrap our project on which we will call Is4RoleDemo.
As a rule of thumb, always run the bootstrapped code first to see if there are no errors and whatsoever. Then if there are no problems commit it to a version control system (VCS), so you could rollback if there’s a problem.
We can now start modifying the project. Start by editing the Config.cs which can be found on the root directory.
The Config.cs contains initial data that can be used to run IdentityServer4 for in-memory storage setup. The in-memory storage should only be used in non-production environment.
First, we insert and create a new client on the variable named clients inside Config.cs file. This new config will require the client to have PKCE (Proof Key for Code Exchange) enabled authentication and verification (currently authentication with PKCE is now the standard in OAuth 2.0).
After configuring the clients, we need to add roles to the initial seed data. Edit the SeedData.cs file and add the following before the user seed data.
The code above specifies two new roles which are member and admin. After adding the roles, we need to assign the roles to the seed users. Add the code below after the user initialization specifically alice’s user initialization.
What this does is, it will add the specific role to the user on the AspNetRoles mapping table. Same with alice put the code below bob’s user initialization in SeedData.cs.
With all that implemented, adding roles and assigning roles to users. We need now to get the roles and put it on to user claims and return it as part of user info.
To return the roles on claims we will implement a profile service that will inject the roles. To do that, we create a folder Services and a class file named ProfileService.cs inside it.
The ProfileService class will inherit the IProfileService trait. Then we override the method GetProfileDataAsync(ProfileDataRequestContext context) inside the class and put the code below.
The code above specifically search for the specific user and check whether that returned user data is assigned to any roles. And if it satisfy that condition then modify the current claims adding the role assigned for that user.
Check the whole source for the ProfileService class below and compare it with your current code.
We should head now to the Startup.cs file to create and initialize the class ProfileService class that we’ve created. Put the code inside the ConfigureServices(IServiceCollection services) method. This will scoped the class and inject our custom implementation to the service.
Finally, build and run the project to see if there are any errors using dotnet build and dotnet run. If everything is okay, test the implementation using Postman.
On postman window, make sure to set the authentication to OAuth 2.0 with PKCE and query to /userinfo endpoint of the identity service. If everything is correct, on the OAuth 2.0 get token tab — copy the JWT token returned by our identity service.
After copying the JWT token, we put the token on a JWT analyzer site like https://www.jsonwebtoken.io/. The site will analyze and return a JSON structure on which we will use to confirm if the role has been added properly.
If you look above the JSON, you’ll see there is a role field included that means we succeeded in adding roles to the claims. Otherwise, debug and see the ProfileService class if the user is returning roles.
(Optional) Connecting to MVC ASP.NET Core projects
To use the identity service we created in your own MVC project. First and foremost, we need to add in the MVC project the Microsoft.AspNetCore.Authentication.OpenIdConnect package using NuGet package manager.
Then on Startup.cs we add and configure the OpenId Connect driver to connect to our newly created identity service. Then modify the AddOpenIdConnect option and add the code below, this will map the roles to the authorize attribute field roles.
To use the roles in controllers you need to import Microsoft.AspNetCore.Authorization namespace. This will let you use the authorize attribute to secure the class or method that you intend to filter out users.
I think that’s all for it, check the full source repository in following link below.
Working with IdentityServer4 is somewhat pain in the ass — as developer support is locked behind a paywall. There are many ways to put roles in claims, but I think this is the most simplified and easiest implementation there is. With roles you can now filter out users accessing specific endpoints.
You can found the complete repository here.
Follow me for similar article, tips, and tricks ❤.