问题
I'm using Identity Server 4 and I've customised my ASP.NET Identity user as follows:
public class ApplicationUser : IdentityUser
{
[MaxLength(100)]
public virtual string FirstName { get; set; }
[MaxLength(100)]
public virtual string LastName { get; set; }
}
I can't see where I would configure Identity Server 4 to include these 2 properties in the claims collection. I've had a look through some of the Identity Server 4 samples but can't see any examples.
I'd ideally like to map these 2 user properties to the given_name
and family_name
claims.
I'm currently hooking up to the notifications and querying the userinfo
endpoint (hybrid flow?). So I'm not sure if this is configuration of Identity Server or customization of the userinfo
endpoint?
回答1:
In order to include your custom claims, you need to implement your own GetProfileDataAsync()
method using the IProfileService
. This method is being called everytime a user claim is requested.
Here is my implementation of IProfileService.
public class CustomProfileService : IProfileService
{
private readonly UserManager<User> _userManager;
public CustomProfileService(UserManager<User> userManager)
{
_userManager = userManager;
}
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var subjectId = context.Subject.GetSubjectId();
var user = await _userManager.FindByIdAsync(subjectId);
if (user == null) return;
var claims = new List<Claim>
{
new Claim("username", user.UserName),
new Claim("email", user.Email),
new Claim("firstname", user.FirstName),
new Claim("lastname", user.LastName)
};
var roles = await _userManager.GetRolesAsync(user);
foreach (var role in roles)
{
claims.Add(new Claim("role", role));
}
var userClaims = await _userManager.GetClaimsAsync(user);
foreach (var userClaim in userClaims)
{
claims.Add(new Claim(userClaim.Type, userClaim.Value));
}
context.IssuedClaims = claims;
}
public async Task IsActiveAsync(IsActiveContext context)
{
var user = await _userManager.FindByIdAsync(context.Subject.GetSubjectId());
context.IsActive = user.IsActive;
}
}
Then you will have to add this following line to Startup.ConfigureServices()
services.AddScoped<IProfileService, CustomProfileService>();
回答2:
I was wondering why there is no documentation on this. It lead me to realise that I'm probably doing it wrong.
I'd not seen the table AspNetUserClaims
created as part of ASP.NET Identity. I added my claim data into here and the claim data pulls through as part of the profile
.
In the POST
method for AccountController.Register
I added:
var givenNameClaim = new IdentityUserClaim<string>()
{
ClaimType = "given_name",
ClaimValue = model.FirstName
};
var familyNameClaim = new IdentityUserClaim<string>()
{
ClaimType = "family_name",
ClaimValue = model.LastName
};
var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
user.Claims.Add(givenNameClaim);
user.Claims.Add(familyNameClaim);
回答3:
Here's what I've done: In AccountController.ExternalLoginCallback I added this:
//Add claim even if client didn't ask for it
additionalClaims.Add(new Claim(JwtClaimTypes.Email, "email@email.com"));
then I added the claim to the access_token
by dependency injecting my ProfileService
class and adding the claims in the MyProfileService.GetProfileDataAsync
like this:
public Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var claims = new List<Claim>();
Claim emailClaim = context.Subject.Claims.Where<Claim>(claim => claim.Type.Equals(JwtClaimTypes.Email)).FirstOrDefault();
if (emailClaim != null)
{
claims.Add(emailClaim);
}
context.IssuedClaims = claims;
return Task.FromResult(0);
}
来源:https://stackoverflow.com/questions/44392817/customizing-asp-net-identity