Oauth 2.0 IdentityServerV4引用令牌自省

Oauth 2.0 IdentityServerV4引用令牌自省,oauth-2.0,jwt,identityserver4,openid-connect,Oauth 2.0,Jwt,Identityserver4,Openid Connect,我已使用授权代码+PKCE与客户端设置IdentityServerV4,并已将访问令牌类型设置为reference new Client { ClientId = "app", ClientName = "My Application", AllowedGrantTypes = GrantTypes.Code, RequireClientSecret = false, RedirectUris = { "http://site.example.com:30

我已使用授权代码+PKCE与客户端设置IdentityServerV4,并已将访问令牌类型设置为reference

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。在设置网关之前,我试图通过使用从登录中获得的引用令牌调用内省端点来手动执行交换

我向identity server添加了一个称为“gateway”的API,为其提供了一个机密,并使用具有API ID和机密的内省客户端成功地调用了此端点,但我得到的响应是active:false,identity server日志显示一个错误,即令牌缺少预期的作用域“gateway”。日志中显示的令牌信息仅显示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和发出的令牌之间缺少一些链接,但我尝试了我能想到的客户机和ApiResource定义之间的所有范围和允许范围的排列,但我似乎无法得到预期的结果。我已经反复阅读了文档好几次,在这种情况下,我不能完全理解API和客户机之间的关系。需要什么样的配置来支持这种类型的设置?

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

这里有两个选项:

  • gateway
    作用域提供给您的客户端,并使其在授权请求中将网关作用域与其他作用域一起发送
  • 编写自定义
    IClaimService
    并将网关作用域添加到所有访问令牌

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

    AllowedScopes = { "openid", "profile", "email" },
    
    因此,如果apigateway使用此令牌调用内省端点,则响应将始终
    active=false

    我想你的api需要用户信息。如果没有,您可以使用apigateway中的客户端凭据授权来调用您的api

    如果没有,则有两种解决方案:

  • 在apigateway和api中使用相同的作用域,并将令牌直接传递给api,在api中调用内省端点。请注意,您的api网关和api正在共享访问群体和作用域,因此这不是最佳选择

  • 海关授权。apigateway和api有自己的受众和范围。apigateways充当委托客户端,它调用idp的令牌端点,将用户声明转发给为api发布的新令牌。IdentityServer4文档展示了一种实现身份验证的方法。您必须记住,您的apigateway是一个apiresource,同时也是一个委托客户机


  • 你有一篇关于斯科特·布雷迪的精彩文章

    谢谢。第一个建议是我尝试过的,但对我不起作用,而且在再次测试时仍然不起作用,我得到了与以前相同的信息。实现IClaimService看起来确实可行,但我不确定这里到底发生了什么,也找不到有关此IClaimService的文档。我不确定这是否相关,但当尝试采取下一步并将这些参考令牌与Kong+Nokia OIDC一起使用时,X-Access-Token标头在到达上游服务时丢失。@Paul第一个解决方案也会起作用。您确定您的客户端正在其授权请求中发送网关作用域吗?不幸的是,现在还没有关于
    iclaimservice
    的文档,但是如果你跟踪源代码,你会发现它就是做这件事的地方。此外,Kong+诺基亚OIDC的情况似乎与此问题无关
    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);
        }
    }
    
    public void ConfigureServices(IServiceCollection services)
    {
        ...
        services.AddTransient<IClaimsService, CustomClaimService>();
        services.AddIdentityServer();
        ...
    }
    
    AllowedScopes = { "openid", "profile", "email" },