动态配置身份验证

发布于 2025-01-11 15:55:38 字数 2279 浏览 0 评论 0原文

[上下文]

我正在测试身份提供者。我遇到了一个有趣的场景,其中......内省端点仍然缺失,这意味着我将自己验证令牌,如下所示:

        HttpClient client = new HttpClient();
        client.DefaultRequestHeaders.Clear();
        client.DefaultRequestHeaders.Add(HeaderNames.Accept, "application/json");

        var response = await client.GetAsync("url_to_jwks");
        var content = await response.Content.ReadAsStringAsync();            
        var jwk = new JsonWebKeySet(content).GetSigningKeys().First();

        services.AddAuthentication()
            .AddJwtBearer("SelfValidationKey", opt =>
            {
                opt.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = false,
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = jwk
                };
                opt.RequireHttpsMetadata = false;
            });
        services.AddOcelot();

当然还有其他参数需要检查,但为了简单起见,我们将只需关注签名,因为这也是我的问题:)

[想法]

与其使用证书进行验证,为什么不使用 IdP 众所周知的文档提供的 jwk(jwk 并不总是相同的)。这就是我所做的,而且有效,但是!当我尝试在配置服务中进行 http 调用时,在添加身份验证之前,它会崩溃:

System.NullReferenceException:未将对象引用设置为对象的实例。 在 Ocelot.Middleware.OcelotMiddlewareExtensions.CreateConfiguration(IApplicationBuilder 构建器) 在 Ocelot.Middleware.OcelotMiddlewareExtensions.UseOcelot(IApplicationBuilder 构建器,OcelotPipelineConfiguration pipelineConfiguration) 在 Ocelot.Middleware.OcelotMiddlewareExtensions.UseOcelot(IApplicationBuilder 构建器) 在 ApiGateway.Startup.Configure

我以为我无法在我的服务配置中进行 http 调用,但实际上我检查了并且确实收到了我期望的响应。我已经在不同的startup.cs上尝试过了,它工作得很好,所以我猜......它与Ocelot(api网关)有关,我是否以错误的方式制作了async/await语句?异常是在 Programs .cs 中引发的,这是非常基本的,我从未达到 Services.AddAuthentication()

public static void Main(string[] args)
        {
            BuildWebHost(args).Run();
        }

public static IWebHost BuildWebHost(string[] args)
        {
            var builder = WebHost.CreateDefaultBuilder(args);

            builder.ConfigureServices(s => s.AddSingleton(builder))
                .ConfigureAppConfiguration(
                    ic => ic.AddJsonFile("ocelot.json"))
                .UseStartup<Startup>();
            var host = builder.Build();
            return host;
        }

[Context]

I'm testing an identity provider. And I came across an intriguing scenario where ... the introspect endpoint was still missing which means, i'm going to validate the token by myself like so:

        HttpClient client = new HttpClient();
        client.DefaultRequestHeaders.Clear();
        client.DefaultRequestHeaders.Add(HeaderNames.Accept, "application/json");

        var response = await client.GetAsync("url_to_jwks");
        var content = await response.Content.ReadAsStringAsync();            
        var jwk = new JsonWebKeySet(content).GetSigningKeys().First();

        services.AddAuthentication()
            .AddJwtBearer("SelfValidationKey", opt =>
            {
                opt.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = false,
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = jwk
                };
                opt.RequireHttpsMetadata = false;
            });
        services.AddOcelot();

There are others parameters to check of course, but just for simplicity, we'll just focus on the signature, and because that's also my problem :)

[The idea]

Instead of verifying it with a certificate, why not use the jwk provided by the IdP well-known document (the jwk is not always the same). And that's what I did, and it works, but! When I try to make an http call inside my configure services, before adding authentification, it crashes:

System.NullReferenceException: Object reference not set to an instance of an object.
at Ocelot.Middleware.OcelotMiddlewareExtensions.CreateConfiguration(IApplicationBuilder builder)
at Ocelot.Middleware.OcelotMiddlewareExtensions.UseOcelot(IApplicationBuilder builder, OcelotPipelineConfiguration pipelineConfiguration)
at Ocelot.Middleware.OcelotMiddlewareExtensions.UseOcelot(IApplicationBuilder builder)
at ApiGateway.Startup.Configure

I thought I couldn't make http calls inside my service configuration, but acutally I checked and I do receive the response I was expecting. I've tried it on a different startup.cs and it works just fine, so my guess ... it has to do with Ocelot (api gateway) somehow, am I making the async/await statement in the wrong way? The exception is thrown at Programs .cs which is very basic, and I never reach Services.AddAuthentication():

public static void Main(string[] args)
        {
            BuildWebHost(args).Run();
        }

public static IWebHost BuildWebHost(string[] args)
        {
            var builder = WebHost.CreateDefaultBuilder(args);

            builder.ConfigureServices(s => s.AddSingleton(builder))
                .ConfigureAppConfiguration(
                    ic => ic.AddJsonFile("ocelot.json"))
                .UseStartup<Startup>();
            var host = builder.Build();
            return host;
        }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

源来凯始玺欢你 2025-01-18 15:55:38

一种方法是...

通过我的program.cs中的静态类IdpDocument进行调用,通过UseSetting方法将我需要的值传递给配置,然后将其注入到startup.cs中,它看起来像这样:

    public static async Task Main(string[] args)
    {
        jwks = await IdpDocument.FetchJwks();
        BuildWebHost(args).Run();
    }

    public static IWebHost BuildWebHost(string[] args)
    {
        var builder = WebHost.CreateDefaultBuilder(args);

        builder.ConfigureServices(s => s.AddSingleton(builder))
            .ConfigureAppConfiguration(
                ic => ic.AddJsonFile("ocelot.json"))
            .UseSetting("jwks", jwks)
            .UseStartup<Startup>();
        var host = builder.Build();
        return host;
    }

在我的startup.cs中,我得到的值:

public void ConfigureServices(IServiceCollection services)
{
     var jwks = Configuration.GetValue<string>("jwks");
     // and the rest of the code ...
}

但是......我唯一关心的是......我只发出一次请求。那么,如果 jwks 更新了怎么办? (这不是该程序的责任)

获得正确密钥的唯一方法是重新运行该程序,该程序并不是真正干净。

One way was to ...

Make a call through my static class IdpDocument in my program.cs, pass the value I need to the configuration via UseSetting method, which is then injected into the startup.cs, and it looks like this:

    public static async Task Main(string[] args)
    {
        jwks = await IdpDocument.FetchJwks();
        BuildWebHost(args).Run();
    }

    public static IWebHost BuildWebHost(string[] args)
    {
        var builder = WebHost.CreateDefaultBuilder(args);

        builder.ConfigureServices(s => s.AddSingleton(builder))
            .ConfigureAppConfiguration(
                ic => ic.AddJsonFile("ocelot.json"))
            .UseSetting("jwks", jwks)
            .UseStartup<Startup>();
        var host = builder.Build();
        return host;
    }

And in my startup.cs, i get the value:

public void ConfigureServices(IServiceCollection services)
{
     var jwks = Configuration.GetValue<string>("jwks");
     // and the rest of the code ...
}

But ... my only concern with that is .. I only make the request once. So, what if the jwks get updated? (which is not this program responsibility)

The only way to get the right keys, is to re-run this program which .. is not really clean.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文