When working with applications in ASP.NET Core 6, you will often want to create an IP address whitelist to allow client requests only from certain IP addresses, while blocking requests from all other addresses. We do this to protect our API endpoints from potentially malicious requests from bad actors, while at the same time allowing requests originating from trusted IP addresses.

Also called an IP safelist, an IP whitelist helps to ensure that our application’s sensitive data is exposed only to IP addresses that we know and trust. An IP whitelist can be implemented in ASP.NET Core by using middleware or by using MVC action filters. This article shows how we can implement an IP whitelist in ASP.NET Core 6 by using middleware.

To work with the code examples provided in this article, you should have Visual Studio 2022 installed in your system. If you don’t already have a copy, you can download Visual Studio 2022 here.

Create an ASP.NET Core Web API project in Visual Studio 2022

First off, let’s create an ASP.NET Core project in Visual Studio 2022. Following these steps will create a new ASP.NET Core Web API project in Visual Studio 2022:

  1. Launch the Visual Studio 2022 IDE.
  2. Click on “Create new project.”
  3. In the “Create new project” window, select “ASP.NET Core Web API” from the list of templates displayed.
  4. Click Next.
  5. In the “Configure your new project” window, specify the name and location for the new project.
  6. Optionally check the “Place solution and project in the same directory” check box, depending on your preferences.
  7. Click Next.
  8. In the “Additional Information” window shown next, ensure that the “Use controllers…” check box is checked. Leave the “Authentication Type” set to “None” (default). And make sure the check boxes “Enable Docker,” “Configure for HTTPS,” and “Enable Open API Support” are unchecked as we won’t be using any of those features here.
  9. Click Create.

We’ll use this ASP.NET Core 6 Web API project to work with IP whitelists in the subsequent sections of this article.

The Program class in ASP.NET Core 6

Program and Startup are the main classes for configuring your .NET applications. However, ASP.NET Core 6 provides a simplified programming and hosting model that removes most of the boilerplate code. You no longer have the Startup class now. Instead, you have to write your code to configure the request processing pipeline in the Program class.

When you create a new ASP.NET Core 6 project in Visual Studio, the Program class would look like this:

var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
var app = builder.Build();
// Configure the HTTP request pipeline.
app.UseAuthorization();
app.MapControllers();
app.Run();

We’ll use this Program class in the subsequent sections of this article. But first we’ll examine how we can implement an IP whitelist middleware in ASP.NET Core 6.

Specify the whitelisted IP addresses in the config file

Specify the following whitelisted IP addresses in the appsettings.json file.

"IPWhitelistOptions": {
    "Whitelist": [ "192.168.0.9", "192.168.1.9", "::1" ]
  }

Note that these IP addresses have been given for illustration purposes only. You should replace these IP addresses with the IP addresses you would like to whitelist.

Now create a new class named IPWhitelistOptions with the following code, which will read the config values (IP addresses) we just specified.

public class IPWhitelistOptions
{
   public List<string> Whitelist { get; set; }
}

Create the IPWhitelistMiddleware class

To build our middleware that will whitelist our IP addresses, create a new class called IPWhitelistMiddleware with the following code.

public class IPWhitelistMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly IPWhitelistOptions _iPWhitelistOptions;
        private readonly ILogger<IPWhitelistMiddleware> _logger;
        public IPWhitelistMiddleware(RequestDelegate next,
        ILogger<IPWhitelistMiddleware> logger,
            IOptions<IPWhitelistOptions> applicationOptionsAccessor)
        {
            _iPWhitelistOptions = applicationOptionsAccessor.Value;
            _next = next;
            _logger = logger;
        }
        public async Task Invoke(HttpContext context)
        {
            if (context.Request.Method != HttpMethod.Get.Method)
            {
                var ipAddress = context.Connection.RemoteIpAddress;
                List<string> whiteListIPList =
                _iPWhitelistOptions.Whitelist;
                var isIPWhitelisted = whiteListIPList
                .Where(ip => IPAddress.Parse(ip)
                .Equals(ipAddress))
                .Any();
                if (!isIPWhitelisted)
                {
                    _logger.LogWarning(
                    "Request from Remote IP address: {RemoteIp}
                    is forbidden.", ipAddress);
                    context.Response.StatusCode =
                    (int)HttpStatusCode.Forbidden;
                    return;
                }
            }            
            await _next.Invoke(context);
        }
    }

Note that, in this example, whitelisting of IP addresses will work for all HTTP verbs except HTTP Get. If you want this whitelist to apply to all HTTP verbs, you can just comment out the following statement in the Invoke method.

if (context.Request.Method != HttpMethod.Get.Method)

In the Invoke method of our middleware, we’re reading all whitelisted IP addresses in a List of string. If the IP address where the request originated matches one of the IP addresses in the list, the request is allowed; otherwise the middleware returns HTTP 403 Forbidden and a log message is generated accordingly.

The IPWhitelistMiddlewareExtensions class

Now, create a class named IPWhitelistMiddlewareExtensions and enter the following code.

 public static class IPWhitelistMiddlewareExtensions
    {
        public static IApplicationBuilder UseIPWhitelist(this
        IApplicationBuilder builder)
        {
            return builder.UseMiddleware<IPWhitelistMiddleware>();
        }
    }

We’ll use our IP whitelist middleware in the Program class as illustrated in the next section.

Configure the IP whitelist middleware in the Program class

You should configure the IP whitelist middleware in the Program class using the Configure method of the Service collection, as shown in the code snippet given below.

builder.Services.Configure<IPWhitelistOptions>(builder.Configuration.GetSection("IPWhitelistOptions"));

Now, insert the following line of code in the Program class to leverage the extension method we created earlier.

app.UseIPWhitelist();

Here is how your Program class should look now:

using IPWhiteListDemo;
using System.Configuration;
var builder = WebApplication.CreateBuilder(args);
builder.Services.Configure<IPWhitelistOptions>(builder.Configuration.GetSection("IPWhitelistOptions"));
builder.Services.AddControllers();
var app = builder.Build();
app.UseIPWhitelist();
app.UseAuthorization();
app.MapControllers();
app.Run();

Lastly, run the application by pressing the F5 key in Visual Studio. To test the middleware, you can issue a HTTP Post request from Postman. If your IP address matches any of the IP addresses in the whitelist, the request will be allowed. Otherwise, the request will be denied and the middleware will return HTTP 403 Forbidden.