web-dev-qa-db-ja.com

テスト中にJWT認証をスキップするASP.Net Core 3.1 Web API

私は1つのJWT認証コントローラーを備えた非常にシンプルなアプリを持っています。

[ApiController]
[Authorize]
[Route("[controller]")]
public class JwtController : ControllerBase
{

    public JwtController() { }

    [HttpGet]
    public ActionResult Get() => Ok("Working!");
}

認証が次のように構成されている場合:

services.AddAuthentication(x =>
{
    x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(x =>
{
    x.RequireHttpsMetadata = false;
    x.SaveToken = true;
    x.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = false,
        ValidateAudience = false
    };
});

テスト中は、[Authorize]がスキップされるように、ユーザーを常に「認証」する必要があります。

[Fact]
public async Task JwtIsSkipped()
{
    var response = (await _Client.GetAsync("/jwt")).EnsureSuccessStatusCode();
    var stringResponse = await response.Content.ReadAsStringAsync();

    Assert.Equal("Working!", stringResponse);
}

このようにテストを実行すると失敗するので、次のように this doc この簡単な認証ハンドラを追加しました。

public class TestAuthHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
    public const string DefaultScheme = "Test";
    public TestAuthHandler(IOptionsMonitor<AuthenticationSchemeOptions> options,
        ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
        : base(options, logger, encoder, clock)
    {
    }

    protected override Task<AuthenticateResult> HandleAuthenticateAsync()
    {
        var claims = new[] { new Claim(ClaimTypes.Name, "Test user") };
        var identity = new ClaimsIdentity(claims, DefaultScheme);
        var principal = new ClaimsPrincipal(identity);
        var ticket = new AuthenticationTicket(principal, DefaultScheme);

        return Task.FromResult(AuthenticateResult.Success(ticket));
    }
}

だから今私のテストクラスは次のようになります:

public class UnitTest : IClassFixture<WebApplicationFactory<Startup>>
{
    private readonly WebApplicationFactory<Startup> _Factory;
    private readonly HttpClient _Client;

    public UnitTest(WebApplicationFactory<Startup> factory)
    {
        _Factory = factory;
        _Client = _Factory.WithWebHostBuilder(builder =>
        {
            builder.ConfigureTestServices(services =>
            {
                services.AddAuthentication(TestAuthHandler.DefaultScheme)
                        .AddScheme<AuthenticationSchemeOptions, TestAuthHandler>(
                            TestAuthHandler.DefaultScheme, options => { });
            });
        }).CreateClient();

        _Client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(TestAuthHandler.DefaultScheme);
    }

    [Fact]
    public async Task JwtIsSkipped()
    {
        var response = (await _Client.GetAsync("/jwt")).EnsureSuccessStatusCode();
        var stringResponse = await response.Content.ReadAsStringAsync();

        Assert.Equal("Working!", stringResponse);
    }
}

それでも失敗します。何が悪いのかわかりません。

12
Shkar T. Noori

DefaultAuthenticateSchemeを設定する必要があります

builder.ConfigureTestServices(services =>
{
    services.AddAuthentication(options =>
    {
        x.DefaultAuthenticateScheme = TestAuthHandler.DefaultScheme;
        x.DefaultScheme = TestAuthHandler.DefaultScheme;
    }).AddScheme<AuthenticationSchemeOptions, TestAuthHandler>(
           TestAuthHandler.DefaultScheme, options => { });
});
2
Kahbazi