More than one scheme - Xabaril/Acheve.TestHost GitHub Wiki

You know... authentication is hard :-)

Sometimes a single scheme is not enough to handle our authentication requirements. In fact, you can see that in the ClaimsPrincipal class we have a collection of identities, so we can use more than one authentication scheme in one request and each one will create a new ClaimsIdentity that will be included in the ClaimsPrincipal instance.

To allow this scenario, you must configure three elements:

Register a TestServer for each scheme

public void ConfigureServices(IServiceCollection services)
{
    // Register Authentication
    services.AddAuthentication(options =>
        {
            options.DefaultScheme = TestServerDefaults.AuthenticationScheme;
        })
        .AddTestServer("scheme1")
        .AddTestServer("scheme2");

     ApiConfiguration.ConfigureServices(services);
        }

Use AuthenticationSchemes

You must configure the schemes you want to process. You have two options:

  • Authorize attribute
[Authorize(AuthenticationSchemes = "scheme1, scheme2")]
[HttpGet("schema")]
public IActionResult ValuesWithSchema()
{
    return Ok(new[] { "Value1", "Value2" });
}
  • Authorization policy
options.AddPolicy(Default, builder =>
{
    builder.RequireAuthenticatedUser();
    builder.AddAuthenticationSchemes("scheme1", "scheme2");
});

Either the one you choose, the behavior is the same. The default authentication scheme configured will be ignored and only the specified schemes will be used.

Add a call to .WithIdentity per scheme in the request

You should include a call to .WithIdentity per schema in the tests.

[Fact]
public async Task When_Use_Different_Schemas_We_Are_Authenticated()
{
    var builder = _fixture.Server.CreateHttpApiRequest<SchemasController>(controller => controller.Values());

    var response = await builder
        .WithIdentity(Identities.Scheme1Claims, "scheme1")
        .WithIdentity(Identities.Scheme2Claims, "scheme2")
        .GetAsync();

    await response.IsSuccessStatusCodeOrThrow();
}