Take advantage of fake authentication/authorization checks to simplify integration tests in ASP.Net Core Credit: Paul Keller Integration tests are used to check if the different parts of the application work as expected when they are assembled together. When working with integration tests, you will often want to skip authentication and authorization tests. For instance, you might be more interested in testing the controller methods, without authentication and authorization getting in the way. In this article I will discuss how we can bypass such security checks when working with integration tests in ASP.Net Core. Who needs secure integration tests? You will often need to write integration tests for controller methods that have the [Authorize] tag on them. Let’s say that you are hitting an identity provider (that resides on another server) with this attribute. The problem is that your integration tests might fail if the identity server is down. As such, it would be a good practice to bypass the authentication checks when running integration tests on the controller methods. After all, you want to test the application pipeline and not the availability of an external server. In the sections that follow, we will examine how we can bypass the [Authorize] attribute in integration tests. Create an ASP.Net Core Web API project in Visual Studio First off, let’s create an ASP.Net Core project. If Visual Studio 2017 is up and running in your system, follow the steps given below to create a new ASP.Net Core project in Visual Studio. Launch the Visual Studio 2017 IDE. Click on File > New > Project. Select “ASP.Net Core Web Application (.Net Core)” from the list of the templates displayed. Specify a name for the project. Click OK to save the project. A new window “New .Net Core Web Application…” is shown next. Select .Net Core as the runtime and ASP.Net Core 2.2 (or later) from the drop-down list at the top. Select API as the project template Ensure that the check boxes “Enable Docker Support” and “Configure for HTTPS” are unchecked as we won’t be using those features here. Ensure that “No Authentication” is selected as we won’t be using authentication either. Click OK. This will create a new ASP.Net Core Web API project in Visual Studio. IDG Add authentication to the ConfigureServices method in ASP.Net Core The Startup class in the Startup.cs file contains the ConfigureServices method. Note that the ConfigureServices method is called by the runtime—you can take advantage of this method to add services to the pipeline. Next, write the following code in the ConfigureServices method of the Startup.cs file. public void ConfigureServices(IServiceCollection services) { services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; }).AddJwtBearer(options => { options.Authority = "abcxyz.com"; options.Audience = "abcxyz.com"; }); } Create a controller method in ASP.Net Core Now create a controller named DefaultController that contains the following code. using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace BypassAuthentication.Controllers { [Route("api/[controller]")] [ApiController] public class DefaultController : ControllerBase { [HttpGet] public string Get() { return "Hello World!"; } } } We will take advantage of this controller to write integration tests later. Create a test project in ASP.Net Core Now that the ASP.Net Core Web API project has been created, let’s create a test project to write our integration tests. To do this, follow the steps given below. In the Visual Studio IDE, click on File > New > Project. Select .Net Core from the list of installed templates. Select “xUnit Test Project (.Net Core)” from the list of templates displayed. Specify a name for the project. Click OK to save. Add the TestHost package to your test project in ASP.Net Core ASP.Net Core includes a test host that you can add to your integration test projects via NuGet. The TestHost package provides you with an ASP.Net Core Web Server that you can take advantage of to write and execute tests. To install the TestHost package, select the integration test project in the Solution Explorer window, right click, and select “Manage NuGet Packages…”. Then click on Browse, search for “Microsoft.AspNetCore.TestHost” package, and install the package. You should also install the Microsoft.AspNetCore.Diagnostics and Microsoft.AspNetCore.Mvc packages from NuGet (see the screen image below). IDG Create integration tests in your ASP.Net Core test project When you created the test project in ASP.Net Core in the step above, a test class will be created in the project automatically. Replace the test class created by default with the following code. public class MyTests { private readonly TestServer testServer; private readonly HttpClient httpClient; public MyTests() { testServer = new TestServer(new WebHostBuilder() .UseStartup<Startup>()); httpClient = testServer.CreateClient(); } [Fact] public async Task GetMessageTestAsync() { var response = await httpClient.GetAsync("http://localhost:13022/api/default"); response.EnsureSuccessStatusCode(); var result = await response.Content.ReadAsStringAsync(); Assert.NotNull(result); } } Note the usage of the TestServer and how the httpClient instance is configured in the constructor. The GetMessageTestAsync test method will run fine as long as there is no [Authorize] attribute on the controller or the controller method. However, if the controller or the controller method has an [Authorize] tag, the GetMessageTestAsync test method will fail, stating that you are unauthorized to call the Get method of the controller. Let’s now examine how we can bypass this security check when running integration tests. Bypass the authentication/authorization check in ASP.Net Core To bypass the authentication/authorization check, we need to create a dummy Startup class. To do that, we should create a class that extends the Startup class and overrides its methods. First off, we should reorganize the ConfigureServices method so that we can override it later. Here’s the updated version of the ConfigureServices method. public void ConfigureServices(IServiceCollection services) { services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); ConfigureAuthentication(services); } protected virtual void ConfigureAuthentication(IServiceCollection services) { services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; }).AddJwtBearer(options => { options.Authority = "abcxyz.com"; options.Audience = "abcxyz.com"; }); } Create a dummy Startup class in your ASP.Net Core test project In the test project, create a dummy Startup class as shown in the code snippet given below. public class FakeStartup : Startup { public FakeStartup(IConfiguration configuration) : base(configuration) { } protected override void ConfigureAuthentication(IServiceCollection services) { //Write your implementation of fake authentication here } } Next, you should update the constructor of the MyTests class (this is our test class) with the following piece of code. Note that the TestServer now uses the FakeStartup class. public MyTests() { testServer = new TestServer(new WebHostBuilder() .UseStartup<FakeStartup>()); httpClient = testServer.CreateClient(); } Create a custom authentication handler class to fake authentication Note that the test will still fail if you run it now because the authentication middleware hasn’t been specified in the FakeStartup class. To achieve this, you should create a custom authentication handler class that extends the AuthenticationHandler class and overrides the HandleAuthenticateAsync method. It is in this method that you can approve or reject an authentication request. Lastly, you should specify the custom authentication middleware in the FakeStartup class we created earlier. I will leave this part for you to implement on your own. And that’s all you need to do! Your integration tests will now run perfectly as the security checks will be bypassed. Integration tests often need to take advantage of infrastructure concerns—database resources, file system resources, web requests and responses, etc. As such, you will not want your integration tests to check for authentication/authorization, especially if your security framework resides in an external server. By creating a dummy Startup class and dummy authentication middleware, you can get the job done. Related content news F# 9 adds nullable reference types Latest version of Microsoft’s functional .NEt programming language provides a type-safe way to handle reference types that can have null as a valid value. By Paul Krill Nov 18, 2024 3 mins Microsoft .NET Programming Languages Software Development how-to How to use DispatchProxy for AOP in .NET Core Take advantage of the DispatchProxy class in C# to implement aspect-oriented programming by creating proxies that dynamically intercept method calls. By Joydip Kanjilal Nov 14, 2024 7 mins Microsoft .NET C# Development Libraries and Frameworks news Visual Studio 17.12 brings C++, Copilot enhancements Debugging and productivity improvements also feature in the latest release of Microsoft’s signature IDE, built for .NET 9. By Paul Krill Nov 13, 2024 3 mins Visual Studio Integrated Development Environments Microsoft .NET news Microsoft’s .NET 9 arrives, with performance, cloud, and AI boosts Cloud-native apps, AI-enabled apps, ASP.NET Core, Aspire, Blazor, MAUI, C#, and F# all get boosts with the latest major rev of the .NET platform. By Paul Krill Nov 12, 2024 4 mins C# Generative AI Microsoft .NET Resources Videos