Configuring Identity Server to use ASP.NET Identit

2019-03-01 13:34发布

问题:

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: Bert@Bert.com 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:

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>();