@@ -15,6 +15,7 @@ A flexible and lightweight API key authentication library for ASP.NET Core appli
1515- [ Installation] ( #installation )
1616- [ How to Pass API Keys] ( #how-to-pass-api-keys )
1717- [ Configuration] ( #configuration )
18+ - [ IP Address Whitelisting] ( #ip-address-whitelisting )
1819- [ Usage Patterns] ( #usage-patterns )
1920- [ Advanced Customization] ( #advanced-customization )
2021- [ OpenAPI/Swagger Integration] ( #openapiswagger-integration )
@@ -30,18 +31,14 @@ AspNetCore.SecurityKey provides a complete API key authentication solution for A
3031
3132** Key Features:**
3233
33- - 🔑 ** Multiple Input Sources** - API keys via headers, query parameters, or cookies
34- - 🛡️ ** Flexible Authentication** - Works with ASP.NET Core's built-in authentication or as standalone middleware
35- - 🔧 ** Extensible Design** - Custom validation and extraction logic support
36- - 📝 ** Rich Integration** - Controller attributes, middleware, and minimal API support
37- - 📖 ** OpenAPI Support** - Automatic Swagger/OpenAPI documentation generation (.NET 9+)
38- - ⚡ ** High Performance** - Minimal overhead with optional caching
39- - 🏗️ ** Multiple Deployment Patterns** - Attribute-based, middleware, or endpoint filters
40-
41- ** Supported Frameworks:**
42-
43- - .NET 8.0+
44- - ASP.NET Core 8.0+
34+ - ** Multiple Input Sources** - API keys via headers, query parameters, or cookies
35+ - ** Flexible Authentication** - Works with ASP.NET Core's built-in authentication or as standalone middleware
36+ - ** IP Address Whitelisting** - Restrict API access by IP addresses and network ranges (IPv4 and IPv6)
37+ - ** Extensible Design** - Custom validation and extraction logic support
38+ - ** Rich Integration** - Controller attributes, middleware, and minimal API support
39+ - ** OpenAPI Support** - Automatic Swagger/OpenAPI documentation generation (.NET 9+)
40+ - ** High Performance** - Minimal overhead with optional caching and timing-attack protection
41+ - ** Multiple Deployment Patterns** - Attribute-based, middleware, or endpoint filters
4542
4643## Quick Start
4744
@@ -151,6 +148,34 @@ Support multiple valid API keys using semicolon separation:
151148}
152149```
153150
151+ ### Enhanced Configuration Format
152+
153+ For advanced scenarios with IP whitelisting and multiple keys, use the enhanced configuration format:
154+
155+ ``` json
156+ {
157+ "SecurityKey" : {
158+ "AllowedKeys" : [
159+ " 01HSGVBGWXWDWTFGTJSYFXXDXQ" ,
160+ " 01HSGVBSF99SK6XMJQJYF0X3WQ" ,
161+ " 01HSGVAH2M5WVQYG4YPT7FNK4K8"
162+ ],
163+ "AllowedAddresses" : [
164+ " 192.168.1.100" ,
165+ " 10.0.0.1" ,
166+ " 203.0.113.50" ,
167+ " ::1"
168+ ],
169+ "AllowedNetworks" : [
170+ " 192.168.0.0/16" ,
171+ " 10.0.0.0/8" ,
172+ " 172.16.0.0/12" ,
173+ " 2001:db8::/32"
174+ ]
175+ }
176+ }
177+ ```
178+
154179### Advanced Options
155180
156181Customize key extraction and validation behavior:
@@ -185,6 +210,107 @@ builder.Services.AddSecurityKey(options =>
185210});
186211```
187212
213+ ## IP Address Whitelisting
214+
215+ AspNetCore.SecurityKey provides built-in IP address whitelisting capabilities to restrict API access based on client IP addresses. This feature supports both IPv4 and IPv6 addresses, individual IPs, and network ranges using CIDR notation.
216+
217+ ### Configuration
218+
219+ IP whitelisting is configured using the enhanced configuration format in ` appsettings.json ` :
220+
221+ ``` json
222+ {
223+ "SecurityKey" : {
224+ "AllowedKeys" : [" your-api-key-here" ],
225+ "AllowedAddresses" : [
226+ " 192.168.1.100" , // Specific IPv4 address
227+ " 10.0.0.1" , // Another IPv4 address
228+ " ::1" , // IPv6 localhost
229+ " 2001:db8::1" // Specific IPv6 address
230+ ],
231+ "AllowedNetworks" : [
232+ " 192.168.0.0/16" , // Private network range
233+ " 10.0.0.0/8" , // Class A private network
234+ " 172.16.0.0/12" , // Class B private network
235+ " 2001:db8::/32" // IPv6 network range
236+ ]
237+ }
238+ }
239+ ```
240+
241+ ### How It Works
242+
243+ 1 . ** No Restrictions** : If neither ` AllowedAddresses ` nor ` AllowedNetworks ` are configured, all IP addresses are allowed
244+ 2 . ** Address Matching** : Client IP is checked against the ` AllowedAddresses ` list for exact matches
245+ 3 . ** Network Matching** : Client IP is checked against the ` AllowedNetworks ` list using CIDR notation
246+ 4 . ** Combined Logic** : A request is allowed if the IP matches either an allowed address OR falls within an allowed network
247+
248+ ### Common Use Cases
249+
250+ #### Development Environment
251+ Allow only local development machines:
252+
253+ ``` json
254+ {
255+ "SecurityKey" : {
256+ "AllowedKeys" : [" dev-key-123" ],
257+ "AllowedAddresses" : [
258+ " 127.0.0.1" , // IPv4 localhost
259+ " ::1" // IPv6 localhost
260+ ],
261+ "AllowedNetworks" : [
262+ " 192.168.0.0/16" // Local network
263+ ]
264+ }
265+ }
266+ ```
267+
268+ #### Corporate Environment
269+ Allow only internal corporate networks:
270+
271+ ``` json
272+ {
273+ "SecurityKey" : {
274+ "AllowedKeys" : [" corporate-api-key" ],
275+ "AllowedNetworks" : [
276+ " 10.0.0.0/8" , // Corporate internal network
277+ " 172.16.0.0/12" , // Secondary corporate network
278+ " 203.0.113.0/24" // Public-facing servers
279+ ]
280+ }
281+ }
282+ ```
283+
284+
285+ ### Reverse Proxy Considerations
286+
287+ When running behind a reverse proxy (like nginx, IIS, or cloud load balancers), ensure proper configuration to get the real client IP:
288+
289+ ``` csharp
290+ // Configure forwarded headers
291+ builder .Services .Configure <ForwardedHeadersOptions >(options =>
292+ {
293+ options .ForwardedHeaders = ForwardedHeaders .XForwardedFor | ForwardedHeaders .XForwardedProto ;
294+ options .KnownProxies .Clear ();
295+ options .KnownNetworks .Clear ();
296+ });
297+
298+ var app = builder .Build ();
299+
300+ // Use forwarded headers before SecurityKey middleware
301+ app .UseForwardedHeaders ();
302+ app .UseSecurityKey ();
303+ ```
304+
305+ ### Security Considerations
306+
307+ 1 . ** Combine with HTTPS** : IP whitelisting should always be combined with HTTPS to prevent man-in-the-middle attacks
308+ 2 . ** Network Ranges** : Be careful with broad network ranges like ` 0.0.0.0/0 ` or ` ::/0 ` as they allow all addresses
309+ 3 . ** Dynamic IPs** : Consider that client IPs may change, especially for mobile clients or users behind NAT
310+ 4 . ** Proxy Headers** : Validate that your reverse proxy configuration correctly forwards real client IPs
311+ 5 . ** Logging** : Monitor failed authentication attempts to detect potential security issues
312+
313+
188314## Usage Patterns
189315
190316AspNetCore.SecurityKey supports multiple integration patterns to fit different application architectures and security requirements.
@@ -333,7 +459,7 @@ public class DatabaseSecurityKeyValidator : ISecurityKeyValidator
333459 _logger = logger ;
334460 }
335461
336- public async ValueTask <bool > Validate (string ? value , CancellationToken cancellationToken = default )
462+ public async ValueTask <bool > Validate (string ? value , IPAddress ? ipAddress = null , CancellationToken cancellationToken = default )
337463 {
338464 if (string .IsNullOrEmpty (value ))
339465 return false ;
@@ -354,6 +480,13 @@ public class DatabaseSecurityKeyValidator : ISecurityKeyValidator
354480 return false ;
355481 }
356482
483+ // Validate IP address if restrictions are configured
484+ if (! IsIpAddressAllowed (ipAddress , apiKey .AllowedIpAddresses , apiKey .AllowedNetworks ))
485+ {
486+ _logger .LogWarning (" API key {Key} used from unauthorized IP: {IpAddress}" , value , ipAddress );
487+ return false ;
488+ }
489+
357490 // Update last used timestamp
358491 await _repository .UpdateLastUsedAsync (value , DateTime .UtcNow , cancellationToken );
359492
@@ -366,7 +499,7 @@ public class DatabaseSecurityKeyValidator : ISecurityKeyValidator
366499 }
367500 }
368501
369- public async ValueTask <ClaimsIdentity > Authenticate (string ? value , CancellationToken cancellationToken = default )
502+ public async ValueTask <ClaimsIdentity > Authenticate (string ? value , IPAddress ? ipAddress = null , CancellationToken cancellationToken = default )
370503 {
371504 if (string .IsNullOrEmpty (value ))
372505 return new ClaimsIdentity ();
@@ -387,6 +520,12 @@ public class DatabaseSecurityKeyValidator : ISecurityKeyValidator
387520
388521 return identity ;
389522 }
523+
524+ private bool IsIpAddressAllowed (IPAddress ? ipAddress , string []? allowedAddresses , string []? allowedNetworks )
525+ {
526+ // Use the built-in whitelist functionality
527+ return SecurityKeyWhitelist .IsIpAllowed (ipAddress , allowedAddresses , allowedNetworks );
528+ }
390529}
391530
392531// Register custom validator
@@ -567,6 +706,21 @@ The `SecurityKeyDocumentTransformer` automatically configures the OpenAPI specif
5677062 . ** Key Rotation** : Implement regular API key rotation policies
5687073 . ** Logging** : Log authentication attempts without exposing the actual keys
5697084 . ** Rate Limiting** : Implement rate limiting to prevent abuse
709+ 5 . ** IP Whitelisting** : Use IP restrictions for additional security when possible
710+ 6 . ** Timing Attack Protection** : The library uses cryptographic operations to prevent timing attacks
711+
712+ ### Configuration Best Practices
713+
714+ 1 . ** Environment Variables** : Store sensitive keys in environment variables or secure key vaults
715+ 2 . ** Separate Keys** : Use different API keys for different environments (dev, staging, production)
716+ 3 . ** Network Restrictions** : Configure IP whitelisting to restrict access to known sources
717+ 4 . ** Monitor Usage** : Implement logging and monitoring to track API key usage patterns
718+
719+ ### Performance Considerations
720+
721+ 1 . ** Caching** : Enable caching for authentication results when using custom validators
722+ 2 . ** Connection Pooling** : Use connection pooling for database-backed validators
723+ 3 . ** Async Operations** : Leverage async/await patterns for I/O operations
570724
571725## Troubleshooting
572726
@@ -609,6 +763,22 @@ builder.Services.AddScoped<IApiKeyRepository, ApiKeyRepository>();
609763builder .Services .AddSecurityKey <CustomValidator >();
610764```
611765
766+ ** Issue** : IP whitelisting not working correctly
767+
768+ ** Solution** : Check reverse proxy configuration and enable debug logging:
769+
770+ ``` csharp
771+ // Configure forwarded headers
772+ builder .Services .Configure <ForwardedHeadersOptions >(options =>
773+ {
774+ options .ForwardedHeaders = ForwardedHeaders .XForwardedFor | ForwardedHeaders .XForwardedProto ;
775+ });
776+
777+ var app = builder .Build ();
778+ app .UseForwardedHeaders (); // Must be before UseSecurityKey()
779+ app .UseSecurityKey ();
780+ ```
781+
612782### Debug Logging
613783
614784Enable detailed logging to troubleshoot issues:
@@ -630,7 +800,7 @@ For complete working examples, see the samples in this repository:
630800
631801- ** [ Sample.Controllers] ( samples/Sample.Controllers/ ) ** - Controller-based API with attribute security
632802- ** [ Sample.Middleware] ( samples/Sample.Middleware/ ) ** - Middleware-based global security
633- - ** [ Sample.MinimalApi] ( samples/Sample.MinimalApi/ ) ** - Minimal APIs with endpoint filters
803+ - ** [ Sample.MinimalApi] ( samples/Sample.MinimalApi/ ) ** - Minimal APIs with endpoint filters and IP whitelisting
634804
635805Each sample includes:
636806
0 commit comments