asp.net-core - XUnit 与 Identityserver 集成测试 : Token received from Identityserver is unable to match key

标签 asp.net-core jwt identityserver4 xunit testserver

我目前正在尝试在具有 2 台服务器的环境中实现集成测试:

  • .NET Core API 服务器
  • IdentityServer4 身份验证服务器

经过一番努力,我设法让两者相互通信,但是,IdentityServer 在尝试确认 JWT token (通过 API)时抛出以下错误:

Bearer was not authenticated. Failure message: IDX10501: Signature validation failed. Unable to match key: kid: '8C1D5950D083E20D4B20DE9B37AC71FAEF679469'.

我会尽量保持代码示例简短:

在 XUnit 启动中,我为两个 TestServer 配置并创建客户端。

    public APITestBase(ITestOutputHelper output)
    {
        _output = output;

        var apicon = new ConfigurationBuilder()
            .AddJsonFile("apisettings.json", optional: true, reloadOnChange: true)
            .Build();

        var authcon = new ConfigurationBuilder()
            .AddJsonFile("authsettings.json", optional: true, reloadOnChange: true)
            .Build();

        _authServer = new TestServer(new WebHostBuilder()
            .UseConfiguration(authcon)
            .ConfigureLogging(x => x.AddXUnit(_output))
            .UseEnvironment("Development")
            .UseStartup<Auth.Startup>());

        _authClient = _authServer.CreateClient();

        _server = new TestServer(new WebHostBuilder()
            .UseConfiguration(apicon)
            .ConfigureLogging(x => x.AddXUnit(_output))
            .UseEnvironment("Test")
            .ConfigureServices(
                  services => {
//Here, I'm adding an httpclienthandler. In the application I will use this as JWTBackChannelHandler. This allows communication between the two servers
                      services.AddSingleton<HttpMessageHandler>(_authServer.CreateHandler());
                  })
            .UseStartup<Api.Startup>());

        _client = _server.CreateClient();

        APIConfig = new Cnfg();
         
        apicon.Bind("APIConfig", APIConfig);

        //Make users in api

    }

这是我尝试运行的实际测试

        [Fact]
        public async Task ApplyTest()
        {
            _client.SetBearerToken(await GetAccessToken());

            // Act
            var response = await _client.GetAsync($"{APIConfig.ApiBaseUrl}api/call/");
             response.EnsureSuccessStatusCode();
        }

这里是 GetAccessToken,它返回集成用来将自身标识为用户的 JWT token ...至少这是计划。

        protected async Task<string> GetAccessToken()
    {
        var disco = await _authClient.GetDiscoveryDocumentAsync(new DiscoveryDocumentRequest()
        {
            Address = _authServer.BaseAddress.ToString(),
            Policy =
                {
                    ValidateIssuerName = false
                }
        });

        if (!String.IsNullOrEmpty(disco.Error))
        {
            throw new Exception(disco.Error);
        }
        var response = await _authClient.RequestPasswordTokenAsync(new PasswordTokenRequest
        {
            Address = disco.TokenEndpoint,
            GrantType = "password",
            ClientId = "api",

            UserName = "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b0c4d5c3c4f0c4d5c3c49ededc" rel="noreferrer noopener nofollow">[email protected]</a>",
            Password = "test"
        });

        return response.AccessToken;
    }

我可以发现通过此函数生成的 JWT token 与正常网站请求的 JWT token 之间唯一可识别的区别是缺少公钥(根据 jwt.io)。

最后,因为我认为这一点可能有用,所以这是 API 的 Startup.cs 的一部分,我在其中强制使用 JWTBackChannelHandler

if (Environment.EnvironmentName == "Test")
            {
                services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
                    .AddIdentityServerAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme, o =>
                    {
                        o.JwtBackChannelHandler = _identityServerMessageHandler;
                        o.RequireHttpsMetadata = false;
                    })
                    .AddApiKeyAuthenication(o =>
                    {
                        o.Keys.Add("****".ToSha256());
                        o.Keys.Add("****".ToSha256());
                    });
            }

提前非常感谢您的帮助,我对此已经束手无策了。如果您需要更多信息,请告诉我,我很乐意提供。

最佳答案

经过另外 2 个小时的挖掘,我发现我需要添加

o.Authority = identityServerOptions.Address.AbsoluteUri;

到 AddIdentityServerAuthentication。

感谢那些花时间为我深入研究问题的人。

关于asp.net-core - XUnit 与 Identityserver 集成测试 : Token received from Identityserver is unable to match key,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64555221/

相关文章:

asp.net-core - 在 ASP.NET Core 中将 html 导出为 pdf

Spring 安全 : How to use a UserDetailsService with JwtAuthenticationProvider?

jwt - 使用 Passport-jwt 和尾声,我的 req.user 为空

java - Spring Boot Web 应用程序中的 JWT 过滤器和 Spring Security 控制流

angular - Angular SPA 中的 OpenID Connect 与 Asp.Net Core 3.1 后端

asp.net-core - 使用 .AddIdentityServerJwt() 时,.NET Core Razor Pages 应用程序的身份验证不适用于没有 "/Identity"路由的 View

asp.net-core - Asp.Net Core cookie 身份验证选项登录路径通过 HTTP 路由

javascript - 应用服务未获取JS发送的参数值

c# - 从 ASP.NET Core Web API 中的 Controller 访问用户身份

c# - ASP.NET 样板 + IdentityServer