IdentityServerV4参考令牌自省

时间:2019-10-08 15:39:14

标签: oauth-2.0 jwt identityserver4 openid-connect

我已经使用授权代码+ 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,并且身份服务器日志显示错误,指示令牌缺少预期的作用域“网关”。日志中显示的令牌信息仅显示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和客户端之间的关系。要支持这种类型的设置,需要哪种配置?

2 个答案:

答案 0 :(得分:2)

您的代理似乎正在将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);
    }
}

您还需要在CustomClaimService之前向IServiceCollection注册AddIdentityServer

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

答案 1 :(得分:0)

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

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

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

我猜您的api需要用户信息。如果没有,则可以在apigateway中使用“客户端凭据授予”来调用您的api。

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

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

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

您在斯科特·布雷迪(Scott Brady)上有一篇很棒的帖子,内容关于Delegation Patterns for OAuth 2.0.