Включение аутентификации сертификата в. net core api заставляет TestServer всегда возвращать 403-Forbidden в интеграционных тестах (несмотря на сертификат, использованный в запросе).
Я пытался изменить CertificateValidationService в TestClientProvider, но, похоже, сбой проверки сертификата до достижения пользовательского логина аутентификации c. Служба работает правильно с сертификатом клиента при развертывании в Azure.
Я что-то упустил? Есть ли способ использовать TestServer с API, защищенным сертификатом клиента?
Для воспроизведения
- Включить аутентификацию сертификата в. NET Core API https://docs.microsoft.com/en-us/aspnet/core/security/authentication/certauth?view=aspnetcore-3.1
// Startup.cs
...
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<CertificateValidationService>();
services.AddAuthentication(
CertificateAuthenticationDefaults.AuthenticationScheme).AddCertificate(options =>
{
...
});
services.AddAuthorization();
services.AddControllers();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILogger<Startup> logger)
{
...
app.UseRouting();
app.UseCertificateForwarding();
app.UseAuthentication();
app.UseAuthorization();
...
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
Используйте атрибут "authorize" на вашем API
// WeatherForecastController.cs (VS 2019 template)
[ApiController]
[Route("api/weather")]
[Authorize]
public class WeatherForecastController : ControllerBase
{
...
}
Написать интеграционный тест с использованием Microsoft.AspNetCore.TestHost
// IntegrationTests/ClientCertificateTests.cs
[Fact]
public async void GivenValidCertificate_PerformGet_ExpectSuccess()
{
X509Certificate2 validClientCertificate;
using (var certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser))
{
certStore.Open(OpenFlags.ReadOnly);
validClientCertificate = certStore.Certificates.Find(X509FindType.FindByTimeValid, DateTime.Now, true)[0];
}
using (var server = new TestClientProvider(ignoreCertificate: false).Server)
{
// Act
var result = await server.SendAsync(context =>
{
context.Connection.ClientCertificate = validClientCertificate;
context.Request.Method = "GET";
context.Request.Path = "/api/weather";
});
// Assert
Assert.Equal(200, result.Response.StatusCode);
}
}