IdentityServer4声明不属于混合流令牌的一部分 [英] IdentityServer4 claims are not part of the token on hybrid flow
问题描述
我正在尝试构建混合流,并使用IdentityServer4对返回的访问令牌进行声明.我正在使用 QuickStart UI 控件.
I'm trying to build a hybrid flow, and have claims on the returned access token with IdentityServer4. I'm using the QuickStart UI controlles.
在我的AccountController
中,该用户成功通过身份验证之后,我有以下代码可以使他登录:
In my AccountController
after the user was authenticated successfully, I have the following code which signs him in:
await HttpContext.SignInAsync("anon@nymous.com", "anon@nymous.com", null, new Claim("MyName", "Ophir"));
在导致此流程的MVC网站中,在我要保护"的页面上,我具有以下代码:
In the MVC website that is causing this flow, on the page I want to "protect" I have the following code:
[Authorize]
public IActionResult RestrictedMvcResource()
{
var token = _httpContext.HttpContext.GetTokenAsync("access_token").Result;
var identity = User.Identity;
return View();
}
成功登录后,调试器会将此代码正常运行,并且我获得了访问令牌.
After a successful login, the debugger hits this code fine and I'm getting the access token.
问题在于,如果我解码访问令牌(我正在使用 https://jwt.io/)我看到了名称和主题,但没有看到我定义的MyName
声明.
The problem is that if I decode my access token (I'm using https://jwt.io/) I see the name and subject, but I do not see the MyName
claim that I have defined.
(我的系统中还有另一个针对client_credentials
的流程,该流程确实返回了对令牌的声明-但它使用了不同的代码流程).
(I have another flow in my system for client_credentials
which does return the claims on the token - but it uses a different code flow).
如何为混合流程返回代币上的声明?
How do I return the claims on the token for the hybrid flow?
解决此问题是两件事的结合:
Solving this problem was a combination of 2 things:
- 按照(选定)答案的建议实施
IProfileService
.这是我的实现:
- Implementing
IProfileService
as suggested in (selected) answer. here's my implementation:
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);
}
}
这将添加令牌上尚未存在的所有声明.
This will add any claim that isn't already on the token.
- 调用
HttpContext.SignInAsync
时,您必须传递声明列表,否则context.Subject.Claims
集合中将没有其他声明.
- When calling
HttpContext.SignInAsync
you must pass the list of claims, otherwise no additional claims will be in thecontext.Subject.Claims
collection.
推荐答案
如果要向令牌添加自定义声明,则可以实现自定义IProfileService
.
You can implement custom IProfileService
if you want to add custom claims to the token.
您可以在 Identity Server 4文档中找到更多信息.
You can find more info in Identity Server 4 docs.
简单的自定义配置文件服务的示例为:
An example of simple custom profile service would be:
public class CustomProfileService : IProfileService
{
public Task GetProfileDataAsync(ProfileDataRequestContext context)
{
context.AddRequestedClaims(context.Subject.Claims);
context.IssuedClaims.Add(new Claim("MyName", "Ophir"));
return Task.FromResult(0);
}
public Task IsActiveAsync(IsActiveContext context)
{
context.IsActive = true;
return Task.FromResult(0);
}
}
有了这个,只需将其注册到DI:
Once you have this, just register it to the DI:
services.AddTransient<IProfileService, CustomProfileService>();
每当请求access_token
或id_token
时,它将被调用.如果您只想要某些类型的令牌中的额外声明,则需要按照Ruard的注释检查context.Caller
.
It will get called whenever an access_token
or id_token
is requested. You would need to check context.Caller
as per Ruard's comment if you only wanted the extra claims in certain type of token.
Also alternatively, you can add the claims directly to the user configuration as per example in one of the Identity Server 4 quickstarts:
new TestUser
{
SubjectId = "1",
Username = "alice",
Password = "password",
Claims = new []
{
new Claim("MyName", "Ophir")
}
},
如果最终没有实现自定义IProfileService
并继续使用DefaultProfileService
,那么您还需要在配置中添加自定义IdentityResource
:
If you end up not implementing custom IProfileService
and keep using DefaultProfileService
, then you would also need add a custom IdentityResource
in your configuration:
return new List<IdentityResource>
{
//..Your other configured identity resources
new IdentityResource(
name: "custom.name",
displayName: "Custom Name",
claimTypes: new[] { "MyName" });
};
任何希望在令牌中添加此声明的客户都需要请求custom.name
范围.
Any clients wanting to have this claim added in the token would need request for custom.name
scope.
这篇关于IdentityServer4声明不属于混合流令牌的一部分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!