我目前正在尝试在具有 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/