Bypassing ASP.NET Core 6.0 [Authorize] attribute for integration tests

Dipendra Neupane
codenp
Published in
2 min readMay 23, 2023

I recently started automated testing on some of my Asp.net Core projects.

Integration testing in ASP.NET Core is the process of testing the interactions and behavior of various components of an application within the context of an integrated environment.

I really like the approach of combining different modules and testing them as a unit that covers mostly different aspects of the software.

It involves testing how different components, such as controllers, services, and databases, work together to ensure that the application functions correctly as a whole.

Starting from the basics, I had to deal with the Authorize attribute on Asp.NetCore controller.

As you might know, the Authorize attribute is there to safeguard the entry point of an API and the valid entry will only happen when the header request contains the valid JWT bearer token.

For this example, I have set up the JWT-based authorization where the api/movies URL of MovieController is authorized and is only accessed once the user sends a bearer token on the request header.

[Authorize]
[HttpGet(Name = "get-movies")]
public IActionResult Get()
{
try
{
return Ok(Movies);
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return BadRequest();
}
}

The fully functional source code including the TestClient setup for the integration test is available on the GitHub repository.

Our goal is to Authorize the system while running the test without setting up the Authentication related code on our TestClient. For that, the code below represents the 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, "DipNeupane")
}, "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());
}
}

Now, let's register it as a singleton on our test configuration on TestClient.

public static class TestClient
{
public static HttpClient GetTestClient()
{
return new WebApplicationFactory<Program>().WithWebHostBuilder(builder =>
{
builder.ConfigureTestServices(services =>
{
services.AddSingleton<IPolicyEvaluator, FakePolicyEvaluator>();
});
}).CreateClient();
}
}

And that’s it! The test method below works fine with this simple workaround.

[TestMethod]
public async Task GetMovies_ShouldReturn200StatusCode()
{
//Setup
var client = TestClient.GetTestClient();

//arrange
var response = await client.GetAsync("api/Movies");

//Assert
Assert.IsTrue(response.StatusCode == HttpStatusCode.OK);
}

You now have a flexible fake scheme that you can use in your tests. You can make further customization for your requirement if needed.

--

--

Dipendra Neupane
codenp
Editor for

Full-Stack Software Dev | When Dipendra isn't busy crafting code or captivating content, you can find him enjoying a good cup of americano or hitting the Gym.