Repository: ThreeMammals/Ocelot

Issue:
Issue with IP Blocking and Allowing in global configuration
I configured IP blocking and allowing in Ocelot using SecurityOptions, but it's not working.

 
```
{
  "GlobalConfiguration": {
    "BaseUrl": "http://localhost:5000",
    "SecurityOptions": {
      "IPBlockedList": ["192.168.0.23"]
    }
  }
}


```


The IP blocking configuration is not working as expected.




Hints:
Hello, Cavid!
It seems we lack support for global settings.
The potential solutions could be:
1. Solely using `ocelot.json`. Define the options for each route individually.
2. Utilizing C# coding. Replace the `ISecurityOptionsCreator` service in the DI container by redeveloping the `SecurityOptionsCreator` class to consider only the global settings.
https://github.com/ThreeMammals/Ocelot/blob/6088515173b70abd52798e544e5ded409680dbdb/src/Ocelot/DependencyInjection/OcelotBuilder.cs#L141

Which solution would be more convenient for you?
Hello @Fabman08,
The absence of global settings support is a significant issue. Here's the current usage of [SecurityOptionsCreator](https://github.com/ThreeMammals/Ocelot/blob/develop/src/Ocelot/Configuration/Creator/SecurityOptionsCreator.cs):

https://github.com/ThreeMammals/Ocelot/blob/6088515173b70abd52798e544e5ded409680dbdb/src/Ocelot/Configuration/Creator/RoutesCreator.cs#L111

Consequently, the method should accept two arguments, including global settings:
https://github.com/ThreeMammals/Ocelot/blob/6088515173b70abd52798e544e5ded409680dbdb/src/Ocelot/Configuration/Creator/SecurityOptionsCreator.cs#L8
Would you be able to allocate some time to address this?
Hi @raman-m!
Sure, I'll be able to fix the issue this or next week. ☺️ 

@CavidH thank you for reporting this issue! 👍 
Thank you very much for your help. We will eagerly await the new version.
> Hello, Cavid! It seems we lack support for global settings. The potential solutions could be:
> 
> 1. Solely using `ocelot.json`. Define the options for each route individually.
> 2. Utilizing C# coding. Replace the `ISecurityOptionsCreator` service in the DI container by redeveloping the `SecurityOptionsCreator` class to consider only the global settings.
>    https://github.com/ThreeMammals/Ocelot/blob/6088515173b70abd52798e544e5ded409680dbdb/src/Ocelot/DependencyInjection/OcelotBuilder.cs#L141
> 
> Which solution would be more convenient for you?

I had thought of the first option, but since I have too many services, it will be difficult to control this
@raman-m just a little question about Global Settings behaviours.

I've found three ways to fix the issue:
1. Every properties in Route FileSecurityOptions overrides their Global Settings values
eg.
- Global:
Allowed: B,C
Blocked: E
ExcludeAllowedFromBlocked: true
- Route:
Allowed: **A,B,C**
Blocked: **D,E,F**
ExcludeAllowedFromBlocked: **false**
- Final:
Allowed: **A,B,C**
Blocked: **D,E,F**
ExcludeAllowedFromBlocked: **false**

2. Only the existing properties in Route FileSecurityOptions overrides their Global Settings values
eg.
- Global:
Allowed: B,C
Blocked: **E**
ExcludeAllowedFromBlocked: **true**
- Route:
Allowed: **A,B,C**
Blocked: *null*
ExcludeAllowedFromBlocked: *null*
- Final:
Allowed: ***A,B,C***
Blocked: **E**
ExcludeAllowedFromBlocked: **true**

3. The Route FileSecurityOptions values will be merged to Global Settings values
eg.
- Global:
Allowed: **A,B,C**
Blocked: **D,E**
ExcludeAllowedFromBlocked: true
- Route:
Allowed: **F,G,H**
Blocked: **I,K**
ExcludeAllowedFromBlocked: **false**
- Final:
Allowed: **A,B,C,F,G,H**
Blocked: **D,E,I,K**
ExcludeAllowedFromBlocked: **false**

Which one is the best?
@Fabman08  Your research is too complicated!
> Which one is the best?

It is best to prioritize the route-specific `FileSecurityOptions` object over the global settings. Therefore, if route settings are defined, all global settings should be disregarded. In practice, if the route object is null, then the global settings should be utilized.

> Every properties in Route FileSecurityOptions overrides their Global Settings values

Yes, if route options are defined, all global ones should be ignored. We will highlight this in the documentation. There should be no merging whatsoever. This approach is the simplest and most correct solution, as merging properties would be erroneous due to potential conflicts within the algorithm. Therefore, merging is identified as a source of bugs.

Patch:
diff --git a/src/Ocelot/Configuration/Creator/ISecurityOptionsCreator.cs b/src/Ocelot/Configuration/Creator/ISecurityOptionsCreator.cs
index 5f5f727f3..f85acf510 100644
--- a/src/Ocelot/Configuration/Creator/ISecurityOptionsCreator.cs
+++ b/src/Ocelot/Configuration/Creator/ISecurityOptionsCreator.cs
@@ -1,9 +1,8 @@
 ﻿using Ocelot.Configuration.File;
 
-namespace Ocelot.Configuration.Creator
+namespace Ocelot.Configuration.Creator;
+
+public interface ISecurityOptionsCreator
 {
-    public interface ISecurityOptionsCreator
-    {
-        SecurityOptions Create(FileSecurityOptions securityOptions);
-    }
+    SecurityOptions Create(FileSecurityOptions securityOptions, FileGlobalConfiguration global);
 }
diff --git a/src/Ocelot/Configuration/Creator/RoutesCreator.cs b/src/Ocelot/Configuration/Creator/RoutesCreator.cs
index 015944014..409257700 100644
--- a/src/Ocelot/Configuration/Creator/RoutesCreator.cs
+++ b/src/Ocelot/Configuration/Creator/RoutesCreator.cs
@@ -108,7 +108,7 @@ private DownstreamRoute SetUpDownstreamRoute(FileRoute fileRoute, FileGlobalConf
 
             var lbOptions = _loadBalancerOptionsCreator.Create(fileRoute.LoadBalancerOptions);
 
-            var securityOptions = _securityOptionsCreator.Create(fileRoute.SecurityOptions);
+            var securityOptions = _securityOptionsCreator.Create(fileRoute.SecurityOptions, globalConfiguration);
 
             var downstreamHttpVersion = _versionCreator.Create(fileRoute.DownstreamHttpVersion);
 
diff --git a/src/Ocelot/Configuration/Creator/SecurityOptionsCreator.cs b/src/Ocelot/Configuration/Creator/SecurityOptionsCreator.cs
index 3c4c93d80..8e53e963a 100644
--- a/src/Ocelot/Configuration/Creator/SecurityOptionsCreator.cs
+++ b/src/Ocelot/Configuration/Creator/SecurityOptionsCreator.cs
@@ -1,39 +1,28 @@
 ﻿using NetTools; // <PackageReference Include="IPAddressRange" Version="6.0.0" />
 using Ocelot.Configuration.File;
 
-namespace Ocelot.Configuration.Creator
+namespace Ocelot.Configuration.Creator;
+
+public class SecurityOptionsCreator : ISecurityOptionsCreator
 {
-    public class SecurityOptionsCreator : ISecurityOptionsCreator
+    public SecurityOptions Create(FileSecurityOptions securityOptions, FileGlobalConfiguration global)
     {
-        public SecurityOptions Create(FileSecurityOptions securityOptions)
-        {
-            var ipAllowedList = new List<string>();
-            var ipBlockedList = new List<string>();
-
-            foreach (var allowed in securityOptions.IPAllowedList)
-            {
-                if (IPAddressRange.TryParse(allowed, out var allowedIpAddressRange))
-                {
-                    var allowedIps = allowedIpAddressRange.Select<IPAddress, string>(x => x.ToString());
-                    ipAllowedList.AddRange(allowedIps);
-                }
-            }
-
-            foreach (var blocked in securityOptions.IPBlockedList)
-            {
-                if (IPAddressRange.TryParse(blocked, out var blockedIpAddressRange))
-                {
-                    var blockedIps = blockedIpAddressRange.Select<IPAddress, string>(x => x.ToString());
-                    ipBlockedList.AddRange(blockedIps);
-                }
-            }
-
-            if (securityOptions.ExcludeAllowedFromBlocked)
-            {
-                ipBlockedList = ipBlockedList.Except(ipAllowedList).ToList();
-            }
+        var options = securityOptions.IsEmpty() ? global.SecurityOptions : securityOptions;
+        var allowedIPs = options.IPAllowedList.SelectMany(Parse)
+            .ToArray();
+        var blockedIPs = options.IPBlockedList.SelectMany(Parse)
+            .Except(options.ExcludeAllowedFromBlocked ? allowedIPs : Enumerable.Empty<string>())
+            .ToArray();
+        return new(allowedIPs, blockedIPs);
+    }
 
-            return new SecurityOptions(ipAllowedList, ipBlockedList);
+    private static string[] Parse(string ipValue)
+    {
+        if (IPAddressRange.TryParse(ipValue, out var range))
+        {
+            return range.Select<IPAddress, string>(ip => ip.ToString()).ToArray();
         }
+
+        return Array.Empty<string>();
     }
 }
diff --git a/src/Ocelot/Configuration/File/FileGlobalConfiguration.cs b/src/Ocelot/Configuration/File/FileGlobalConfiguration.cs
index 7ce35f99e..1675680d3 100644
--- a/src/Ocelot/Configuration/File/FileGlobalConfiguration.cs
+++ b/src/Ocelot/Configuration/File/FileGlobalConfiguration.cs
@@ -13,6 +13,7 @@ public FileGlobalConfiguration()
             HttpHandlerOptions = new FileHttpHandlerOptions();
             CacheOptions = new FileCacheOptions();
             MetadataOptions = new FileMetadataOptions();
+            SecurityOptions = new FileSecurityOptions();
         }
 
         public string RequestIdKey { get; set; }
@@ -48,5 +49,7 @@ public FileGlobalConfiguration()
         public FileCacheOptions CacheOptions { get; set; }
 
         public FileMetadataOptions MetadataOptions { get; set; }
+
+        public FileSecurityOptions SecurityOptions { get; set; }
     }
 }
diff --git a/src/Ocelot/Configuration/File/FileSecurityOptions.cs b/src/Ocelot/Configuration/File/FileSecurityOptions.cs
index ffd595cb4..e3aa1fdd0 100644
--- a/src/Ocelot/Configuration/File/FileSecurityOptions.cs
+++ b/src/Ocelot/Configuration/File/FileSecurityOptions.cs
@@ -1,54 +1,51 @@
-namespace Ocelot.Configuration.File
+namespace Ocelot.Configuration.File;
+
+public class FileSecurityOptions
 {
-    public class FileSecurityOptions
+    public FileSecurityOptions()
     {
-        public FileSecurityOptions()
-        {
-            IPAllowedList = new List<string>();
-            IPBlockedList = new List<string>();
-            ExcludeAllowedFromBlocked = false;
-        }
+        IPAllowedList = new();
+        IPBlockedList = new();
+        ExcludeAllowedFromBlocked = false;
+    }
 
-        public FileSecurityOptions(FileSecurityOptions from)
-        {
-            IPAllowedList = new(from.IPAllowedList);
-            IPBlockedList = new(from.IPBlockedList);
-            ExcludeAllowedFromBlocked = from.ExcludeAllowedFromBlocked;
-        }
+    public FileSecurityOptions(FileSecurityOptions from)
+    {
+        IPAllowedList = new(from.IPAllowedList);
+        IPBlockedList = new(from.IPBlockedList);
+        ExcludeAllowedFromBlocked = from.ExcludeAllowedFromBlocked;
+    }
 
-        public FileSecurityOptions(string allowedIPs = null, string blockedIPs = null, bool? excludeAllowedFromBlocked = null)
-            : this()
+    public FileSecurityOptions(string allowedIPs = null, string blockedIPs = null, bool? excludeAllowedFromBlocked = null)
+        : this()
+    {
+        if (!string.IsNullOrEmpty(allowedIPs))
         {
-            if (!string.IsNullOrEmpty(allowedIPs))
-            {
-                IPAllowedList.Add(allowedIPs);
-            }
-
-            if (!string.IsNullOrEmpty(blockedIPs))
-            {
-                IPBlockedList.Add(blockedIPs);
-            }
-
-            ExcludeAllowedFromBlocked = excludeAllowedFromBlocked ?? false;
+            IPAllowedList.Add(allowedIPs);
         }
 
-        public FileSecurityOptions(IEnumerable<string> allowedIPs = null, IEnumerable<string> blockedIPs = null, bool? excludeAllowedFromBlocked = null)
-            : this()
+        if (!string.IsNullOrEmpty(blockedIPs))
         {
-            IPAllowedList.AddRange(allowedIPs ?? Enumerable.Empty<string>());
-            IPBlockedList.AddRange(blockedIPs ?? Enumerable.Empty<string>());
-            ExcludeAllowedFromBlocked = excludeAllowedFromBlocked ?? false;
+            IPBlockedList.Add(blockedIPs);
         }
 
-        public List<string> IPAllowedList { get; set; }
-        public List<string> IPBlockedList { get; set; }
+        ExcludeAllowedFromBlocked = excludeAllowedFromBlocked ?? false;
+    }
 
-        /// <summary>
-        /// Provides the ability to specify a wide range of blocked IP addresses and allow a subrange of IP addresses.
-        /// </summary>
-        /// <value>
-        /// Default value: false.
-        /// </value>        
-        public bool ExcludeAllowedFromBlocked { get; set; }
+    public FileSecurityOptions(IEnumerable<string> allowedIPs = null, IEnumerable<string> blockedIPs = null, bool? excludeAllowedFromBlocked = null)
+        : this()
+    {
+        IPAllowedList.AddRange(allowedIPs ?? Enumerable.Empty<string>());
+        IPBlockedList.AddRange(blockedIPs ?? Enumerable.Empty<string>());
+        ExcludeAllowedFromBlocked = excludeAllowedFromBlocked ?? false;
     }
+
+    public List<string> IPAllowedList { get; set; }
+    public List<string> IPBlockedList { get; set; }
+
+    /// <summary>Provides the ability to specify a wide range of blocked IP addresses and allow a subrange of IP addresses.</summary>
+    /// <value>A <see cref="bool"/> value, defaults to <see langword="false"/>.</value>        
+    public bool ExcludeAllowedFromBlocked { get; set; }
+
+    public bool IsEmpty() => IPAllowedList.Count == 0 && IPBlockedList.Count == 0;
 }
diff --git a/src/Ocelot/Configuration/SecurityOptions.cs b/src/Ocelot/Configuration/SecurityOptions.cs
index 96186fe65..09dd9a662 100644
--- a/src/Ocelot/Configuration/SecurityOptions.cs
+++ b/src/Ocelot/Configuration/SecurityOptions.cs
@@ -4,8 +4,8 @@ public class SecurityOptions
     {
         public SecurityOptions()
         {
-            IPAllowedList = new();
-            IPBlockedList = new();
+            IPAllowedList = new List<string>();
+            IPBlockedList = new List<string>();
         }
 
         public SecurityOptions(string allowed = null, string blocked = null)
@@ -22,13 +22,13 @@ public SecurityOptions(string allowed = null, string blocked = null)
             }
         }
 
-        public SecurityOptions(List<string> allowedList = null, List<string> blockedList = null)
+        public SecurityOptions(IList<string> allowedList = null, IList<string> blockedList = null)
         {
-            IPAllowedList = allowedList ?? new();
-            IPBlockedList = blockedList ?? new();
+            IPAllowedList = allowedList ?? new List<string>();
+            IPBlockedList = blockedList ?? new List<string>();
         }
 
-        public List<string> IPAllowedList { get; }
-        public List<string> IPBlockedList { get; }
+        public IList<string> IPAllowedList { get; }
+        public IList<string> IPBlockedList { get; }
     }
 }
diff --git a/src/Ocelot/Security/IPSecurity/IPSecurityPolicy.cs b/src/Ocelot/Security/IPSecurity/IPSecurityPolicy.cs
index e76044ecf..8437af39e 100644
--- a/src/Ocelot/Security/IPSecurity/IPSecurityPolicy.cs
+++ b/src/Ocelot/Security/IPSecurity/IPSecurityPolicy.cs
@@ -3,38 +3,40 @@
 using Ocelot.Middleware;
 using Ocelot.Responses;
 
-namespace Ocelot.Security.IPSecurity
+namespace Ocelot.Security.IPSecurity;
+
+public class IPSecurityPolicy : ISecurityPolicy
 {
-    public class IPSecurityPolicy : ISecurityPolicy
+    public Response Security(DownstreamRoute downstreamRoute, HttpContext context)
     {
-        public async Task<Response> Security(DownstreamRoute downstreamRoute, HttpContext httpContext)
+        var clientIp = context.Connection.RemoteIpAddress;
+        var options = downstreamRoute.SecurityOptions;
+        if (options == null || clientIp == null)
         {
-            var clientIp = httpContext.Connection.RemoteIpAddress;
-            var securityOptions = downstreamRoute.SecurityOptions;
-            if (securityOptions == null)
-            {
-                return new OkResponse();
-            }
+            return new OkResponse();
+        }
 
-            if (securityOptions.IPBlockedList != null)
+        if (options.IPBlockedList?.Count > 0)
+        {
+            if (options.IPBlockedList.Contains(clientIp.ToString()))
             {
-                if (securityOptions.IPBlockedList.Exists(f => f == clientIp.ToString()))
-                {
-                    var error = new UnauthenticatedError($" This request rejects access to {clientIp} IP");
-                    return new ErrorResponse(error);
-                }
+                var error = new UnauthenticatedError($"This request rejects access to {clientIp} IP");
+                return new ErrorResponse(error);
             }
+        }
 
-            if (securityOptions.IPAllowedList?.Count > 0)
+        if (options.IPAllowedList?.Count > 0)
+        {
+            if (!options.IPAllowedList.Contains(clientIp.ToString()))
             {
-                if (!securityOptions.IPAllowedList.Exists(f => f == clientIp.ToString()))
-                {
-                    var error = new UnauthenticatedError($"{clientIp} does not allow access, the request is invalid");
-                    return new ErrorResponse(error);
-                }
+                var error = new UnauthenticatedError($"{clientIp} does not allow access, the request is invalid");
+                return new ErrorResponse(error);
             }
-
-            return await Task.FromResult(new OkResponse());
         }
+
+        return new OkResponse();
     }
+
+    public Task<Response> SecurityAsync(DownstreamRoute downstreamRoute, HttpContext context)
+        => Task.Run(() => Security(downstreamRoute, context));
 }
diff --git a/src/Ocelot/Security/ISecurityPolicy.cs b/src/Ocelot/Security/ISecurityPolicy.cs
index 783d1b5ac..b4eb5bf75 100644
--- a/src/Ocelot/Security/ISecurityPolicy.cs
+++ b/src/Ocelot/Security/ISecurityPolicy.cs
@@ -2,10 +2,10 @@
 using Ocelot.Configuration;
 using Ocelot.Responses;
 
-namespace Ocelot.Security
+namespace Ocelot.Security;
+
+public interface ISecurityPolicy
 {
-    public interface ISecurityPolicy
-    {
-        Task<Response> Security(DownstreamRoute downstreamRoute, HttpContext httpContext);
-    }
+    Response Security(DownstreamRoute downstreamRoute, HttpContext context);
+    Task<Response> SecurityAsync(DownstreamRoute downstreamRoute, HttpContext context);
 }
diff --git a/src/Ocelot/Security/Middleware/SecurityMiddleware.cs b/src/Ocelot/Security/Middleware/SecurityMiddleware.cs
index 068ff2ea0..ebbd80248 100644
--- a/src/Ocelot/Security/Middleware/SecurityMiddleware.cs
+++ b/src/Ocelot/Security/Middleware/SecurityMiddleware.cs
@@ -11,8 +11,7 @@ public class SecurityMiddleware : OcelotMiddleware
 
         public SecurityMiddleware(RequestDelegate next,
             IOcelotLoggerFactory loggerFactory,
-            IEnumerable<ISecurityPolicy> securityPolicies
-            )
+            IEnumerable<ISecurityPolicy> securityPolicies)
             : base(loggerFactory.CreateLogger<SecurityMiddleware>())
         {
             _securityPolicies = securityPolicies;
@@ -27,7 +26,7 @@ public async Task Invoke(HttpContext httpContext)
             {
                 foreach (var policy in _securityPolicies)
                 {
-                    var result = await policy.Security(downstreamRoute, httpContext);
+                    var result = policy.Security(downstreamRoute, httpContext);
                     if (!result.IsError)
                     {
                         continue;


Test patch:
diff --git a/test/Ocelot.AcceptanceTests/Security/SecurityOptionsTests.cs b/test/Ocelot.AcceptanceTests/Security/SecurityOptionsTests.cs
new file mode 100644
index 000000000..7a33207b7
--- /dev/null
+++ b/test/Ocelot.AcceptanceTests/Security/SecurityOptionsTests.cs
@@ -0,0 +1,162 @@
+﻿using Microsoft.AspNetCore.Http;
+using Ocelot.Configuration.File;
+
+namespace Ocelot.AcceptanceTests.Security;
+
+public sealed class SecurityOptionsTests: Steps
+{
+    private readonly ServiceHandler _serviceHandler;
+
+    public SecurityOptionsTests()
+    {
+        _serviceHandler = new ServiceHandler();
+    }
+
+    public override void Dispose()
+    {
+        _serviceHandler.Dispose();
+        base.Dispose();
+    }
+
+    [Fact]
+    [Trait("Feat", "2170")]
+    public void Should_call_with_allowed_ip_in_global_config()
+    {
+        var port = PortFinder.GetRandomPort();
+        var ip = Dns.GetHostAddresses("192.168.1.35")[0];
+        var route = GivenRoute(port, "/myPath", "/worldPath");
+        var configuration = GivenGlobalConfiguration(route, "192.168.1.30-50", "192.168.1.1-100");
+
+        this.Given(x => x.GivenThereIsAServiceRunningOn(port, ip))
+            .And(x => GivenThereIsAConfiguration(configuration))
+            .And(x => GivenOcelotIsRunning())
+            .When(x => WhenIGetUrlOnTheApiGateway("/worldPath"))
+            .Then(x => ThenTheStatusCodeShouldBe(HttpStatusCode.OK));
+    }
+
+    [Fact]
+    [Trait("Feat", "2170")]
+    public void Should_block_call_with_blocked_ip_in_global_config()
+    {
+        var port = PortFinder.GetRandomPort();
+        var ip = Dns.GetHostAddresses("192.168.1.55")[0];
+        var route = GivenRoute(port, "/myPath", "/worldPath");
+        var configuration = GivenGlobalConfiguration(route, "192.168.1.30-50", "192.168.1.1-100");
+
+        this.Given(x => x.GivenThereIsAServiceRunningOn(port, ip))
+            .And(x => GivenThereIsAConfiguration(configuration))
+            .And(x => GivenOcelotIsRunning())
+            .When(x => WhenIGetUrlOnTheApiGateway("/worldPath"))
+            .Then(x => ThenTheStatusCodeShouldBe(HttpStatusCode.Unauthorized));
+    }
+
+    [Fact]
+    public void Should_call_with_allowed_ip_in_route_config()
+    {
+        var port = PortFinder.GetRandomPort();
+        var ip = Dns.GetHostAddresses("192.168.1.1")[0];
+        var securityConfig = new FileSecurityOptions
+        {
+            IPAllowedList = new() { "192.168.1.1" },
+        };
+        var route = GivenRoute(port, "/myPath", "/worldPath", securityConfig);
+        var configuration = GivenConfiguration(route);
+
+        this.Given(x => x.GivenThereIsAServiceRunningOn(port, ip))
+            .And(x => GivenThereIsAConfiguration(configuration))
+            .And(x => GivenOcelotIsRunning())
+            .When(x => WhenIGetUrlOnTheApiGateway("/worldPath"))
+            .Then(x => ThenTheStatusCodeShouldBe(HttpStatusCode.OK));
+    }
+
+    [Fact]
+    public void Should_block_call_with_blocked_ip_in_route_config()
+    {
+        var port = PortFinder.GetRandomPort();
+        var ip = Dns.GetHostAddresses("192.168.1.1")[0];
+        var securityConfig = new FileSecurityOptions
+        {
+            IPBlockedList = new() { "192.168.1.1" },
+        };
+        var route = GivenRoute(port, "/myPath", "/worldPath", securityConfig);
+        var configuration = GivenConfiguration(route);
+
+        this.Given(x => x.GivenThereIsAServiceRunningOn(port, ip))
+            .And(x => GivenThereIsAConfiguration(configuration))
+            .And(x => GivenOcelotIsRunning())
+            .When(x => WhenIGetUrlOnTheApiGateway("/worldPath"))
+            .Then(x => ThenTheStatusCodeShouldBe(HttpStatusCode.Unauthorized));
+    }
+
+    [Fact]
+    [Trait("Feat", "2170")]
+    public void Should_call_with_allowed_ip_in_route_config_and_blocked_ip_in_global_config()
+    {
+        var port = PortFinder.GetRandomPort();
+        var ip = Dns.GetHostAddresses("192.168.1.55")[0];
+        var securityConfig = new FileSecurityOptions
+        {
+            IPAllowedList = new() { "192.168.1.55" },
+        };
+        var route = GivenRoute(port, "/myPath", "/worldPath", securityConfig);
+        var configuration = GivenGlobalConfiguration(route, "192.168.1.30-50", "192.168.1.1-100");
+
+        this.Given(x => x.GivenThereIsAServiceRunningOn(port, ip))
+           .And(x => GivenThereIsAConfiguration(configuration))
+           .And(x => GivenOcelotIsRunning())
+           .When(x => WhenIGetUrlOnTheApiGateway("/worldPath"))
+           .Then(x => ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
+           .Then(x => ThenTheResponseBodyShouldBe("Hello from Fabrizio"));
+    }
+
+    [Fact]
+    [Trait("Feat", "2170")]
+    public void Should_block_call_with_blocked_ip_in_route_config_and_allowed_ip_in_global_config()
+    {
+        var port = PortFinder.GetRandomPort();
+        var ip = Dns.GetHostAddresses("192.168.1.35")[0];
+        var securityConfig = new FileSecurityOptions
+        {
+            IPBlockedList = new() { "192.168.1.35" },
+        };
+        var route = GivenRoute(port, "/myPath", "/worldPath", securityConfig);
+        var configuration = GivenGlobalConfiguration(route, "192.168.1.30-50", "192.168.1.1-100");
+
+        this.Given(x => x.GivenThereIsAServiceRunningOn(port, ip))
+           .And(x => GivenThereIsAConfiguration(configuration))
+           .And(x => GivenOcelotIsRunning())
+           .When(x => WhenIGetUrlOnTheApiGateway("/worldPath"))
+           .Then(x => ThenTheStatusCodeShouldBe(HttpStatusCode.Unauthorized));
+    }
+
+    private void GivenThereIsAServiceRunningOn(int port, IPAddress ipAddess)
+    {
+        string url = DownstreamUrl(port);
+        _serviceHandler.GivenThereIsAServiceRunningOn(url, async context =>
+        {
+            context.Connection.RemoteIpAddress = ipAddess;
+            context.Response.StatusCode = (int)HttpStatusCode.OK;
+            await context.Response.WriteAsync("Hello from Fabrizio");
+        });
+    }
+
+    private static FileConfiguration GivenGlobalConfiguration(FileRoute route, string allowed, string blocked, bool exclude = true)
+    {
+        var config = GivenConfiguration(route);
+        config.GlobalConfiguration.SecurityOptions = new FileSecurityOptions
+        {
+            IPAllowedList = new() { allowed },
+            IPBlockedList = new() { blocked },
+            ExcludeAllowedFromBlocked = exclude,
+        };
+        return config;
+    }
+
+    private static FileRoute GivenRoute(int port, string downstream, string upstream, FileSecurityOptions fileSecurityOptions = null) => new()
+    {
+        DownstreamPathTemplate = downstream,
+        UpstreamPathTemplate = upstream,
+        UpstreamHttpMethod = new() { HttpMethods.Get },
+        SecurityOptions = fileSecurityOptions ?? new(),
+    };
+}
diff --git a/test/Ocelot.UnitTests/Configuration/RoutesCreatorTests.cs b/test/Ocelot.UnitTests/Configuration/RoutesCreatorTests.cs
index dbb9ef25a..2c2b6e9bc 100644
--- a/test/Ocelot.UnitTests/Configuration/RoutesCreatorTests.cs
+++ b/test/Ocelot.UnitTests/Configuration/RoutesCreatorTests.cs
@@ -303,7 +303,7 @@ private void ThenTheDepsAreCalledFor(FileRoute fileRoute, FileGlobalConfiguratio
             _hfarCreator.Verify(x => x.Create(fileRoute), Times.Once);
             _daCreator.Verify(x => x.Create(fileRoute), Times.Once);
             _lboCreator.Verify(x => x.Create(fileRoute.LoadBalancerOptions), Times.Once);
-            _soCreator.Verify(x => x.Create(fileRoute.SecurityOptions), Times.Once);
+            _soCreator.Verify(x => x.Create(fileRoute.SecurityOptions, globalConfig), Times.Once);
             _metadataCreator.Verify(x => x.Create(fileRoute.Metadata, globalConfig), Times.Once);
         }
     }
diff --git a/test/Ocelot.UnitTests/Configuration/SecurityOptionsCreatorTests.cs b/test/Ocelot.UnitTests/Configuration/SecurityOptionsCreatorTests.cs
index 81d9fd36d..2a223c78f 100644
--- a/test/Ocelot.UnitTests/Configuration/SecurityOptionsCreatorTests.cs
+++ b/test/Ocelot.UnitTests/Configuration/SecurityOptionsCreatorTests.cs
@@ -2,62 +2,98 @@
 using Ocelot.Configuration.Creator;
 using Ocelot.Configuration.File;
 
-namespace Ocelot.UnitTests.Configuration
+namespace Ocelot.UnitTests.Configuration;
+
+public sealed class SecurityOptionsCreatorTests : UnitTest
 {
-    public class SecurityOptionsCreatorTests : UnitTest
-    {
-        private FileRoute _fileRoute;
-        private SecurityOptions _result;
-        private readonly ISecurityOptionsCreator _creator;
+    private readonly SecurityOptionsCreator _creator = new();
 
-        public SecurityOptionsCreatorTests()
+    [Fact]
+    public void Should_create_route_security_config()
+    {
+        // Arrange
+        var ipAllowedList = new List<string> { "127.0.0.1", "192.168.1.1" };
+        var ipBlockedList = new List<string> { "127.0.0.1", "192.168.1.1" };
+        var securityOptions = new FileSecurityOptions
         {
-            _creator = new SecurityOptionsCreator();
-        }
+            IPAllowedList = ipAllowedList,
+            IPBlockedList = ipBlockedList,
+        };
+        var expected = new SecurityOptions(ipAllowedList, ipBlockedList);
+        var globalConfig = new FileGlobalConfiguration();
+
+        // Act
+        var actual = _creator.Create(securityOptions, globalConfig);
+
+        // Assert
+        ThenTheResultIs(actual, expected);
+    }
 
-        [Fact]
-        public void should_create_security_config()
+    [Fact]
+    [Trait("Feat", "2170")]
+    public void Should_create_global_security_config()
+    {
+        // Arrange
+        var ipAllowedList = new List<string> { "127.0.0.1", "192.168.1.1" };
+        var ipBlockedList = new List<string> { "127.0.0.1", "192.168.1.1" };
+        var globalConfig = new FileGlobalConfiguration
         {
-            var ipAllowedList = new List<string> { "127.0.0.1", "192.168.1.1" };
-            var ipBlockedList = new List<string> { "127.0.0.1", "192.168.1.1" };
-            var fileRoute = new FileRoute
+            SecurityOptions = new()
             {
-                SecurityOptions = new FileSecurityOptions
-                {
-                    IPAllowedList = ipAllowedList,
-                    IPBlockedList = ipBlockedList,
-                },
-            };
-
-            var expected = new SecurityOptions(ipAllowedList, ipBlockedList);
-
-            this.Given(x => x.GivenThe(fileRoute))
-              .When(x => x.WhenICreate())
-              .Then(x => x.ThenTheResultIs(expected))
-              .BDDfy();
-        }
+                IPAllowedList = ipAllowedList,
+                IPBlockedList = ipBlockedList,
+            },
+        };
+        var expected = new SecurityOptions(ipAllowedList, ipBlockedList);
+
+        // Act
+        var actual = _creator.Create(new(), globalConfig);
+
+        // Assert
+        ThenTheResultIs(actual, expected);
+    }
 
-        private void GivenThe(FileRoute route)
+    [Fact]
+    [Trait("Feat", "2170")]
+    public void Should_create_global_route_security_config()
+    {
+        // Arrange
+        var routeIpAllowedList = new List<string> { "127.0.0.1", "192.168.1.1" };
+        var routeIpBlockedList = new List<string> { "127.0.0.1", "192.168.1.1" };
+        var securityOptions = new FileSecurityOptions
         {
-            _fileRoute = route;
-        }
+            IPAllowedList = routeIpAllowedList,
+            IPBlockedList = routeIpBlockedList,
+        };
+        var globalIpAllowedList = new List<string> { "127.0.0.2", "192.168.1.2" };
+        var globalIpBlockedList = new List<string> { "127.0.0.2", "192.168.1.2" };
+        var globalConfig = new FileGlobalConfiguration
+        {
+            SecurityOptions = new FileSecurityOptions
+            {
+                IPAllowedList = globalIpAllowedList,
+                IPBlockedList = globalIpBlockedList,
+            },
+        };
+        var expected = new SecurityOptions(routeIpAllowedList, routeIpBlockedList);
+
+        // Act
+        var actual = _creator.Create(securityOptions, globalConfig);
 
-        private void WhenICreate()
+        // Assert
+        ThenTheResultIs(actual, expected);
+    }
+
+    private static void ThenTheResultIs(SecurityOptions actual, SecurityOptions expected)
+    {
+        for (var i = 0; i < expected.IPAllowedList.Count; i++)
         {
-            _result = _creator.Create(_fileRoute.SecurityOptions);
+            actual.IPAllowedList[i].ShouldBe(expected.IPAllowedList[i]);
         }
 
-        private void ThenTheResultIs(SecurityOptions expected)
+        for (var i = 0; i < expected.IPBlockedList.Count; i++)
         {
-            for (var i = 0; i < expected.IPAllowedList.Count; i++)
-            {
-                _result.IPAllowedList[i].ShouldBe(expected.IPAllowedList[i]);
-            }
-
-            for (var i = 0; i < expected.IPBlockedList.Count; i++)
-            {
-                _result.IPBlockedList[i].ShouldBe(expected.IPBlockedList[i]);
-            }
+            actual.IPBlockedList[i].ShouldBe(expected.IPBlockedList[i]);
         }
     }
 }
diff --git a/test/Ocelot.UnitTests/Security/IPSecurityPolicyTests.cs b/test/Ocelot.UnitTests/Security/IPSecurityPolicyTests.cs
index 83d7bb73f..bd7b9cd3d 100644
--- a/test/Ocelot.UnitTests/Security/IPSecurityPolicyTests.cs
+++ b/test/Ocelot.UnitTests/Security/IPSecurityPolicyTests.cs
@@ -8,404 +8,391 @@
 using Ocelot.Responses;
 using Ocelot.Security.IPSecurity;
 
-namespace Ocelot.UnitTests.Security
+namespace Ocelot.UnitTests.Security;
+
+public sealed class IPSecurityPolicyTests : UnitTest
 {
-    public class IPSecurityPolicyTests : UnitTest
+    private readonly DownstreamRouteBuilder _downstreamRouteBuilder;
+    private readonly IPSecurityPolicy _policy;
+    private readonly HttpContext _context;
+    private readonly SecurityOptionsCreator _securityOptionsCreator;
+    private static readonly FileGlobalConfiguration Empty = new();
+
+    public IPSecurityPolicyTests()
     {
-        private readonly DownstreamRouteBuilder _downstreamRouteBuilder;
-        private readonly IPSecurityPolicy _ipSecurityPolicy;
-        private Response response;
-        private readonly HttpContext _httpContext;
-        private readonly SecurityOptionsCreator _securityOptionsCreator;
+        _context = new DefaultHttpContext();
+        _context.Items.UpsertDownstreamRequest(new DownstreamRequest(new HttpRequestMessage(HttpMethod.Get, "http://test.com")));
+        _context.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.1")[0];
+        _downstreamRouteBuilder = new DownstreamRouteBuilder();
+        _policy = new IPSecurityPolicy();
+        _securityOptionsCreator = new SecurityOptionsCreator();
+    }
 
-        public IPSecurityPolicyTests()
-        {
-            _httpContext = new DefaultHttpContext();
-            _httpContext.Items.UpsertDownstreamRequest(new DownstreamRequest(new HttpRequestMessage(HttpMethod.Get, "http://test.com")));
-            _httpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.1")[0];
-            _downstreamRouteBuilder = new DownstreamRouteBuilder();
-            _ipSecurityPolicy = new IPSecurityPolicy();
-            _securityOptionsCreator = new SecurityOptionsCreator();
-        }
-
-        [Fact]
-        public void should_No_blocked_Ip_and_allowed_Ip()
-        {
-            this.Given(x => x.GivenSetDownstreamRoute())
-                .When(x => x.WhenTheSecurityPolicy())
-                .Then(x => x.ThenSecurityPassing())
-                .BDDfy();
-        }
-
-        [Fact]
-        public void should_blockedIp_clientIp_block()
-        {
-            _httpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.1")[0];
-            this.Given(x => x.GivenSetBlockedIP())
-                .Given(x => x.GivenSetDownstreamRoute())
-                .When(x => x.WhenTheSecurityPolicy())
-                .Then(x => x.ThenNotSecurityPassing())
-                .BDDfy();
-        }
-
-        [Fact]
-        public void should_blockedIp_clientIp_Not_block()
-        {
-            _httpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.2")[0];
-            this.Given(x => x.GivenSetBlockedIP())
-                .Given(x => x.GivenSetDownstreamRoute())
-                .When(x => x.WhenTheSecurityPolicy())
-                .Then(x => x.ThenSecurityPassing())
-                .BDDfy();
-        }
-
-        [Fact]
-        public void should_allowedIp_clientIp_block()
-        {
-            _httpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.1")[0];
-            this.Given(x => x.GivenSetAllowedIP())
-                .Given(x => x.GivenSetDownstreamRoute())
-                .When(x => x.WhenTheSecurityPolicy())
-                .Then(x => x.ThenSecurityPassing())
-                .BDDfy();
-        }
-
-        [Fact]
-        public void should_allowedIp_clientIp_Not_block()
-        {
-            _httpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.2")[0];
-            this.Given(x => x.GivenSetAllowedIP())
-                .Given(x => x.GivenSetDownstreamRoute())
-                .When(x => x.WhenTheSecurityPolicy())
-                .Then(x => x.ThenNotSecurityPassing())
-                .BDDfy();
-        }
-
-        [Fact]
-        public void should_cidrNotation_allowed24_clientIp_block()
-        {
-            _httpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.10.5")[0];
-            this.Given(x => x.GivenCidr24AllowedIP())
-                .Given(x => x.GivenSetDownstreamRoute())
-                .When(x => x.WhenTheSecurityPolicy())
-                .Then(x => x.ThenNotSecurityPassing())
-                .BDDfy();
-        }
-
-        [Fact]
-        public void should_cidrNotation_allowed24_clientIp_not_block()
-        {
-            _httpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.5")[0];
-            this.Given(x => x.GivenCidr24AllowedIP())
-                .Given(x => x.GivenSetDownstreamRoute())
-                .When(x => x.WhenTheSecurityPolicy())
-                .Then(x => x.ThenSecurityPassing())
-                .BDDfy();
-        }
-
-        [Fact]
-        public void should_cidrNotation_allowed29_clientIp_block()
-        {
-            _httpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.10")[0];
-            this.Given(x => x.GivenCidr29AllowedIP())
-                .Given(x => x.GivenSetDownstreamRoute())
-                .When(x => x.WhenTheSecurityPolicy())
-                .Then(x => x.ThenNotSecurityPassing())
-                .BDDfy();
-        }
-
-        [Fact]
-        public void should_cidrNotation_blocked24_clientIp_block()
-        {
-            _httpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.1")[0];
-            this.Given(x => x.GivenCidr24BlockedIP())
-                .Given(x => x.GivenSetDownstreamRoute())
-                .When(x => x.WhenTheSecurityPolicy())
-                .Then(x => x.ThenNotSecurityPassing())
-                .BDDfy();
-        }
-
-        [Fact]
-        public void should_cidrNotation_blocked24_clientIp_not_block()
-        {
-            _httpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.10.1")[0];
-            this.Given(x => x.GivenCidr24BlockedIP())
-                .Given(x => x.GivenSetDownstreamRoute())
-                .When(x => x.WhenTheSecurityPolicy())
-                .Then(x => x.ThenSecurityPassing())
-                .BDDfy();
-        }
-
-        [Fact]
-        public void should_range_allowed_clientIp_block()
-        {
-            _httpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.15")[0];
-            this.Given(x => x.GivenRangeAllowedIP())
-                .Given(x => x.GivenSetDownstreamRoute())
-                .When(x => x.WhenTheSecurityPolicy())
-                .Then(x => x.ThenNotSecurityPassing())
-                .BDDfy();
-        }
-
-        [Fact]
-        public void should_range_allowed_clientIp_not_block()
-        {
-            _httpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.8")[0];
-            this.Given(x => x.GivenRangeAllowedIP())
-                .Given(x => x.GivenSetDownstreamRoute())
-                .When(x => x.WhenTheSecurityPolicy())
-                .Then(x => x.ThenSecurityPassing())
-                .BDDfy();
-        }
-
-        [Fact]
-        public void should_range_blocked_clientIp_block()
-        {
-            _httpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.5")[0];
-            this.Given(x => x.GivenRangeBlockedIP())
-                .Given(x => x.GivenSetDownstreamRoute())
-                .When(x => x.WhenTheSecurityPolicy())
-                .Then(x => x.ThenNotSecurityPassing())
-                .BDDfy();
-        }
-
-        [Fact]
-        public void should_range_blocked_clientIp_not_block()
-        {
-            _httpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.15")[0];
-            this.Given(x => x.GivenRangeBlockedIP())
-                .Given(x => x.GivenSetDownstreamRoute())
-                .When(x => x.WhenTheSecurityPolicy())
-                .Then(x => x.ThenSecurityPassing())
-                .BDDfy();
-        }
-
-        [Fact]
-        public void should_shortRange_allowed_clientIp_block()
-        {
-            _httpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.15")[0];
-            this.Given(x => x.GivenShortRangeAllowedIP())
-                .Given(x => x.GivenSetDownstreamRoute())
-                .When(x => x.WhenTheSecurityPolicy())
-                .Then(x => x.ThenNotSecurityPassing())
-                .BDDfy();
-        }
-
-        [Fact]
-        public void should_shortRange_allowed_clientIp_not_block()
-        {
-            _httpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.8")[0];
-            this.Given(x => x.GivenShortRangeAllowedIP())
-                .Given(x => x.GivenSetDownstreamRoute())
-                .When(x => x.WhenTheSecurityPolicy())
-                .Then(x => x.ThenSecurityPassing())
-                .BDDfy();
-        }
-
-        [Fact]
-        public void should_shortRange_blocked_clientIp_block()
-        {
-            _httpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.5")[0];
-            this.Given(x => x.GivenShortRangeBlockedIP())
-                .Given(x => x.GivenSetDownstreamRoute())
-                .When(x => x.WhenTheSecurityPolicy())
-                .Then(x => x.ThenNotSecurityPassing())
-                .BDDfy();
-        }
-
-        [Fact]
-        public void should_shortRange_blocked_clientIp_not_block()
-        {
-            _httpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.15")[0];
-            this.Given(x => x.GivenShortRangeBlockedIP())
-                .Given(x => x.GivenSetDownstreamRoute())
-                .When(x => x.WhenTheSecurityPolicy())
-                .Then(x => x.ThenSecurityPassing())
-                .BDDfy();
-        }
-
-        [Fact]
-        public void should_ipSubnet_allowed_clientIp_block()
-        {
-            _httpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.10.15")[0];
-            this.Given(x => x.GivenIpSubnetAllowedIP())
-                .Given(x => x.GivenSetDownstreamRoute())
-                .When(x => x.WhenTheSecurityPolicy())
-                .Then(x => x.ThenNotSecurityPassing())
-                .BDDfy();
-        }
-
-        [Fact]
-        public void should_ipSubnet_allowed_clientIp_not_block()
-        {
-            _httpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.15")[0];
-            this.Given(x => x.GivenIpSubnetAllowedIP())
-                .Given(x => x.GivenSetDownstreamRoute())
-                .When(x => x.WhenTheSecurityPolicy())
-                .Then(x => x.ThenSecurityPassing())
-                .BDDfy();
-        }
-
-        [Fact]
-        public void should_ipSubnet_blocked_clientIp_block()
-        {
-            _httpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.15")[0];
-            this.Given(x => x.GivenIpSubnetBlockedIP())
-                .Given(x => x.GivenSetDownstreamRoute())
-                .When(x => x.WhenTheSecurityPolicy())
-                .Then(x => x.ThenNotSecurityPassing())
-                .BDDfy();
-        }
-
-        [Fact]
-        public void should_ipSubnet_blocked_clientIp_not_block()
-        {
-            _httpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.10.1")[0];
-            this.Given(x => x.GivenIpSubnetBlockedIP())
-                .Given(x => x.GivenSetDownstreamRoute())
-                .When(x => x.WhenTheSecurityPolicy())
-                .Then(x => x.ThenSecurityPassing())
-                .BDDfy();
-        }
-
-        [Fact]
-        public void should_exludeAllowedFromBlocked_moreAllowed_clientIp_block()
-        {
-            _httpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.150")[0];
-            this.Given(x => x.GivenIpMoreAllowedThanBlocked(false))
-                .Given(x => x.GivenSetDownstreamRoute())
-                .When(x => x.WhenTheSecurityPolicy())
-                .Then(x => x.ThenNotSecurityPassing())
-                .BDDfy();
-        }
-
-        [Fact]
-        public void should_exludeAllowedFromBlocked_moreAllowed_clientIp_not_block()
-        {
-            _httpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.150")[0];
-            this.Given(x => x.GivenIpMoreAllowedThanBlocked(true))
-                .Given(x => x.GivenSetDownstreamRoute())
-                .When(x => x.WhenTheSecurityPolicy())
-                .Then(x => x.ThenSecurityPassing())
-                .BDDfy();
-        }
-
-        [Fact]
-        public void should_exludeAllowedFromBlocked_moreBlocked_clientIp_block()
-        {
-            _httpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.10")[0];
-            this.Given(x => x.GivenIpMoreBlockedThanAllowed(false))
-                .Given(x => x.GivenSetDownstreamRoute())
-                .When(x => x.WhenTheSecurityPolicy())
-                .Then(x => x.ThenNotSecurityPassing())
-                .BDDfy();
-        }
-
-        [Fact]
-        public void should_exludeAllowedFromBlocked_moreBlocked_clientIp_not_block()
-        {
-            _httpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.10")[0];
-            this.Given(x => x.GivenIpMoreBlockedThanAllowed(true))
-                .Given(x => x.GivenSetDownstreamRoute())
-                .When(x => x.WhenTheSecurityPolicy())
-                .Then(x => x.ThenSecurityPassing())
-                .BDDfy();
-        }
-
-        private void GivenSetAllowedIP()
-        {
-            _downstreamRouteBuilder.WithSecurityOptions(new SecurityOptions("192.168.1.1"));
-        }
+    [Fact]
+    public void Should_No_blocked_Ip_and_allowed_Ip()
+    {
+        GivenSetDownstreamRoute();
+        var actual = WhenTheSecurityPolicy();
+        Assert.False(actual.IsError);
+    }
 
-        private void GivenSetBlockedIP()
-        {
-            _downstreamRouteBuilder.WithSecurityOptions(new SecurityOptions(blocked: "192.168.1.1"));
-        }
+    [Fact]
+    public void Should_blockedIp_clientIp_block()
+    {
+        _context.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.1")[0];
+        GivenSetBlockedIP();
+        GivenSetDownstreamRoute();
+        var actual = WhenTheSecurityPolicy();
+        Assert.True(actual.IsError);
+    }
 
-        private void GivenSetDownstreamRoute()
-        {
-            _httpContext.Items.UpsertDownstreamRoute(_downstreamRouteBuilder.Build());
-        }
+    [Fact]
+    public void Should_blockedIp_clientIp_Not_block()
+    {
+        _context.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.2")[0];
+        GivenSetBlockedIP();
+        GivenSetDownstreamRoute();
+        var actual = WhenTheSecurityPolicy();
+        Assert.False(actual.IsError);
+    }
 
-        private void GivenCidr24AllowedIP()
-        {
-            var securityOptions = _securityOptionsCreator.Create(new FileSecurityOptions("192.168.1.0/24"));
-            _downstreamRouteBuilder.WithSecurityOptions(securityOptions);
-        }
+    [Fact]
+    public void Should_allowedIp_clientIp_block()
+    {
+        _context.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.1")[0];
+        GivenSetAllowedIP();
+        GivenSetDownstreamRoute();
+        var actual = WhenTheSecurityPolicy();
+        Assert.False(actual.IsError);
+    }
 
-        private void GivenCidr29AllowedIP()
-        {
-            var securityOptions = _securityOptionsCreator.Create(new FileSecurityOptions("192.168.1.0/29"));
-            _downstreamRouteBuilder.WithSecurityOptions(securityOptions);
-        }
+    [Fact]
+    public void Should_allowedIp_clientIp_Not_block()
+    {
+        _context.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.2")[0];
+        GivenSetAllowedIP();
+        GivenSetDownstreamRoute();
+        var actual = WhenTheSecurityPolicy();
+        Assert.True(actual.IsError);
+    }
 
-        private void GivenCidr24BlockedIP()
-        {
-            var securityOptions = _securityOptionsCreator.Create(new FileSecurityOptions(blockedIPs: "192.168.1.0/24"));
-            _downstreamRouteBuilder.WithSecurityOptions(securityOptions);
-        }
+    [Fact]
+    public void Should_cidrNotation_allowed24_clientIp_block()
+    {
+        _context.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.10.5")[0];
+        GivenCidr24AllowedIP();
+        GivenSetDownstreamRoute();
+        var actual = WhenTheSecurityPolicy();
+        Assert.True(actual.IsError);
+    }
 
-        private void GivenRangeAllowedIP()
-        {
-            var securityOptions = _securityOptionsCreator.Create(new FileSecurityOptions("192.168.1.0-192.168.1.10"));
-            _downstreamRouteBuilder.WithSecurityOptions(securityOptions);
-        }
+    [Fact]
+    public void Should_cidrNotation_allowed24_clientIp_not_block()
+    {
+        _context.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.5")[0];
+        GivenCidr24AllowedIP();
+        GivenSetDownstreamRoute();
+        var actual = WhenTheSecurityPolicy();
+        Assert.False(actual.IsError);
+    }
 
-        private void GivenRangeBlockedIP()
-        {
-            var securityOptions = _securityOptionsCreator.Create(new FileSecurityOptions(blockedIPs: "192.168.1.0-192.168.1.10"));
-            _downstreamRouteBuilder.WithSecurityOptions(securityOptions);
-        }
+    [Fact]
+    public void Should_cidrNotation_allowed29_clientIp_block()
+    {
+        _context.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.10")[0];
+        GivenCidr29AllowedIP();
+        GivenSetDownstreamRoute();
+        var actual = WhenTheSecurityPolicy();
+        Assert.True(actual.IsError);
+    }
 
-        private void GivenShortRangeAllowedIP()
-        {
-            var securityOptions = _securityOptionsCreator.Create(new FileSecurityOptions("192.168.1.0-10"));
-            _downstreamRouteBuilder.WithSecurityOptions(securityOptions);
-        }
+    [Fact]
+    public void Should_cidrNotation_blocked24_clientIp_block()
+    {
+        _context.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.1")[0];
+        GivenCidr24BlockedIP();
+        GivenSetDownstreamRoute();
+        var actual = WhenTheSecurityPolicy();
+        Assert.True(actual.IsError);
+    }
 
-        private void GivenShortRangeBlockedIP()
-        {
-            var securityOptions = _securityOptionsCreator.Create(new FileSecurityOptions(blockedIPs: "192.168.1.0-10"));
-            _downstreamRouteBuilder.WithSecurityOptions(securityOptions);
-        }
+    [Fact]
+    public void Should_cidrNotation_blocked24_clientIp_not_block()
+    {
+        _context.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.10.1")[0];
+        GivenCidr24BlockedIP();
+        GivenSetDownstreamRoute();
+        var actual = WhenTheSecurityPolicy();
+        Assert.False(actual.IsError);
+    }
 
-        private void GivenIpSubnetAllowedIP()
-        {
-            var securityOptions = _securityOptionsCreator.Create(new FileSecurityOptions("192.168.1.0/255.255.255.0"));
-            _downstreamRouteBuilder.WithSecurityOptions(securityOptions);
-        }
+    [Fact]
+    public void Should_range_allowed_clientIp_block()
+    {
+        _context.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.15")[0];
+        GivenRangeAllowedIP();
+        GivenSetDownstreamRoute();
+        var actual = WhenTheSecurityPolicy();
+        Assert.True(actual.IsError);
+    }
 
-        private void GivenIpSubnetBlockedIP()
-        {
-            var securityOptions = _securityOptionsCreator.Create(new FileSecurityOptions(blockedIPs: "192.168.1.0/255.255.255.0"));
-            _downstreamRouteBuilder.WithSecurityOptions(securityOptions);
-        }
+    [Fact]
+    public void Should_range_allowed_clientIp_not_block()
+    {
+        _context.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.8")[0];
+        GivenRangeAllowedIP();
+        GivenSetDownstreamRoute();
+        var actual = WhenTheSecurityPolicy();
+        Assert.False(actual.IsError);
+    }
 
-        private void GivenIpMoreAllowedThanBlocked(bool excludeAllowedInBlocked)
-        {
-            var securityOptions = _securityOptionsCreator.Create(new FileSecurityOptions("192.168.0.0/255.255.0.0", "192.168.1.100-200", excludeAllowedInBlocked));
-            _downstreamRouteBuilder.WithSecurityOptions(securityOptions);
-        }
+    [Fact]
+    public void Should_range_blocked_clientIp_block()
+    {
+        _context.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.5")[0];
+        GivenRangeBlockedIP();
+        GivenSetDownstreamRoute();
+        var actual = WhenTheSecurityPolicy();
+        Assert.True(actual.IsError);
+    }
 
-        private void GivenIpMoreBlockedThanAllowed(bool excludeAllowedInBlocked)
-        {
-            var securityOptions = _securityOptionsCreator.Create(new FileSecurityOptions("192.168.1.10-20", "192.168.1.0/23", excludeAllowedInBlocked));
-            _downstreamRouteBuilder.WithSecurityOptions(securityOptions);
-        }
+    [Fact]
+    public void Should_range_blocked_clientIp_not_block()
+    {
+        _context.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.15")[0];
+        GivenRangeBlockedIP();
+        GivenSetDownstreamRoute();
+        var actual = WhenTheSecurityPolicy();
+        Assert.False(actual.IsError);
+    }
 
-        private async Task WhenTheSecurityPolicy()
-        {
-            response = await _ipSecurityPolicy.Security(_httpContext.Items.DownstreamRoute(), _httpContext);
-        }
+    [Fact]
+    public void Should_shortRange_allowed_clientIp_block()
+    {
+        _context.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.15")[0];
+        GivenShortRangeAllowedIP();
+        GivenSetDownstreamRoute();
+        var actual = WhenTheSecurityPolicy();
+        Assert.True(actual.IsError);
+    }
 
-        private void ThenSecurityPassing()
-        {
-            Assert.False(response.IsError);
-        }
+    [Fact]
+    public void Should_shortRange_allowed_clientIp_not_block()
+    {
+        _context.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.8")[0];
+        GivenShortRangeAllowedIP();
+        GivenSetDownstreamRoute();
+        var actual = WhenTheSecurityPolicy();
+        Assert.False(actual.IsError);
+    }
+
+    [Fact]
+    public void Should_shortRange_blocked_clientIp_block()
+    {
+        _context.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.5")[0];
+        GivenShortRangeBlockedIP();
+        GivenSetDownstreamRoute();
+        var actual = WhenTheSecurityPolicy();
+        Assert.True(actual.IsError);
+    }
+
+    [Fact]
+    public void Should_shortRange_blocked_clientIp_not_block()
+    {
+        _context.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.15")[0];
+        GivenShortRangeBlockedIP();
+        GivenSetDownstreamRoute();
+        var actual = WhenTheSecurityPolicy();
+        Assert.False(actual.IsError);
+    }
+
+    [Fact]
+    public void Should_ipSubnet_allowed_clientIp_block()
+    {
+        _context.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.10.15")[0];
+        GivenIpSubnetAllowedIP();
+        GivenSetDownstreamRoute();
+        var actual = WhenTheSecurityPolicy();
+        Assert.True(actual.IsError);
+    }
+
+    [Fact]
+    public void Should_ipSubnet_allowed_clientIp_not_block()
+    {
+        _context.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.15")[0];
+        GivenIpSubnetAllowedIP();
+        GivenSetDownstreamRoute();
+        var actual = WhenTheSecurityPolicy();
+        Assert.False(actual.IsError);
+    }
+
+    [Fact]
+    public void Should_ipSubnet_blocked_clientIp_block()
+    {
+        _context.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.15")[0];
+        GivenIpSubnetBlockedIP();
+        GivenSetDownstreamRoute();
+        var actual = WhenTheSecurityPolicy();
+        Assert.True(actual.IsError);
+    }
+
+    [Fact]
+    public void Should_ipSubnet_blocked_clientIp_not_block()
+    {
+        _context.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.10.1")[0];
+        GivenIpSubnetBlockedIP();
+        GivenSetDownstreamRoute();
+        var actual = WhenTheSecurityPolicy();
+        Assert.False(actual.IsError);
+    }
+
+    [Fact]
+    public void Should_exludeAllowedFromBlocked_moreAllowed_clientIp_block()
+    {
+        _context.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.150")[0];
+        GivenIpMoreAllowedThanBlocked(false);
+        GivenSetDownstreamRoute();
+        var actual = WhenTheSecurityPolicy();
+        Assert.True(actual.IsError);
+    }
 
-        private void ThenNotSecurityPassing()
+    [Fact]
+    public void Should_exludeAllowedFromBlocked_moreAllowed_clientIp_not_block()
+    {
+        _context.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.150")[0];
+        GivenIpMoreAllowedThanBlocked(true);
+        GivenSetDownstreamRoute();
+        var actual = WhenTheSecurityPolicy();
+        Assert.False(actual.IsError);
+    }
+
+    [Fact]
+    public void Should_exludeAllowedFromBlocked_moreBlocked_clientIp_block()
+    {
+        _context.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.10")[0];
+        GivenIpMoreBlockedThanAllowed(false);
+        GivenSetDownstreamRoute();
+        var actual = WhenTheSecurityPolicy();
+        Assert.True(actual.IsError);
+    }
+
+    [Fact]
+    public void Should_exludeAllowedFromBlocked_moreBlocked_clientIp_not_block()
+    {
+        _context.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.10")[0];
+        GivenIpMoreBlockedThanAllowed(true);
+        GivenSetDownstreamRoute();
+        var actual = WhenTheSecurityPolicy();
+        Assert.False(actual.IsError);
+    }
+
+    [Fact]
+    [Trait("Feat", "2170")]
+    public void Should_route_config_overrides_global_config()
+    {
+        _context.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.10")[0];
+        GivenRouteConfigAndGlobalConfig(false);
+        GivenSetDownstreamRoute();
+        var actual = WhenTheSecurityPolicy();
+        Assert.False(actual.IsError);
+    }
+
+    private void GivenSetAllowedIP()
+    {
+        _downstreamRouteBuilder.WithSecurityOptions(new SecurityOptions("192.168.1.1"));
+    }
+
+    private void GivenSetBlockedIP()
+    {
+        _downstreamRouteBuilder.WithSecurityOptions(new SecurityOptions(blocked: "192.168.1.1"));
+    }
+
+    private void GivenSetDownstreamRoute()
+    {
+        _context.Items.UpsertDownstreamRoute(_downstreamRouteBuilder.Build());
+    }
+
+    private void GivenCidr24AllowedIP()
+    {
+        var securityOptions = _securityOptionsCreator.Create(new FileSecurityOptions("192.168.1.0/24"), Empty);
+        _downstreamRouteBuilder.WithSecurityOptions(securityOptions);
+    }
+
+    private void GivenCidr29AllowedIP()
+    {
+        var securityOptions = _securityOptionsCreator.Create(new FileSecurityOptions("192.168.1.0/29"), Empty);
+        _downstreamRouteBuilder.WithSecurityOptions(securityOptions);
+    }
+
+    private void GivenCidr24BlockedIP()
+    {
+        var securityOptions = _securityOptionsCreator.Create(new FileSecurityOptions(blockedIPs: "192.168.1.0/24"), Empty);
+        _downstreamRouteBuilder.WithSecurityOptions(securityOptions);
+    }
+
+    private void GivenRangeAllowedIP()
+    {
+        var securityOptions = _securityOptionsCreator.Create(new FileSecurityOptions("192.168.1.0-192.168.1.10"), Empty);
+        _downstreamRouteBuilder.WithSecurityOptions(securityOptions);
+    }
+
+    private void GivenRangeBlockedIP()
+    {
+        var securityOptions = _securityOptionsCreator.Create(new FileSecurityOptions(blockedIPs: "192.168.1.0-192.168.1.10"), Empty);
+        _downstreamRouteBuilder.WithSecurityOptions(securityOptions);
+    }
+
+    private void GivenShortRangeAllowedIP()
+    {
+        var securityOptions = _securityOptionsCreator.Create(new FileSecurityOptions("192.168.1.0-10"), Empty);
+        _downstreamRouteBuilder.WithSecurityOptions(securityOptions);
+    }
+
+    private void GivenShortRangeBlockedIP()
+    {
+        var securityOptions = _securityOptionsCreator.Create(new FileSecurityOptions(blockedIPs: "192.168.1.0-10"), Empty);
+        _downstreamRouteBuilder.WithSecurityOptions(securityOptions);
+    }
+
+    private void GivenIpSubnetAllowedIP()
+    {
+        var securityOptions = _securityOptionsCreator.Create(new FileSecurityOptions("192.168.1.0/255.255.255.0"), Empty);
+        _downstreamRouteBuilder.WithSecurityOptions(securityOptions);
+    }
+
+    private void GivenIpSubnetBlockedIP()
+    {
+        var securityOptions = _securityOptionsCreator.Create(new FileSecurityOptions(blockedIPs: "192.168.1.0/255.255.255.0"), Empty);
+        _downstreamRouteBuilder.WithSecurityOptions(securityOptions);
+    }
+
+    private void GivenIpMoreAllowedThanBlocked(bool excludeAllowedInBlocked)
+    {
+        var securityOptions = _securityOptionsCreator.Create(new FileSecurityOptions("192.168.0.0/255.255.0.0", "192.168.1.100-200", excludeAllowedInBlocked), Empty);
+        _downstreamRouteBuilder.WithSecurityOptions(securityOptions);
+    }
+
+    private void GivenIpMoreBlockedThanAllowed(bool excludeAllowedInBlocked)
+    {
+        var securityOptions = _securityOptionsCreator.Create(new FileSecurityOptions("192.168.1.10-20", "192.168.1.0/23", excludeAllowedInBlocked), Empty);
+        _downstreamRouteBuilder.WithSecurityOptions(securityOptions);
+    }
+
+    private void GivenRouteConfigAndGlobalConfig(bool excludeAllowedInBlocked)
+    {
+        var globalConfig = new FileGlobalConfiguration
         {
-            Assert.True(response.IsError);
-        }
+            SecurityOptions = new FileSecurityOptions("192.168.1.30-50", "192.168.1.1-100", true),
+        };
+        
+        var localConfig = new FileSecurityOptions("192.168.1.10", "", excludeAllowedInBlocked);
+
+        var securityOptions = _securityOptionsCreator.Create(localConfig, globalConfig);
+        _downstreamRouteBuilder.WithSecurityOptions(securityOptions);
+    }
+
+    private Response WhenTheSecurityPolicy()
+    {
+        return _policy.Security(_context.Items.DownstreamRoute(), _context);
     }
 }
diff --git a/test/Ocelot.UnitTests/Security/SecurityMiddlewareTests.cs b/test/Ocelot.UnitTests/Security/SecurityMiddlewareTests.cs
index 9f493391c..60818f015 100644
--- a/test/Ocelot.UnitTests/Security/SecurityMiddlewareTests.cs
+++ b/test/Ocelot.UnitTests/Security/SecurityMiddlewareTests.cs
@@ -7,83 +7,84 @@
 using Ocelot.Security;
 using Ocelot.Security.Middleware;
 
-namespace Ocelot.UnitTests.Security
+namespace Ocelot.UnitTests.Security;
+
+public sealed class SecurityMiddlewareTests : UnitTest
 {
-    public class SecurityMiddlewareTests : UnitTest
-    {
-        private readonly List<Mock<ISecurityPolicy>> _securityPolicyList;
-        private readonly Mock<IOcelotLoggerFactory> _loggerFactory;
-        private readonly Mock<IOcelotLogger> _logger;
-        private readonly SecurityMiddleware _middleware;
-        private readonly RequestDelegate _next;
-        private readonly HttpContext _httpContext;
+    private readonly List<Mock<ISecurityPolicy>> _securityPolicyList;
+    private readonly Mock<IOcelotLoggerFactory> _loggerFactory;
+    private readonly Mock<IOcelotLogger> _logger;
+    private readonly SecurityMiddleware _middleware;
+    private readonly RequestDelegate _next;
+    private readonly HttpContext _httpContext;
 
-        public SecurityMiddlewareTests()
+    public SecurityMiddlewareTests()
+    {
+        _httpContext = new DefaultHttpContext();
+        _loggerFactory = new Mock<IOcelotLoggerFactory>();
+        _logger = new Mock<IOcelotLogger>();
+        _loggerFactory.Setup(x => x.CreateLogger<SecurityMiddleware>()).Returns(_logger.Object);
+        _securityPolicyList = new List<Mock<ISecurityPolicy>>
         {
-            _httpContext = new DefaultHttpContext();
-            _loggerFactory = new Mock<IOcelotLoggerFactory>();
-            _logger = new Mock<IOcelotLogger>();
-            _loggerFactory.Setup(x => x.CreateLogger<SecurityMiddleware>()).Returns(_logger.Object);
-            _securityPolicyList = new List<Mock<ISecurityPolicy>>
-            {
-                new(),
-                new(),
-            };
-            _next = context => Task.CompletedTask;
-            _middleware = new SecurityMiddleware(_next, _loggerFactory.Object, _securityPolicyList.Select(f => f.Object).ToList());
-            _httpContext.Items.UpsertDownstreamRequest(new DownstreamRequest(new HttpRequestMessage(HttpMethod.Get, "http://test.com")));
-        }
+            new(),
+            new(),
+        };
+        _next = context => Task.CompletedTask;
+        _middleware = new SecurityMiddleware(_next, _loggerFactory.Object, _securityPolicyList.Select(f => f.Object).ToList());
+        _httpContext.Items.UpsertDownstreamRequest(new DownstreamRequest(new HttpRequestMessage(HttpMethod.Get, "http://test.com")));
+    }
 
-        [Fact]
-        public void Should_legal_request()
-        {
-            this.Given(x => x.GivenPassingSecurityVerification())
-                .When(x => x.WhenICallTheMiddleware())
-                .Then(x => x.ThenTheRequestIsPassingSecurity())
-                .BDDfy();
-        }
+    [Fact]
+    public async Task Should_legal_request()
+    {
+        // Arrange
+        GivenPassingSecurityVerification();
+
+        // Act
+        await _middleware.Invoke(_httpContext);
+
+        // Assert: security passed
+        _httpContext.Items.Errors().Count.ShouldBe(0);
+    }
+
+    [Fact]
+    public async Task Should_verification_failed_request()
+    {
+        // Arrange
+        GivenNotPassingSecurityVerification();
 
-        [Fact]
-        public void Should_verification_failed_request()
+        // Act
+        await _middleware.Invoke(_httpContext);
+
+        // Assert: security not passed
+        _httpContext.Items.Errors().Count.ShouldBeGreaterThan(0);
+    }
+
+    private void GivenPassingSecurityVerification()
+    {
+        foreach (var item in _securityPolicyList)
         {
-            this.Given(x => x.GivenNotPassingSecurityVerification())
-                .When(x => x.WhenICallTheMiddleware())
-                .Then(x => x.ThenTheRequestIsNotPassingSecurity())
-                .BDDfy();
+            Response response = new OkResponse();
+            item.Setup(x => x.Security(_httpContext.Items.DownstreamRoute(), _httpContext)).Returns(response);
         }
+    }
 
-        private void GivenPassingSecurityVerification()
+    private void GivenNotPassingSecurityVerification()
+    {
+        for (var i = 0; i < _securityPolicyList.Count; i++)
         {
-            foreach (var item in _securityPolicyList)
+            var item = _securityPolicyList[i];
+            if (i == 0)
             {
-                Response response = new OkResponse();
-                item.Setup(x => x.Security(_httpContext.Items.DownstreamRoute(), _httpContext)).Returns(Task.FromResult(response));
+                Error error = new UnauthenticatedError("Not passing security verification");
+                Response response = new ErrorResponse(error);
+                item.Setup(x => x.Security(_httpContext.Items.DownstreamRoute(), _httpContext)).Returns(response);
             }
-        }
-
-        private void GivenNotPassingSecurityVerification()
-        {
-            for (var i = 0; i < _securityPolicyList.Count; i++)
+            else
             {
-                var item = _securityPolicyList[i];
-                if (i == 0)
-                {
-                    Error error = new UnauthenticatedError("Not passing security verification");
-                    Response response = new ErrorResponse(error);
-                    item.Setup(x => x.Security(_httpContext.Items.DownstreamRoute(), _httpContext)).Returns(Task.FromResult(response));
-                }
-                else
-                {
-                    Response response = new OkResponse();
-                    item.Setup(x => x.Security(_httpContext.Items.DownstreamRoute(), _httpContext)).Returns(Task.FromResult(response));
-                }
+                Response response = new OkResponse();
+                item.Setup(x => x.Security(_httpContext.Items.DownstreamRoute(), _httpContext)).Returns(response);
             }
         }
-
-        private Task WhenICallTheMiddleware() => _middleware.Invoke(_httpContext);
-
-        private void ThenTheRequestIsPassingSecurity() => _httpContext.Items.Errors().Count.ShouldBe(0);
-
-        private void ThenTheRequestIsNotPassingSecurity() => _httpContext.Items.Errors().Count.ShouldBeGreaterThan(0);
     }
 }