Posts About

Disabling OAuth2 in ASP.NET Core Integration Tests

Recently I've had to integrate OAuth2 into our backend here at CarbonCure. This broke the tests since you can't easily authenticate with OAuth2 without interacting with a browser, so the best option was to disable it entirely.

0. Prerequisites

This procedure requires a setup matching Microsoft's official documentation on the subject. Specifically, you need to have implemented the section on "Customize WebApplicationFactory."

This also assumes you've used the Google OAuth2 integration without identity, the best example of which is also described in Microsoft's docs. However, there's a point where you can likely change the code to suite your OAuth2 provider.

1. Create a custom IPolicyEvaluator

Internally, ASP.NET Core's identity management depends on some implementation of IPolicyEvaluator. So, we need to fake one that lets everything through. I got this class from a StackOverflow answer.

public class IntegrationTestsPolicyEvaluator : IPolicyEvaluator
{
    public async Task<AuthenticateResult> AuthenticateAsync(AuthorizationPolicy policy, HttpContext context)
    {
        // Always pass authentication.
        var authenticationTicket = new AuthenticationTicket(new ClaimsPrincipal(), new AuthenticationProperties(), JwtBearerDefaults.AuthenticationScheme);
        return await Task.FromResult(AuthenticateResult.Success(authenticationTicket));
    }

    public async Task<PolicyAuthorizationResult> AuthorizeAsync(AuthorizationPolicy policy, AuthenticateResult authenticationResult, HttpContext context, object resource)
    {
        // Always pass authorization
        return await Task.FromResult(PolicyAuthorizationResult.Success());
    }
}

2. Remove the existing policy evaluator

Once this is done, we need to remove the IPolicyEvaluator ASP.NET Core injected for us and replace it with ours. Assuming you've followed the docs mentioned above, somewhere in your factory insert the following two lines:

services.RemoveAll<IPolicyEvaluator>(); // Cut out the existing IPolicyEvaluator
services.AddSingleton<IPolicyEvaluator, IntegrationTestsPolicyEvaluator>(); // Insert the replacement

3. Disable setup for the existing OAuth2 integration

The trouble I was experiencing was solved by this step. Even though I had told ASP.NET Core to let everything through, it still tried to create a Google OAuth2 handler upon the first request. Since our testing project doesn't quite share the same configuration as the main project, the Google OAuth2 configuration setup handler would fail with the following errors:

The 'ClientId' option must be provided.
// or
The 'ClientSecret' option must be provided.

To fix this, we simply have to remove the handler for the OAuth2 provider and the OAuth2 configuration handler. Both are straightforward to remove — though the configuration handler is contained inside of a IValidateOptions construct.

services.RemoveAll<GoogleHandler>();
services.RemoveAll<IValidateOptions<GoogleOptions>>();

While this is specific to the Google OAuth2 handler, it should be possible to swap out the Google-specific types with the types of the other providers.

I hope this helps!