【问题标题】:IdentityServer4 Restrict Claims by ApiResource in ProfileServiceIdentityServer4 通过 ProfileService 中的 ApiResource 限制声明
【发布时间】:2021-02-06 01:51:04
【问题描述】:

我已经使用带有 ASP.Net Identity 的 asp.net 核心实现了 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.Claims 时,我看到以下值:

  • WEBSITE 可以查看用户声明:姓名、family_name、given_name 和电子邮件
  • PUBLIC API 没有用户声明信息
  • PRIVATE API 没有用户声明信息

根据 Tore Nestenius 的建议,我将私有 api 资源更改如下:

new ApiResource("private_api"){
    Scopes = new List<string> { "openid" },
    UserClaims = { "email", "email_verified" }
}

重新运行应用程序,我现在看到以下值:

  • WEBSITE 可以看到用户声明:name、family_name、given_name 和 email(没有变化,不知道为什么 email_verified 没有显示?)
  • PUBLIC API 可以查看用户声明:email 和 email_verified
  • PRIVATE API 可以查看用户声明:email 和 email_verified

我不明白为什么公共 api 会看到电子邮件用户声明?我原以为只有私有 api 会看到这些声明,但事实并非如此。理想情况下,我希望将每个微服务限制为仅查看针对 Api 资源定义的用户声明。 我希望这有助于澄清发生了什么。

【问题讨论】:

    标签: asp.net-core microservices identityserver4


    【解决方案1】:

    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;
    

    【讨论】:

    • 您好,Tore Nestenius。我已经实现了自省令牌端点,但它似乎只返回范围 - 而不是用户声明,例如 Type = "Email", Value = "exampl@email.com"。
    • 查看我的更新答案,这是否使它成为可接受的答案?
    • 嗨,Tore,这很好,但仍然不是我所期望的。正如您在上面所做的那样,我将用户声明“creditlimit”添加到“public_paymentapi”ApiResource 并填充了声明。我没有将该用户声明添加到“private_paymentapi”ApiResource 并且当我期望它不会填充到私有 api 中时仍然获得了声明值。我认为自省端点会识别出私有 api 无权访问用户声明并且不会填充它?
    • 你对不同的 ApiResources 有不同的名称/秘密吗?你能澄清你的意思吗? APi 通常不需要访问 userinfo 端点。
    • 您好,Tore,我已经用更多信息更新了原始问题。希望能帮助到你!感谢您的帮助 - 非常感谢。
    猜你喜欢
    • 2018-02-02
    • 1970-01-01
    • 2019-01-07
    • 2015-07-07
    • 2018-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多