我使用asp.net core和ASP实现了一个IdentityServer4解决方案。净的身份。到目前为止一切顺利。我已经配置了解决方案,这样用户声明就不会与访问令牌一起传输,客户机必须调用UserInfo端点来获取用户声明。我遇到的问题是网站(客户端)调用公共api,然后调用我需要访问用户声明的私有api。从私有api,我调用用户信息端点请求用户声明并接收所有内容。我期望只接收由APiResource(仅openid)定义的声明,但我收到了客户端请求的所有用户声明(openid、配置文件、电子邮件、地址等)。我假定配置文件服务能够理解apiresource请求的是用户信息——而不是客户端,从而减少返回的请求,但事实并非如此。我的问题是。我如何使我的ProfileService意识到调用的发起者,这样,如果私有api调用UserINfo itv只返回ApiResource中定义的那些声明?
我正在使用引用令牌,所以我的客户端看起来如下(不包括所有属性)
new Client
{
ClientId = "client",
AccessTokenType = AccessTokenType.Reference,
ClientSecrets = { new Secret("secret".Sha256()) },
AllowedScopes = { "openid", "profile", "email" }
}
我定义了两个api资源,如下所示:
new ApiResource("public_api"){
Scopes = new List<string> { "openid" }
}
new ApiResource("private_api"){
Scopes = new List<string> { "openid" },
}
我的客户端(网站)请求以下范围:
openid, profile, email
使用上述配置,当检查User时。在每个级别上,我看到以下值:
- 网站可以看到用户声明:name, family_name, given_name和email
- PUBLIC API没有用户声明信息
- PRIVATE API没有用户声明信息
根据Tore Nestenius的建议,我修改了私有api资源如下:
new ApiResource("private_api"){
Scopes = new List<string> { "openid" },
UserClaims = { "email", "email_verified" }
}
重新运行应用程序,我现在看到以下值:
- 网站可以看到用户声明:name, family_name, given_name和email(没有变化的想法不确定为什么email_verified不显示?) PUBLIC API可以看到用户声明:email和email_verified
- PRIVATE API可以看到用户声明:email和email_verified
我不明白的是为什么公共api会看到电子邮件用户声明?我原以为只有私有api才能看到这些声明,但事实并非如此。理想情况下,我希望限制每个微服务只能看到针对Api资源定义的用户声明。我希望这有助于弄清楚发生了什么。
UserInfoEndpoint总是返回用户声明。
要获取ApiResources用户声明,您需要请求TokenIntrospection端点。这个端点的目的是让定义为ApiResources的API查询IdentityServer以获取用户声明。也用于检查访问令牌是否仍然有效。
您还必须映射哪些用户声明应该出现在令牌自省结果中,使用如下代码:
new ApiResource()
{
Name = "paymentapi",
Scopes = new List<string> { "payment"},
ApiSecrets = new List<Secret>() { new Secret("myapisecret".Sha256()) },
UserClaims = new List<string>
{
"creditlimit", "paymentaccess","admin"
}
}
同样,如果设置了此标志,则所有用户声明也包含在访问令牌中:
/// <summary>
/// Gets or sets a value indicating whether client claims should be always included in the access tokens - or only for client credentials flow.
/// Defaults to <c>false</c>
/// </summary>
/// <value>
/// <c>true</c> if claims should always be sent; otherwise, <c>false</c>.
/// </value>
public bool AlwaysSendClientClaims { get; set; } = false;