Tl; dr::如何防止自定义声明出现在访问令牌中,并且仅在调用userinfo
端点时返回?
我有一个IdentityServer4(使用authorization_code
授予类型),在其中,在成功进行第三方身份验证时,我获得了有关用户的一些其他信息。我将这些声明存储为声明,将用户登录到IS4服务中并将这些声明添加到用户。声明已连接到名为“ custom”的身份资源范围
var myUser = some3rdParty.GetUserData();
Claim[] claims = {
new Claim("custom.value1", myUser.Custom1),
new Claim("custom.value2", myUser.Custom2)
};
await _events.RaiseAsync(new UserLoginSuccessEvent("myOidcProviderIS4", myUser.Id, myUser.Id, myUser.Fullname));
await _httpContextAccessor.HttpContext.SignInAsync(
myUser.Id,
myUser.Fullname,
new AuthenticationProperties(),
claims);
现在,当我检索访问令牌时,它不包含这些自定义声明,但是包含“自定义”范围。下一步将是调用userinfo
端点以获取这些自定义声明。但是,默认情况下,对userinfo
端点的调用不不包括这些自定义声明。
因此,我创建了一个IProfileService
,将声明复制到IssuedClaims
中:
public class ProfileService : IProfileService
{
public Task GetProfileDataAsync(ProfileDataRequestContext context)
{
List<Claim> claims = new List<Claim>();
foreach (IdentityResource identityResource in context.RequestedResources.IdentityResources)
{
foreach (string userClaim in identityResource.UserClaims)
{
var claim = context.Subject.Claims.FirstOrDefault(c => c.Type == userClaim);
if (claim != null)
{
claims.Add(claim);
}
}
}
if (claims.Any())
{
context.IssuedClaims.AddRange(claims);
}
return Task.CompletedTask;
}
}
现在,当我调用userinfo
端点时,可见自定义声明。
但是在检查了访问令牌之后,我可以看到我的自定义声明也在那里可见。我觉得这有点多余,因为您(在这种情况下)实际上不必致电userinfo
。
如果没有自定义IProfileService
实现(类仍在那儿,但只使用一个空方法),我做了以下观察:
context.Subject.Claims
在调用token
端点时包含自定义声明,但从userinfo
调用时不包含自定义声明。PersistedGrants
表具有一个Data
列,该列还包含自定义标记。所以问题仍然是:如何防止我的自定义声明出现在访问令牌中,而仅当您调用userinfo
端点时才返回?
答案 0 :(得分:0)
我认为这可能是配置问题。
必须使用2个允许的范围定义客户端:
IdentityServerConstants.StandardScopes.OpenId
new Client
{
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
"custom"
},
// etc...
然后在客户端上配置ResponseType = OpenIdConnectResponseType.IdTokenToken;
:
.AddOpenIdConnect(o =>
{
o.Scope.Clear();
o.Scope.Add("openid");
o.Scope.Add("custom");
o.ResponseType = OpenIdConnectResponseType.IdTokenToken;
// etc...
答案 1 :(得分:0)
您可以检查呼叫者是否是/userinfo
的调用者(我想这就是包含该属性的最初意图):
if (context.Caller == IdentityServerConstants.ProfileDataCallers.UserInfoEndpoint)
{
//custom logic to add requested claims
context.AddRequestedClaims(claims);
}
答案 2 :(得分:0)
我认为您应该检查ApiResource配置。无论您在 ApiResource 配置的 UserClaims 属性中添加什么声明,这些声明都会显示在访问令牌中。例如
public IEnumerable<ApiResource> GetApiResources()
{
return new List<ApiResource>
{
new ApiResource("api1")
{
UserClaims = new[] { "CustomClaim1", "CustomClaim2"},
},
}
}
在上面的代码中,访问代码将包含 CustomClaim1 和 CustomClaim2 。 因此,如果您不提及它们,它们将不会出现在访问令牌中。