我正在将两个asp.net核心1.1身份服务器应用程序升级到asp.net核心2。
第一个,IdentityServer A充当联合网关和身份存储。第二个,IdentityServer B使用A作为外部提供者。在我的应用程序域中,客户端应该对B进行身份验证,这会对从A中收到的身份提出额外的声明。
此时认证流程似乎正常,除非B正在向身份添加其他声明。
On A IdentityServer配置如下:
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryClients(Clients.GetClients())
.AddInMemoryIdentityResources(IdentityResources.GetIdentityResources())
.AddAspNetIdentity<ApplicationUser>()
.AddProfileService<ProfileService>();
A上的ProfileService实现如下:
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var user = await _userManager.GetUserAsync(context.Subject);
// Scope: OpenId
AddClaimIfRequested(JwtClaimTypes.Subject, context.RequestedClaimTypes, context.IssuedClaims, user.Id);
// Scope: Profile
AddClaimIfRequested(JwtClaimTypes.GivenName, context.RequestedClaimTypes, context.IssuedClaims, user.Firstname);
AddClaimIfRequested(JwtClaimTypes.FamilyName, context.RequestedClaimTypes, context.IssuedClaims, user.Lastname);
AddClaimIfRequested(JwtClaimTypes.Picture, context.RequestedClaimTypes, context.IssuedClaims, Convert.ToBase64String(user.ProfilePicture));
// Scope: Email
AddClaimIfRequested(JwtClaimTypes.Email, context.RequestedClaimTypes, context.IssuedClaims, user.Email);
}
private void AddClaimIfRequested(string claim, IEnumerable<string> requestedClaims, List<Claim> issuedClaims, string value)
{
if (requestedClaims.Contains(claim))
issuedClaims.Add(new Claim(claim, value));
}
在B上,来自A的ExternalCallback在AccountController.ExternalCallback中处理:
public async Task<IActionResult> ExternalCallback(string returnUrl)
{
//Read external identity from the tempoary cookie
var result = await HttpContext.AuthenticateAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme);
if (result == null)
throw new Exception("External authentication error");
var externalUser = result.Principal;
if (externalUser == null)
throw new Exception("External authentication error");
//Get external claims
var claims = externalUser.Claims.ToList();
... additional identity handling and signin on B.
此时,索赔中没有任何图片声明。已经在A的ProfileService中设置的其他配置文件相关的声明都存在。如果我在ProfileService中对其他一些声明值进行硬编码,我会按预期看到ExternalCallback中反映的值。但图片声称不存在。此外,当执行GetProfileDataAsync时,context.RequestedClaimTypes确实包含“profile”。
我已经尝试为图片声明提供硬编码值(指向png文件的URL(这似乎是正确的方式)),但没有区别。 由于图片值是base64编码的图像文件,我也尝试增加Kestrel的MaxResponseBufferSize,但这也没有任何区别。
由于在ProfileService中设置了声明值,我猜它必须在调用
之前的某个地方var result = await HttpContext.AuthenticateAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme);
为什么图片声称不存在我无法弄清楚。欢迎任何建议。
修改 更多信息。在B上,其中定义了.AddOpenIdConnect(“oidc”...),我尝试将onUserInformationReceived事件添加到options.Events。当收到用户信息时,我可以在上下文中看到picture属性作为User对象的一部分。因此,这些信息是可用的,但不会作为声明添加......似乎。