【发布时间】:2018-08-27 15:39:03
【问题描述】:
我将 IdentityServer4 与 JWT 和 ASP.NET Core 2 一起用于身份验证。由于大查询的性能问题,我还使用IdentityUser<long>(long 主键而不是string)作为用户模型。这意味着我在编码的访问令牌内获得了一个有序的用户 ID,默认情况下该用户 ID 将提供给公共。使用 GUID 作为默认类型是有原因的,因此我只想向公众提供 GUID,而不是有序整数。为此,我有一个额外的 GUID 类型的 ExternalID 列,将在创建用户时生成一次。
现在我需要替换 sub 声明,其中默认情况下整数 Id 与我的 ExternalId (GUID) 一起使用。
我尝试使用ProfileService 和以下GetProfileDataAsync 方法
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var sub = context.Subject.GetSubjectId();
var user = await _userManager.FindByIdAsync(sub);
var principal = await _claimsFactory.CreateAsync(user);
var claims = principal.Claims.Where(
claim =>
claim.Type != "sub" &&
context.RequestedClaimTypes.Contains(claim.Type))
.ToList();
claims.Add(new Claim("sub", user.ExternalId.ToString()));
context.IssuedClaims = claims;
}
Startup.cs
services.AddIdentityServer()
// ...
.AddProfileService<ProfileService>();
但这没有任何效果。 IssuedClaims 似乎被忽略了。令牌仍然包含 Id sub 声明而不是 ExternalId。
我错过了什么?这是正确的方法吗?
【问题讨论】:
-
只是为了确定 - 您是否确认您的
GetProfileDataAsync()方法正在被调用? -
是的,肯定是在用户第一次登录的时候调用的。
-
刷新令牌交换没有调用。
-
我能够通过扩展 Microsoft.AspNetCore.Identity 包中的 UserClaimsPrincipleFactory 来完成这项工作。至少在大多数情况下。当通过首先点击 ResourceOwnerPassword 端点,然后是 UserInfo 端点来获取 id_token 时,我会收到一个禁止的错误。 access_token 的 sub 声明仍显示 int 值,而 id_token 显示 GUID。冲突导致错误。当使用混合流通过 oidc 获取访问令牌时,子声明将正确返回。如果你能解决这个问题,我很想听听!
标签: c# asp.net-core jwt identityserver4