Skip JWT Auth during Tests ASP.Net Core 3.1 Web Api
I have had similar situation previously with Microsoft example and can promise you it can gives headaches, it may works on specific Core versions, but I have gave up. I have solved this way.
What my goal was, is to Authorize system while testing, instead of using AddAuthentication
in our test we just create a FakePolicyEvaluator
class and added it as a singleton to our test.
So let go to our FakePolicyEvaluator class:
public class FakePolicyEvaluator : IPolicyEvaluator
{
public virtual async Task<AuthenticateResult> AuthenticateAsync(AuthorizationPolicy policy, HttpContext context)
{
var principal = new ClaimsPrincipal();
principal.AddIdentity(new ClaimsIdentity(new[] {
new Claim("Permission", "CanViewPage"),
new Claim("Manager", "yes"),
new Claim(ClaimTypes.Role, "Administrator"),
new Claim(ClaimTypes.NameIdentifier, "John")
}, "FakeScheme"));
return await Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(principal,
new AuthenticationProperties(), "FakeScheme")));
}
public virtual async Task<PolicyAuthorizationResult> AuthorizeAsync(AuthorizationPolicy policy,
AuthenticateResult authenticationResult, HttpContext context, object resource)
{
return await Task.FromResult(PolicyAuthorizationResult.Success());
}
}
Then in our ConfigureTestServices
we added services.AddSingleton<IPolicyEvaluator, FakePolicyEvaluator>();
So in your test code like this:
private readonly HttpClient _client;
public UnitTest(WebApplicationFactory<Startup> factory)
{
_client = factory.WithWebHostBuilder(builder =>
{
builder.ConfigureTestServices(services =>
{
services.AddSingleton<IPolicyEvaluator, FakePolicyEvaluator>();
});
}).CreateClient();
}
[Fact]
public async Task JwtIsSkipped()
{
var response = (await _client.GetAsync("/jwt")).EnsureSuccessStatusCode();
var stringResponse = await response.Content.ReadAsStringAsync();
Assert.Equal("Working!", stringResponse);
}
That is it. Now when you test, it will bypass authentication. I have testing it with the provided controller and it works.
It is also possible to place the fake inside application startup, and it will be both testable for test and working under development environment. Check the referenced article.
Disclaimer: I have wrote in more depth article about this in my personal website Reference you can download a github version of this https://github.com/maythamfahmi/BlogExamples/tree/master/BypassAuthorization
You need to set DefaultAuthenticateScheme
builder.ConfigureTestServices(services =>
{
services.AddAuthentication(options =>
{
x.DefaultAuthenticateScheme = TestAuthHandler.DefaultScheme;
x.DefaultScheme = TestAuthHandler.DefaultScheme;
}).AddScheme<AuthenticationSchemeOptions, TestAuthHandler>(
TestAuthHandler.DefaultScheme, options => { });
});