C# 在没有自定义声明的情况下访问\u令牌,声明仍然从userinfo返回
Tl;dr:如何防止自定义声明出现在访问令牌中,并且仅在调用C# 在没有自定义声明的情况下访问\u令牌,声明仍然从userinfo返回,c#,asp.net-core,identityserver4,C#,Asp.net Core,Identityserver4,Tl;dr:如何防止自定义声明出现在访问令牌中,并且仅在调用userinfo端点时才返回 我有一个IdentityServer4(使用authorization\u codegrant type),在第三方身份验证成功后,我可以从中获得有关用户的一些附加信息。我将这些存储为声明,将用户登录到IS4服务,并将这些声明添加到用户。声明连接到一个名为“custom”的标识资源范围 现在,当我检索访问令牌时,它不包含这些自定义声明,但它包含“自定义”范围。下一步是调用userinfo端点来获取这些自定义
userinfo
端点时才返回
我有一个IdentityServer4(使用authorization\u code
grant type),在第三方身份验证成功后,我可以从中获得有关用户的一些附加信息。我将这些存储为声明,将用户登录到IS4服务,并将这些声明添加到用户。声明连接到一个名为“custom”的标识资源范围
现在,当我检索访问令牌时,它不包含这些自定义声明,但它包含“自定义”范围。下一步是调用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;
}
}
public类ProfileService:IProfileService
{
公共任务GetProfileDataAsync(ProfileDataRequestContext上下文)
{
列表声明=新列表();
foreach(上下文中的IdentityResource IdentityResource.RequestedResources.IdentityResources)
{
foreach(identityResource.UserClaims中的字符串userClaim)
{
var-claim=context.Subject.Claims.FirstOrDefault(c=>c.Type==userClaim);
如果(索赔!=null)
{
索赔。添加(索赔);
}
}
}
if(claims.Any())
{
context.IssuedClaims.AddRange(索赔);
}
返回Task.CompletedTask;
}
}
现在,当我调用userinfo
端点时,我的自定义声明是可见的
但是在检查访问令牌之后,我可以看到我的自定义声明也在那里可见。我觉得这有点多余,因为您(在本例中)实际上不必调用userinfo
如果没有自定义的IProfileService
实现(类仍然存在,但只有一个空方法),我会进行以下观察:
在调用context.Subject.Claims
端点时包含自定义声明,但在从token
调用时不包含自定义声明userinfo
- 数据库中的
表有一个PersistedGrants
列,该列还包含自定义标记Data
所以问题仍然是:如何防止自定义声明出现在访问令牌中,并且仅在调用
userinfo
端点时返回?我认为这可能是一个配置问题
必须使用2个允许的作用域定义客户端:
IdentityServerConstants.StandardScopes.OpenId
- “定制”
新客户端
{
AllowedScopes=新列表
{
IdentityServerConstants.StandardScopes.OpenId,
“定制”
},
//等等。。。
然后在客户端上配置ResponseType=OpenIdConnectResponseType.IdTokenToken;
:
.AddOpenIdConnect(o=>
{
o、 Scope.Clear();
o、 范围。添加(“openid”);
o、 范围。添加(“自定义”);
o、 ResponseType=OpenIdConnectResponseType.IdTokenToken;
//等等。。。
我认为这可能是一个配置问题
必须使用2个允许的作用域定义客户端:
IdentityServerConstants.StandardScopes.OpenId
- “定制”
新客户端
{
AllowedScopes=新列表
{
IdentityServerConstants.StandardScopes.OpenId,
“定制”
},
//等等。。。
然后在客户端上配置ResponseType=OpenIdConnectResponseType.IdTokenToken;
:
.AddOpenIdConnect(o=>
{
o、 Scope.Clear();
o、 范围。添加(“openid”);
o、 范围。添加(“自定义”);
o、 ResponseType=OpenIdConnectResponseType.IdTokenToken;
//等等。。。
您可以检查调用方是否为/userinfo
(我假设这就是包含该属性的初衷):
您可以检查调用方是否为
/userinfo
(我假设这就是包含该属性的最初意图):
我认为您应该检查ApiResource配置。无论您在ApiResource配置的UserClaims属性中添加了什么声明,这些声明都将出现在访问令牌中
public IEnumerable<ApiResource> GetApiResources()
{
return new List<ApiResource>
{
new ApiResource("api1")
{
UserClaims = new[] { "CustomClaim1", "CustomClaim2"},
},
}
}
public IEnumerable GetApiResources()
{
返回新列表
{
新ApiResource(“api1”)
{
UserClaims=new[]{“CustomClaim1”、“CustomClaim2”},
},
}
}
在上面的代码中,访问代码将包含CustomClaim1和CustomClaim2。
因此,如果您不提及它们,它们将不会出现在访问令牌中。我认为您应该检查ApiResource配置。无论您在ApiResource配置的UserClaims属性中添加了什么声明,这些声明都将出现在访问令牌中
public IEnumerable<ApiResource> GetApiResources()
{
return new List<ApiResource>
{
new ApiResource("api1")
{
UserClaims = new[] { "CustomClaim1", "CustomClaim2"},
},
}
}
public IEnumerable GetApiResources()
{
返回新列表
{
新ApiResource(“api1”)
{
UserClaims=new[]{“CustomClaim1”、“CustomClaim2”},
},
}
}
在上面的代码中,访问代码将包含CustomClaim1和CustomClaim2。
因此,如果您不提及它们,它们将不会出现在访问令牌中。我的客户机已经将
自定义
添加到允许的作用域中,并且我正在使用授权\u code
授权类型,因此我只能使用“code”作为响应类型。我的客户机已将自定义
添加到允许的作用域中,并且我正在使用授权_code
授予类型,因此我只能使用“code”作为响应类型。如果我没有执行GetProfileDataAsync
,则
public IEnumerable<ApiResource> GetApiResources()
{
return new List<ApiResource>
{
new ApiResource("api1")
{
UserClaims = new[] { "CustomClaim1", "CustomClaim2"},
},
}
}