This is a common question we get on the repo in one way or another. For integration tests, unless you are specifically testing your auth mechanisms, you should mock the auth handler the same way you do the database.
Can we cover this in the docs? It involves creating a TestAuthenticationHandler and registering it through ConfigureServices in your WebApplicationFactory.
I think this is a dup of one or more existing issues on the Testing Project, but I'll sort that out later. I'm 馃弮馃槄 right now with a backlog of work.
I hope this helps anyone looking for it, be sure to have UseAuthentication() before UseAuthorization() in your pipeline. If you don't have UseAuthentication() the handler won't fire and you won't be signed in through the test handler.
This creates a scheme named "Test" which will always sign you in, and adds the Authorization header to the client so you won't be challenged with a 401.
public static class TestWebApplicationFactory
{
public static HttpClient Create()
{
var factory = new WebApplicationFactory<Startup>()
.WithWebHostBuilder(host =>
{
host.ConfigureTestServices(services =>
{
services
.AddAuthentication("Test")
.AddScheme<AuthenticationSchemeOptions, AuthenticationTestHandler>("Test", null);
});
});
var client = factory.CreateClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Test", "true");
return client;
}
}
public class AuthenticationTestHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
public AuthenticationTestHandler(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, "Test");
var principal = new ClaimsPrincipal(identity);
var ticket = new AuthenticationTicket(principal, "Test");
var result = AuthenticateResult.Success(ticket);
return Task.FromResult(result);
}
}
@guardrex You sound swamped with work, I hope this is useful to you as well and saves you some time.
Thank you! :beers: I'm 100% sure that you're right about that! 馃弮馃弮馃弮馃弮馃弮馃弮馃槄馃弮馃弮
Update ... I should be working this into the topic+sample (and probably one or two additional integration testing topic updates) this weekend (10/26-10/27).
I hope this helps anyone looking for it, be sure to have
UseAuthentication()beforeUseAuthorization()in your pipeline. If you don't haveUseAuthentication()the handler won't fire and you won't be signed in through the test handler.This creates a scheme named "Test" which will always sign you in, and adds the Authorization header to the client so you won't be challenged with a 401.
public static class TestWebApplicationFactory { public static HttpClient Create() { var factory = new WebApplicationFactory<Startup>() .WithWebHostBuilder(host => { host.ConfigureTestServices(services => { services .AddAuthentication("Test") .AddScheme<AuthenticationSchemeOptions, AuthenticationTestHandler>("Test", null); }); }); var client = factory.CreateClient(); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Test", "true"); return client; } } public class AuthenticationTestHandler : AuthenticationHandler<AuthenticationSchemeOptions> { public AuthenticationTestHandler(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, "Test"); var principal = new ClaimsPrincipal(identity); var ticket = new AuthenticationTicket(principal, "Test"); var result = AuthenticateResult.Success(ticket); return Task.FromResult(result); } }@guardrex You sound swamped with work, I hope this is useful to you as well and saves you some time.
I had to add app.UseAuthentication(); to my app's Startup.Configure() method in order to get this working.
Thank you @jvandertil and @guardrex for your help here. I look forward to seeing your solution in the docs @guardrex!
Most helpful comment
Update ... I should be working this into the topic+sample (and probably one or two additional integration testing topic updates) this weekend (10/26-10/27).