2
votes

I am trying to learn more about Identity Server. I am currently struggling to get Role Based Authorisation working. Here are the steps I have followed:

1) Download the sample solution: https://github.com/IdentityServer/IdentityServer4.Samples/tree/release/Quickstarts/6_AspNetIdentity

2) Run the solution, which starts:

a) Identity Server project

b) MVC project

c) API project

3) Browse to the MVC project and apply migrations. 4) Register a new user: [email protected] 5) Browse to: CallApiUsingUserAccessToken in the MVC project. The API is reached as expected because the user is authorised.

Say I now wanted to change IdentityContoller from this:

[Authorize] 
public class IdentityController : ControllerBase 

to this:

[Authorize(Roles="Admin")] 
public class IdentityController : ControllerBase 

and Home Controller (https://github.com/IdentityServer/IdentityServer4.Samples/blob/release/Quickstarts/6_AspNetIdentity/src/MvcClient/Controllers/HomeController.cs) from this:

public async Task<IActionResult> CallApiUsingUserAccessToken()

to this:

[Authorize(Roles="Admin")] 
public async Task<IActionResult> CallApiUsingUserAccessToken()

What changes would I have to make to the configuration?

I have tried a few suggestions this afternoon. For example, in the startup of the MVCClient I tried adding:

options.ClaimActions.MapJsonKey("role", "role", "role");
options.TokenValidationParameters.NameClaimType = "name";
options.TokenValidationParameters.RoleClaimType = "role";

Please assume that I have correctly added the roles to the identity database (and associated the roles with the users).

1
At some point in your implementation you will need to read the roles from your database and add them to your ClaimsIdentity with a type of ClaimType.Roleste-fu
@ste-fu, could you post an answer?w0051977

1 Answers

4
votes

What you are looking for is the AddProfileService() method where you can add your custom implementation of the IProfileService interface where you can customize the claims to add to the access token.

Here's an example using Identity which adds the role claim to the token

public class ProfileService : IProfileService
{
    protected UserManager<ApplicationUser> _userManager;

    public ProfileService(UserManager<ApplicationUser> userManager)
    {
        _userManager = userManager;
    }

    public async Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
        var user = await _userManager.GetUserAsync(context.Subject);
        var roles = await _userManager.GetRolesAsync(user);
        var claims = new List<Claim>
        {
            new Claim(JwtClaimTypes.Role, roles.Any() ? roles.First() : "Standard")
        };

        context.IssuedClaims.AddRange(claims);
    }

    public async Task IsActiveAsync(IsActiveContext context)
    {
        var user = await _userManager.GetUserAsync(context.Subject);
        context.IsActive = (user != null) && user.LockoutEnabled;
    }
}

Then in the startup, tell idp to use your class

var builder = services.AddIdentityServer(options =>
                {
                    options.Events.RaiseErrorEvents = true;
                    options.Events.RaiseInformationEvents = true;
                    options.Events.RaiseFailureEvents = true;
                    options.Events.RaiseSuccessEvents = true;
                })
                .AddInMemoryIdentityResources(Config.GetIdentityResources())
                .AddInMemoryApiResources(Config.GetApiResources())
                .AddInMemoryClients(Config.GetClients())
                .AddAspNetIdentity<ApplicationUser>()
                .AddProfileService<ProfileService>();