Integration testing authorized endpoints with already specified authentication schemes

Viewed 52

I am trying to set up integration tests for my ASP.NET Web API with authorized endpoints.

I have followed the documentation from Microsoft to add mock authentication to the integration tests to allow the test client to access the authorized endpoints. https://learn.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-6.0

E.g.

builder.ConfigureTestServices(services =>
{
    services.AddAuthorization(options =>
    {
        options.DefaultPolicy = new AuthorizationPolicyBuilder()
            .AddAuthenticationSchemes("Test")
            .RequireAuthenticatedUser()
            .Build();
    });
}

This works fine if you are using default authentication schemes that you can change on the startup of your integration tests to use the test scheme. But, my authorized endpoints are using specified AuthenticationSchemes so the test scheme will never be authorized for the endpoint. E.g.

[Authorize(AuthenticationSchemes = "Scheme1,Scheme2")]
public class AppVersionController : ControllerBase
{
    ...
}

I can get around this issue by specifying an environment variable when testing, checking this and dynamically adding the test scheme to the authorized endpoint. Yet, this adds a lot of test-specific logic to the app, which isn't nice to have in the main project.

This would work:

// Test scheme added dynamically from an environment variable to get the below result
[Authorize(AuthenticationSchemes = "Scheme1,Scheme2,Test")]
public class AppVersionController : ControllerBase
{
    ...
}

I get this done by creating a custom attribute that looks basically like this:

public class AuthorizeAll : AuthorizeAttribute
{
    public AuthorizeAll()
    {
        var authenticationSchemes = "Scheme1,Scheme2";
        if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Testing")
        {
            authenticationSchemes += ",Test";
        }
        AuthenticationSchemes = authenticationSchemes;
    }
}

I just don't like how we will have to continue to maintain this test authentication scheme in the application layer as well as the security concerns with this approach.

Questions

What is the best way to authorize endpoints for .NET integration tests when specific authentication schemes are set?

Is it good practice to check environment variables in the app when unit testing to run specific logic that the tests need to work?

The main authentication scheme used at the moment is using JWTs, so is there a better way to mock JWTs for the tests?

0 Answers
Related