【问题标题】:IdentityServerV4 Reference Token IntrospectionIdentityServerV4 参考令牌自省
【发布时间】:2020-02-05 22:31:48
【问题描述】:

我已经使用授权码 + PKCE 与客户端一起设置了 IdentityServerV4,并将访问令牌类型设置为引用。

new Client
{
    ClientId = "app",
    ClientName = "My Application",
    AllowedGrantTypes = GrantTypes.Code,
    RequireClientSecret = false,
    RedirectUris = { "http://site.example.com:3000/callback" },
    AllowedCorsOrigins = { "http://site.example.com:3000" },
    AllowedScopes = { "openid", "profile", "email" },
    AccessTokenType = AccessTokenType.Reference,
    RequireConsent = false,
    RequirePkce = true
}

我现在想在客户端应用程序和服务之间设置一个反向代理网关,该网关将在转发请求之前将参考令牌交换为常规签名的 JWT。在设置网关之前,我尝试通过使用从登录获得的参考令牌调用自省端点来手动执行交换。

我向身份服务器as described here 添加了一个我称为“网关”的 API,给了它一个秘密,并使用带有 API 的 ID 和秘密的 IntrospectionClient 成功调用了这个端点,但我得到了一个活动的响应: false,并且身份服务器日志显示令牌缺少预期范围“网关”的错误。日志中显示的token信息只显示openid范围。

new ApiResource("gateway"){
    ApiSecrets = { new Secret("test".Sha256()) }
}

这会导致来自 IdentityServer 的两条日志消息:

fail: IdentityServer4.ResponseHandling.IntrospectionResponseGenerator[0]
      Expected scope gateway is missing in token
info: IdentityServer4.Endpoints.IntrospectionEndpoint[0]
      Success token introspection. Token active: True, for API name: gateway

所以我从中得出的结论是,API 和发出的令牌之间缺少一些链接,但我已经尝试了我能想到的 Client 和 ApiResource 定义之间的所有范围排列和允许范围,但我似乎无法得到预期的结果。我已经多次阅读和重读文档,但在这种情况下我无法完全弄清楚 API 和客户端之间的关系。需要什么样的配置来支持这种类型的设置?

【问题讨论】:

    标签: oauth-2.0 jwt identityserver4 openid-connect


    【解决方案1】:

    看起来您的代理正在使用gateway 范围作为自省端点,问题是您的令牌没有此gateway 范围,因此您总是会得到active: false 的响应。

    你有两个选择:

    1. gateway 范围提供给您的客户端并使其在授权请求中沿其他范围发送网关范围
    new Client
    {
        ClientId = "app",
        ClientName = "My Application",
        AllowedGrantTypes = GrantTypes.Code,
        RequireClientSecret = false,
        RedirectUris = { "http://site.example.com:3000/callback" },
        AllowedCorsOrigins = { "http://site.example.com:3000" },
        AllowedScopes = { "openid", "profile", "email", "gateway" }, // add gateway here
        AccessTokenType = AccessTokenType.Reference,
        RequireConsent = false,
        RequirePkce = true
    }
    
    1. 编写自定义IClaimService 并将网关范围添加到所有访问令牌。
    public class CustomClaimService : IdentityServer4.Services.DefaultClaimsService
    {
        public CustomClaimService(IProfileService profile, ILogger<DefaultClaimsService> logger)
            : base(profile, logger)
        {
    
        }
    
        public override Task<IEnumerable<Claim>> GetAccessTokenClaimsAsync(ClaimsPrincipal subject, Resources resources, ValidatedRequest request)
        {
            resources.ApiResources.Add(new ApiResource("gateway"));
            return base.GetAccessTokenClaimsAsync(subject, resources, request);
        }
    }
    

    您还需要在AddIdentityServer之前注册CustomClaimServiceIServiceCollection

    public void ConfigureServices(IServiceCollection services)
    {
        ...
        services.AddTransient<IClaimsService, CustomClaimService>();
        services.AddIdentityServer();
        ...
    }
    

    【讨论】:

    • 谢谢。第一个建议是我尝试过的,但对我不起作用,并且似乎仍然无法再次进行测试,我收到与以前相同的消息。实施 IClaimService 似乎确实有效,但我不确定这里到底发生了什么,也找不到有关此 IClaimsService 的文档。我不确定这是否相关,但是当尝试采取下一步并将这些参考令牌与 Kong + Nokia OIDC 一起使用时,X-Access-Token 标头在到达上游服务时丢失。
    • @Paul 第一个解决方案也可以。您确定您的客户端在其授权请求中发送网关范围吗?不幸的是,目前还没有关于 IClaimsServiceright 的文档,但是如果您跟踪源代码,您会发现它就是这样做的地方。此外,Kong + Nokia OIDC 发生的情况似乎与此问题无关
    【解决方案2】:

    尚未为gateway 范围颁发您的令牌。不允许您的客户请求该范围:

    AllowedScopes = { "openid", "profile", "email" },
    

    因此,如果 apigateway 使用此令牌调用自省端点,则响应将始终为 active=false

    我猜你的 api 需要用户信息。如果没有,您可以在 apigateway 中使用 Client Credentials Grant 来调用您的 api。

    如果没有,您有 2 个解决方案:

    1. 在您的 apigateway 和 api 中使用相同的范围,并将令牌直接传递给您的 api,您将在其中调用自省端点。请注意,您的 apigateway 和您的 api 共享受众和范围,因此这不是最佳选择。

    2. 自定义委派授予。 apigateway 和 api 有自己的受众和范围。 apigateways 充当委托客户端,它调用您的 idp 的令牌端点,以将您的用户声明转发到为您的 api 发布的新令牌。 IdentityServer4 文档展示了一种实现Delegation Grant using ExtensionGrants 的方法。您必须记住,您的 apigateway 是一个 apiresource,同时也是一个委托客户端。

    你有一篇很棒的关于 Delegation Patterns for OAuth 2.0. 的 Scott Brady 帖子

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-20
      • 2018-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-06
      • 2017-01-01
      • 1970-01-01
      相关资源
      最近更新 更多