【发布时间】:2019-07-21 11:40:02
【问题描述】:
我正在尝试构建一个混合流,并使用 IdentityServer4 对返回的访问令牌进行声明。我正在使用QuickStart UI 控件。
在用户成功通过身份验证后,在我的AccountController 中,我有以下代码可以让他登录:
await HttpContext.SignInAsync("anon@nymous.com", "anon@nymous.com", null, new Claim("MyName", "Ophir"));
在导致此流程的 MVC 网站中,在我要“保护”的页面上,我有以下代码:
[Authorize]
public IActionResult RestrictedMvcResource()
{
var token = _httpContext.HttpContext.GetTokenAsync("access_token").Result;
var identity = User.Identity;
return View();
}
成功登录后,调试器会很好地命中此代码,并且我正在获取访问令牌。
问题是,如果我解码我的访问令牌(我正在使用 https://jwt.io/),我会看到名称和主题,但我没有看到我定义的 MyName 声明。
(我的系统中有另一个 client_credentials 流,它确实返回了对令牌的声明 - 但它使用不同的代码流)。
如何返回混合流的令牌声明?
编辑:
解决这个问题需要两件事的结合:
- 按照(选定)答案中的建议实施
IProfileService。这是我的实现:
public class ProfileService : IProfileService
{
public Task GetProfileDataAsync(ProfileDataRequestContext context)
{
context.AddRequestedClaims(context.Subject.Claims);
foreach (Claim claim in context.Subject.Claims)
{
if (context.IssuedClaims.Contains(claim))
continue;
context.IssuedClaims.Add(claim);
}
return Task.FromResult(0);
}
public Task IsActiveAsync(IsActiveContext context)
{
context.IsActive = true;
return Task.FromResult(0);
}
}
这将添加任何尚未在令牌上的声明。
- 调用
HttpContext.SignInAsync时,您必须传递声明列表,否则context.Subject.Claims集合中将没有其他声明。
【问题讨论】:
-
如果为 client_credentials 添加了声明,那么这意味着您在 ClientClaims 表中配置了声明?
-
为什么声明应该是 access_token 的一部分?似乎更多的声明应该是 identity_token 的一部分,尽管您可能不会在那里找到它,因为默认情况下它只包含子声明,除非 AlwaysIncludeUserClaimsInIdToken 为真:
var token = await _httpContext.HttpContext.GetTokenAsync("identity_token");。否则从 UserInfo 端点获取声明(使用访问令牌)。 -
声明不是访问令牌的一部分。我提到过,在一种类型的流程中,声明成功地在令牌上进行,而在另一种类型的流程中则没有。
-
为什么要在代码中向 context.Subject.Claims 集合添加声明?更灵活的解决方案是将声明保留在 UserClaims 表中。
-
@RuardvanElburg 我的解决方案不使用文档中的 EF 持久性,我编写了一个自定义解决方案包装 IdentityServer..
标签: c# asp.net-identity identityserver4