mcp-security-framework 1.1.0__py3-none-any.whl → 1.1.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. mcp_security_framework/__init__.py +26 -15
  2. mcp_security_framework/cli/__init__.py +1 -1
  3. mcp_security_framework/cli/cert_cli.py +233 -197
  4. mcp_security_framework/cli/security_cli.py +324 -234
  5. mcp_security_framework/constants.py +21 -27
  6. mcp_security_framework/core/auth_manager.py +41 -22
  7. mcp_security_framework/core/cert_manager.py +210 -147
  8. mcp_security_framework/core/permission_manager.py +9 -9
  9. mcp_security_framework/core/rate_limiter.py +2 -2
  10. mcp_security_framework/core/security_manager.py +284 -229
  11. mcp_security_framework/examples/__init__.py +6 -0
  12. mcp_security_framework/examples/comprehensive_example.py +349 -279
  13. mcp_security_framework/examples/django_example.py +247 -206
  14. mcp_security_framework/examples/fastapi_example.py +315 -283
  15. mcp_security_framework/examples/flask_example.py +274 -203
  16. mcp_security_framework/examples/gateway_example.py +304 -237
  17. mcp_security_framework/examples/microservice_example.py +258 -189
  18. mcp_security_framework/examples/standalone_example.py +255 -230
  19. mcp_security_framework/examples/test_all_examples.py +151 -135
  20. mcp_security_framework/middleware/__init__.py +46 -55
  21. mcp_security_framework/middleware/auth_middleware.py +62 -63
  22. mcp_security_framework/middleware/fastapi_auth_middleware.py +119 -118
  23. mcp_security_framework/middleware/fastapi_middleware.py +156 -148
  24. mcp_security_framework/middleware/flask_auth_middleware.py +160 -147
  25. mcp_security_framework/middleware/flask_middleware.py +183 -157
  26. mcp_security_framework/middleware/mtls_middleware.py +106 -117
  27. mcp_security_framework/middleware/rate_limit_middleware.py +105 -101
  28. mcp_security_framework/middleware/security_middleware.py +109 -124
  29. mcp_security_framework/schemas/config.py +2 -1
  30. mcp_security_framework/schemas/models.py +18 -6
  31. mcp_security_framework/utils/cert_utils.py +14 -8
  32. mcp_security_framework/utils/datetime_compat.py +116 -0
  33. {mcp_security_framework-1.1.0.dist-info → mcp_security_framework-1.1.1.dist-info}/METADATA +2 -1
  34. mcp_security_framework-1.1.1.dist-info/RECORD +84 -0
  35. tests/conftest.py +63 -66
  36. tests/test_cli/test_cert_cli.py +184 -146
  37. tests/test_cli/test_security_cli.py +274 -247
  38. tests/test_core/test_cert_manager.py +24 -10
  39. tests/test_core/test_security_manager.py +2 -2
  40. tests/test_examples/test_comprehensive_example.py +190 -137
  41. tests/test_examples/test_fastapi_example.py +124 -101
  42. tests/test_examples/test_flask_example.py +124 -101
  43. tests/test_examples/test_standalone_example.py +73 -80
  44. tests/test_integration/test_auth_flow.py +213 -197
  45. tests/test_integration/test_certificate_flow.py +180 -149
  46. tests/test_integration/test_fastapi_integration.py +108 -111
  47. tests/test_integration/test_flask_integration.py +141 -140
  48. tests/test_integration/test_standalone_integration.py +290 -259
  49. tests/test_middleware/test_fastapi_auth_middleware.py +195 -174
  50. tests/test_middleware/test_fastapi_middleware.py +147 -132
  51. tests/test_middleware/test_flask_auth_middleware.py +260 -202
  52. tests/test_middleware/test_flask_middleware.py +201 -179
  53. tests/test_middleware/test_security_middleware.py +145 -130
  54. tests/test_utils/test_datetime_compat.py +147 -0
  55. mcp_security_framework-1.1.0.dist-info/RECORD +0 -82
  56. {mcp_security_framework-1.1.0.dist-info → mcp_security_framework-1.1.1.dist-info}/WHEEL +0 -0
  57. {mcp_security_framework-1.1.0.dist-info → mcp_security_framework-1.1.1.dist-info}/entry_points.txt +0 -0
  58. {mcp_security_framework-1.1.0.dist-info → mcp_security_framework-1.1.1.dist-info}/top_level.txt +0 -0
@@ -26,16 +26,22 @@ import json
26
26
  import logging
27
27
  from typing import Any, Dict, List, Optional, Union
28
28
 
29
- from fastapi import Request, Response, HTTPException, status
29
+ from fastapi import HTTPException, Request, Response, status
30
30
  from fastapi.responses import JSONResponse
31
31
 
32
+ from ..schemas.models import (
33
+ AuthMethod,
34
+ AuthResult,
35
+ AuthStatus,
36
+ ValidationResult,
37
+ ValidationStatus,
38
+ )
32
39
  from .security_middleware import SecurityMiddleware, SecurityMiddlewareError
33
- from ..schemas.models import AuthResult, AuthStatus, AuthMethod, ValidationResult, ValidationStatus
34
40
 
35
41
 
36
42
  class FastAPIMiddlewareError(SecurityMiddlewareError):
37
43
  """Raised when FastAPI middleware encounters an error."""
38
-
44
+
39
45
  def __init__(self, message: str, error_code: int = -32008):
40
46
  self.message = message
41
47
  self.error_code = error_code
@@ -45,11 +51,11 @@ class FastAPIMiddlewareError(SecurityMiddlewareError):
45
51
  class FastAPISecurityMiddleware(SecurityMiddleware):
46
52
  """
47
53
  FastAPI Security Middleware Class
48
-
54
+
49
55
  This class provides FastAPI-specific implementation of the security
50
56
  middleware. It integrates with FastAPI's middleware system and
51
57
  handles FastAPI Request/Response objects.
52
-
58
+
53
59
  The FastAPISecurityMiddleware implements:
54
60
  - FastAPI-specific request processing
55
61
  - FastAPI authentication method handling
@@ -57,7 +63,7 @@ class FastAPISecurityMiddleware(SecurityMiddleware):
57
63
  - FastAPI-specific error handling
58
64
  - FastAPI header management
59
65
  - FastAPI rate limiting integration
60
-
66
+
61
67
  Key Responsibilities:
62
68
  - Process FastAPI requests through security pipeline
63
69
  - Extract authentication credentials from FastAPI requests
@@ -65,20 +71,20 @@ class FastAPISecurityMiddleware(SecurityMiddleware):
65
71
  - Add security headers to FastAPI responses
66
72
  - Handle FastAPI-specific request/response objects
67
73
  - Integrate with FastAPI middleware system
68
-
74
+
69
75
  Attributes:
70
76
  Inherits all attributes from SecurityMiddleware
71
77
  _fastapi_app: Reference to FastAPI application (if available)
72
-
78
+
73
79
  Example:
74
80
  >>> from fastapi import FastAPI
75
81
  >>> from mcp_security_framework.middleware import FastAPISecurityMiddleware
76
- >>>
82
+ >>>
77
83
  >>> app = FastAPI()
78
84
  >>> security_manager = SecurityManager(config)
79
85
  >>> middleware = FastAPISecurityMiddleware(security_manager)
80
86
  >>> app.add_middleware(middleware)
81
-
87
+
82
88
  Note:
83
89
  This middleware should be added to FastAPI applications using
84
90
  the add_middleware method or as a dependency.
@@ -98,28 +104,28 @@ class FastAPISecurityMiddleware(SecurityMiddleware):
98
104
  """
99
105
  if security_manager is None:
100
106
  raise FastAPIMiddlewareError("Security manager is required")
101
-
107
+
102
108
  super().__init__(security_manager)
103
109
  self.logger = logging.getLogger(f"{__name__}.{self.__class__.__name__}")
104
110
  self.app = app
105
-
111
+
106
112
  self.logger.info("FastAPI Security Middleware initialized")
107
-
113
+
108
114
  async def __call__(self, request: Request, call_next):
109
115
  """
110
116
  Process FastAPI request through security middleware.
111
-
117
+
112
118
  This method implements the security processing pipeline for
113
119
  FastAPI requests, including rate limiting, authentication,
114
120
  authorization, and security header management.
115
-
121
+
116
122
  Args:
117
123
  request (Request): FastAPI request object
118
124
  call_next: FastAPI call_next function
119
-
125
+
120
126
  Returns:
121
127
  Response: FastAPI response object
122
-
128
+
123
129
  Raises:
124
130
  HTTPException: For security violations (rate limit, auth, permissions)
125
131
  FastAPIMiddlewareError: For middleware processing errors
@@ -130,35 +136,38 @@ class FastAPISecurityMiddleware(SecurityMiddleware):
130
136
  response = await call_next(request)
131
137
  self._add_security_headers(response)
132
138
  return response
133
-
139
+
134
140
  # Check rate limit
135
141
  if not self._check_rate_limit(request):
136
142
  return self._rate_limit_response()
137
-
143
+
138
144
  # Authenticate request
139
145
  auth_result = await self._authenticate_request(request)
140
146
  if not auth_result.is_valid:
141
147
  return self._auth_error_response(auth_result)
142
-
148
+
143
149
  # Validate permissions
144
150
  if not self._validate_permissions(request, auth_result):
145
151
  return self._permission_error_response()
146
-
152
+
147
153
  # Process request
148
154
  response = await call_next(request)
149
155
  self._add_security_headers(response)
150
-
156
+
151
157
  # Log successful request
152
- self._log_security_event("request_processed", {
153
- "ip_address": self._get_client_ip(request),
154
- "username": auth_result.username,
155
- "path": str(request.url.path),
156
- "method": request.method,
157
- "status_code": response.status_code
158
- })
159
-
158
+ self._log_security_event(
159
+ "request_processed",
160
+ {
161
+ "ip_address": self._get_client_ip(request),
162
+ "username": auth_result.username,
163
+ "path": str(request.url.path),
164
+ "method": request.method,
165
+ "status_code": response.status_code,
166
+ },
167
+ )
168
+
160
169
  return response
161
-
170
+
162
171
  except HTTPException:
163
172
  # Re-raise FastAPI HTTP exceptions
164
173
  raise
@@ -166,11 +175,10 @@ class FastAPISecurityMiddleware(SecurityMiddleware):
166
175
  self.logger.error(
167
176
  "FastAPI middleware processing failed",
168
177
  extra={"error": str(e)},
169
- exc_info=True
178
+ exc_info=True,
170
179
  )
171
180
  raise FastAPIMiddlewareError(
172
- f"Middleware processing failed: {str(e)}",
173
- error_code=-32009
181
+ f"Middleware processing failed: {str(e)}", error_code=-32009
174
182
  )
175
183
 
176
184
  def _check_rate_limit(self, request: Request) -> bool:
@@ -201,7 +209,7 @@ class FastAPISecurityMiddleware(SecurityMiddleware):
201
209
  status=AuthStatus.INVALID,
202
210
  auth_method="unknown",
203
211
  error_code=-32001,
204
- error_message="Authentication required"
212
+ error_message="Authentication required",
205
213
  )
206
214
 
207
215
  def _validate_permissions(self, request: Request, auth_result: AuthResult) -> bool:
@@ -224,8 +232,8 @@ class FastAPISecurityMiddleware(SecurityMiddleware):
224
232
  content={
225
233
  "error": "Rate limit exceeded",
226
234
  "error_code": -32010,
227
- "retry_after": 60
228
- }
235
+ "retry_after": 60,
236
+ },
229
237
  )
230
238
 
231
239
  def _auth_error_response(self, auth_result: AuthResult) -> JSONResponse:
@@ -235,8 +243,8 @@ class FastAPISecurityMiddleware(SecurityMiddleware):
235
243
  content={
236
244
  "error": "Authentication failed",
237
245
  "error_code": auth_result.error_code,
238
- "error_message": auth_result.error_message
239
- }
246
+ "error_message": auth_result.error_message,
247
+ },
240
248
  )
241
249
 
242
250
  def _permission_error_response(self) -> JSONResponse:
@@ -246,8 +254,8 @@ class FastAPISecurityMiddleware(SecurityMiddleware):
246
254
  content={
247
255
  "error": "Permission denied",
248
256
  "error_code": -32004,
249
- "error_message": "Insufficient permissions"
250
- }
257
+ "error_message": "Insufficient permissions",
258
+ },
251
259
  )
252
260
 
253
261
  def _add_security_headers(self, response: Response) -> None:
@@ -255,14 +263,13 @@ class FastAPISecurityMiddleware(SecurityMiddleware):
255
263
  response.headers["X-Content-Type-Options"] = "nosniff"
256
264
  response.headers["X-Frame-Options"] = "DENY"
257
265
  response.headers["X-XSS-Protection"] = "1; mode=block"
258
- response.headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains"
266
+ response.headers["Strict-Transport-Security"] = (
267
+ "max-age=31536000; includeSubDomains"
268
+ )
259
269
 
260
270
  def _log_security_event(self, event_type: str, data: Dict[str, Any]) -> None:
261
271
  """Log security event."""
262
- self.logger.info(
263
- f"Security event: {event_type}",
264
- extra=data
265
- )
272
+ self.logger.info(f"Security event: {event_type}", extra=data)
266
273
 
267
274
  def _get_required_permissions_from_state(self, request: Request) -> List[str]:
268
275
  """Get required permissions from request state."""
@@ -278,7 +285,7 @@ class FastAPISecurityMiddleware(SecurityMiddleware):
278
285
  "POST": ["write"],
279
286
  "PUT": ["write"],
280
287
  "DELETE": ["delete"],
281
- "PATCH": ["write"]
288
+ "PATCH": ["write"],
282
289
  }
283
290
  return method_permissions.get(request.method, [])
284
291
 
@@ -300,7 +307,7 @@ class FastAPISecurityMiddleware(SecurityMiddleware):
300
307
  status=AuthStatus.INVALID,
301
308
  auth_method="api_key",
302
309
  error_code=-32001,
303
- error_message="API key not provided"
310
+ error_message="API key not provided",
304
311
  )
305
312
 
306
313
  def _try_jwt_auth(self, request: Request) -> AuthResult:
@@ -312,7 +319,7 @@ class FastAPISecurityMiddleware(SecurityMiddleware):
312
319
  status=AuthStatus.INVALID,
313
320
  auth_method="jwt",
314
321
  error_code=-32001,
315
- error_message="JWT token not provided"
322
+ error_message="JWT token not provided",
316
323
  )
317
324
 
318
325
  token = auth_header[7:] # Remove "Bearer " prefix
@@ -336,78 +343,82 @@ class FastAPISecurityMiddleware(SecurityMiddleware):
336
343
 
337
344
  # Fallback
338
345
  return "unknown"
339
-
346
+
340
347
  def _get_rate_limit_identifier(self, request: Request) -> str:
341
348
  """
342
349
  Get rate limit identifier from FastAPI request.
343
-
350
+
344
351
  This method extracts the rate limit identifier from the FastAPI
345
352
  request, typically using the client IP address.
346
-
353
+
347
354
  Args:
348
355
  request (Request): FastAPI request object
349
-
356
+
350
357
  Returns:
351
358
  str: Rate limit identifier (IP address)
352
359
  """
353
360
  return self._get_client_ip(request)
354
-
361
+
355
362
  def _get_request_path(self, request: Request) -> str:
356
363
  """
357
364
  Get request path from FastAPI request.
358
-
365
+
359
366
  Args:
360
367
  request (Request): FastAPI request object
361
-
368
+
362
369
  Returns:
363
370
  str: Request path
364
371
  """
365
372
  return str(request.url.path)
366
-
373
+
367
374
  def _get_required_permissions(self, request: Request) -> List[str]:
368
375
  """
369
376
  Get required permissions for FastAPI request.
370
-
377
+
371
378
  This method extracts required permissions from the FastAPI request,
372
379
  typically from route dependencies or request state.
373
-
380
+
374
381
  Args:
375
382
  request (Request): FastAPI request object
376
-
383
+
377
384
  Returns:
378
385
  List[str]: List of required permissions
379
386
  """
380
387
  # Try to get permissions from request state
381
- if hasattr(request.state, 'required_permissions'):
388
+ if hasattr(request.state, "required_permissions"):
382
389
  return request.state.required_permissions
383
-
390
+
384
391
  # Try to get permissions from route dependencies
385
- if hasattr(request, 'route') and hasattr(request.route, 'dependencies'):
392
+ if hasattr(request, "route") and hasattr(request.route, "dependencies"):
386
393
  # Check if route has permission dependencies
387
394
  dependencies = request.route.dependencies
388
395
  for dep in dependencies:
389
- if hasattr(dep, 'dependency') and hasattr(dep.dependency, 'required_permissions'):
396
+ if hasattr(dep, "dependency") and hasattr(
397
+ dep.dependency, "required_permissions"
398
+ ):
390
399
  return dep.dependency.required_permissions
391
400
  # Check for permission decorators
392
- if hasattr(dep, 'dependency') and hasattr(dep.dependency, '__permissions__'):
401
+ if hasattr(dep, "dependency") and hasattr(
402
+ dep.dependency, "__permissions__"
403
+ ):
393
404
  return dep.dependency.__permissions__
394
-
405
+
395
406
  # Default: no specific permissions required
396
407
  return []
397
-
408
+
398
409
  async def _authenticate_request(self, request: Request) -> AuthResult:
399
410
  """
400
411
  Authenticate the request using configured authentication methods.
401
-
412
+
402
413
  This method attempts to authenticate the request using all configured
403
414
  authentication methods in order until one succeeds.
404
-
415
+
405
416
  Args:
406
417
  request (Request): FastAPI request object
407
-
418
+
408
419
  Returns:
409
420
  AuthResult: Authentication result
410
-
421
+
411
422
  Raises:
412
423
  SecurityMiddlewareError: If authentication process fails
413
424
  """
@@ -418,9 +429,9 @@ class FastAPISecurityMiddleware(SecurityMiddleware):
418
429
  status=AuthStatus.SUCCESS,
419
430
  username="anonymous",
420
431
  roles=[],
421
- auth_method=None
432
+ auth_method=None,
422
433
  )
423
-
434
+
424
435
  # Try each authentication method in order
425
436
  for method in self.config.auth.methods:
426
437
  auth_result = await self._try_auth_method(request, method)
@@ -430,17 +441,17 @@ class FastAPISecurityMiddleware(SecurityMiddleware):
430
441
  extra={
431
442
  "username": auth_result.username,
432
443
  "auth_method": auth_result.auth_method,
433
- "user_roles": auth_result.roles
434
- }
444
+ "user_roles": auth_result.roles,
445
+ },
435
446
  )
436
447
  return auth_result
437
-
448
+
438
449
  # All authentication methods failed
439
450
  self.logger.warning(
440
451
  "All authentication methods failed",
441
- extra={"auth_methods": self.config.auth.methods}
452
+ extra={"auth_methods": self.config.auth.methods},
442
453
  )
443
-
454
+
444
455
  return AuthResult(
445
456
  is_valid=False,
446
457
  status=AuthStatus.FAILED,
@@ -448,31 +459,28 @@ class FastAPISecurityMiddleware(SecurityMiddleware):
448
459
  roles=[],
449
460
  auth_method=None,
450
461
  error_code=-32005,
451
- error_message="All authentication methods failed"
462
+ error_message="All authentication methods failed",
452
463
  )
453
-
464
+
454
465
  except Exception as e:
455
466
  self.logger.error(
456
- "Authentication process failed",
457
- extra={"error": str(e)},
458
- exc_info=True
467
+ "Authentication process failed", extra={"error": str(e)}, exc_info=True
459
468
  )
460
469
  raise SecurityMiddlewareError(
461
- f"Authentication process failed: {str(e)}",
462
- error_code=-32006
470
+ f"Authentication process failed: {str(e)}", error_code=-32006
463
471
  )
464
472
 
465
473
  async def _try_auth_method(self, request: Request, method: str) -> AuthResult:
466
474
  """
467
475
  Try authentication using specific method with FastAPI request.
468
-
476
+
469
477
  This method attempts to authenticate the FastAPI request using
470
478
  the specified authentication method.
471
-
479
+
472
480
  Args:
473
481
  request (Request): FastAPI request object
474
482
  method (str): Authentication method to try
475
-
483
+
476
484
  Returns:
477
485
  AuthResult: Authentication result
478
486
  """
@@ -493,13 +501,13 @@ class FastAPISecurityMiddleware(SecurityMiddleware):
493
501
  roles=[],
494
502
  auth_method=None,
495
503
  error_code=-32010,
496
- error_message=f"Unsupported authentication method: {method}"
504
+ error_message=f"Unsupported authentication method: {method}",
497
505
  )
498
506
  except Exception as e:
499
507
  self.logger.error(
500
508
  f"Authentication method {method} failed",
501
509
  extra={"error": str(e)},
502
- exc_info=True
510
+ exc_info=True,
503
511
  )
504
512
  return AuthResult(
505
513
  is_valid=False,
@@ -508,16 +516,16 @@ class FastAPISecurityMiddleware(SecurityMiddleware):
508
516
  roles=[],
509
517
  auth_method=None,
510
518
  error_code=-32011,
511
- error_message=f"Authentication method {method} failed: {str(e)}"
519
+ error_message=f"Authentication method {method} failed: {str(e)}",
512
520
  )
513
-
521
+
514
522
  async def _try_api_key_auth(self, request: Request) -> AuthResult:
515
523
  """
516
524
  Try API key authentication with FastAPI request.
517
-
525
+
518
526
  Args:
519
527
  request (Request): FastAPI request object
520
-
528
+
521
529
  Returns:
522
530
  AuthResult: Authentication result
523
531
  """
@@ -528,7 +536,7 @@ class FastAPISecurityMiddleware(SecurityMiddleware):
528
536
  auth_header = request.headers.get("Authorization")
529
537
  if auth_header and auth_header.startswith("Bearer "):
530
538
  api_key = auth_header[7:] # Remove "Bearer " prefix
531
-
539
+
532
540
  if not api_key:
533
541
  return AuthResult(
534
542
  is_valid=False,
@@ -537,19 +545,19 @@ class FastAPISecurityMiddleware(SecurityMiddleware):
537
545
  roles=[],
538
546
  auth_method=AuthMethod.API_KEY,
539
547
  error_code=-32012,
540
- error_message="API key not found in request"
548
+ error_message="API key not found in request",
541
549
  )
542
-
550
+
543
551
  # Authenticate using security manager
544
552
  return self.security_manager.auth_manager.authenticate_api_key(api_key)
545
-
553
+
546
554
  async def _try_jwt_auth(self, request: Request) -> AuthResult:
547
555
  """
548
556
  Try JWT authentication with FastAPI request.
549
-
557
+
550
558
  Args:
551
559
  request (Request): FastAPI request object
552
-
560
+
553
561
  Returns:
554
562
  AuthResult: Authentication result
555
563
  """
@@ -563,28 +571,28 @@ class FastAPISecurityMiddleware(SecurityMiddleware):
563
571
  roles=[],
564
572
  auth_method=AuthMethod.JWT,
565
573
  error_code=-32013,
566
- error_message="JWT token not found in Authorization header"
574
+ error_message="JWT token not found in Authorization header",
567
575
  )
568
-
576
+
569
577
  token = auth_header[7:] # Remove "Bearer " prefix
570
-
578
+
571
579
  # Authenticate using security manager
572
580
  return self.security_manager.auth_manager.authenticate_jwt_token(token)
573
-
581
+
574
582
  async def _try_certificate_auth(self, request: Request) -> AuthResult:
575
583
  """
576
584
  Try certificate authentication with FastAPI request.
577
-
585
+
578
586
  Args:
579
587
  request (Request): FastAPI request object
580
-
588
+
581
589
  Returns:
582
590
  AuthResult: Authentication result
583
591
  """
584
592
  # For certificate authentication, we would typically need
585
593
  # to access the client certificate from the SSL context
586
594
  # This is more complex and depends on the SSL configuration
587
-
595
+
588
596
  # For now, return not implemented
589
597
  return AuthResult(
590
598
  is_valid=False,
@@ -593,16 +601,16 @@ class FastAPISecurityMiddleware(SecurityMiddleware):
593
601
  roles=[],
594
602
  auth_method=AuthMethod.CERTIFICATE,
595
603
  error_code=-32014,
596
- error_message="Certificate authentication not implemented"
604
+ error_message="Certificate authentication not implemented",
597
605
  )
598
-
606
+
599
607
  async def _try_basic_auth(self, request: Request) -> AuthResult:
600
608
  """
601
609
  Try basic authentication with FastAPI request.
602
-
610
+
603
611
  Args:
604
612
  request (Request): FastAPI request object
605
-
613
+
606
614
  Returns:
607
615
  AuthResult: Authentication result
608
616
  """
@@ -616,9 +624,9 @@ class FastAPISecurityMiddleware(SecurityMiddleware):
616
624
  roles=[],
617
625
  auth_method=AuthMethod.BASIC,
618
626
  error_code=-32015,
619
- error_message="Basic authentication credentials not found"
627
+ error_message="Basic authentication credentials not found",
620
628
  )
621
-
629
+
622
630
  # Basic auth implementation would go here
623
631
  # For now, return not implemented
624
632
  return AuthResult(
@@ -628,28 +636,30 @@ class FastAPISecurityMiddleware(SecurityMiddleware):
628
636
  roles=[],
629
637
  auth_method=AuthMethod.BASIC,
630
638
  error_code=-32016,
631
- error_message="Basic authentication not implemented"
639
+ error_message="Basic authentication not implemented",
632
640
  )
633
-
634
- def _apply_security_headers(self, response: Response, headers: Dict[str, str]) -> None:
641
+
642
+ def _apply_security_headers(
643
+ self, response: Response, headers: Dict[str, str]
644
+ ) -> None:
635
645
  """
636
646
  Apply security headers to FastAPI response.
637
-
647
+
638
648
  Args:
639
649
  response (Response): FastAPI response object
640
650
  headers (Dict[str, str]): Headers to apply
641
651
  """
642
652
  for header_name, header_value in headers.items():
643
653
  response.headers[header_name] = header_value
644
-
654
+
645
655
  def _create_error_response(self, status_code: int, message: str) -> Response:
646
656
  """
647
657
  Create error response for security violations.
648
-
658
+
649
659
  Args:
650
660
  status_code (int): HTTP status code
651
661
  message (str): Error message
652
-
662
+
653
663
  Returns:
654
664
  Response: FastAPI error response
655
665
  """
@@ -658,14 +668,14 @@ class FastAPISecurityMiddleware(SecurityMiddleware):
658
668
  content={
659
669
  "error": "Security violation",
660
670
  "message": message,
661
- "error_code": -32017
662
- }
671
+ "error_code": -32017,
672
+ },
663
673
  )
664
-
674
+
665
675
  def _rate_limit_response(self) -> Response:
666
676
  """
667
677
  Create rate limit exceeded response.
668
-
678
+
669
679
  Returns:
670
680
  Response: FastAPI rate limit response
671
681
  """
@@ -674,20 +684,18 @@ class FastAPISecurityMiddleware(SecurityMiddleware):
674
684
  content={
675
685
  "error": "Rate limit exceeded",
676
686
  "message": "Too many requests, please try again later",
677
- "error_code": -32018
687
+ "error_code": -32018,
678
688
  },
679
- headers={
680
- "Retry-After": str(self.config.rate_limit.window_size_seconds)
681
- }
689
+ headers={"Retry-After": str(self.config.rate_limit.window_size_seconds)},
682
690
  )
683
-
691
+
684
692
  def _auth_error_response(self, auth_result: AuthResult) -> Response:
685
693
  """
686
694
  Create authentication error response.
687
-
695
+
688
696
  Args:
689
697
  auth_result (AuthResult): Authentication result
690
-
698
+
691
699
  Returns:
692
700
  Response: FastAPI authentication error response
693
701
  """
@@ -697,17 +705,15 @@ class FastAPISecurityMiddleware(SecurityMiddleware):
697
705
  "error": "Authentication failed",
698
706
  "message": auth_result.error_message or "Invalid credentials",
699
707
  "error_code": auth_result.error_code,
700
- "auth_method": auth_result.auth_method
708
+ "auth_method": auth_result.auth_method,
701
709
  },
702
- headers={
703
- "WWW-Authenticate": "Bearer, ApiKey"
704
- }
710
+ headers={"WWW-Authenticate": "Bearer, ApiKey"},
705
711
  )
706
-
712
+
707
713
  def _permission_error_response(self) -> Response:
708
714
  """
709
715
  Create permission denied response.
710
-
716
+
711
717
  Returns:
712
718
  Response: FastAPI permission error response
713
719
  """
@@ -716,17 +722,17 @@ class FastAPISecurityMiddleware(SecurityMiddleware):
716
722
  content={
717
723
  "error": "Permission denied",
718
724
  "message": "Insufficient permissions to access this resource",
719
- "error_code": -32019
720
- }
725
+ "error_code": -32019,
726
+ },
721
727
  )
722
-
728
+
723
729
  def _get_client_ip(self, request: Request) -> str:
724
730
  """
725
731
  Get client IP address from FastAPI request.
726
-
732
+
727
733
  Args:
728
734
  request (Request): FastAPI request object
729
-
735
+
730
736
  Returns:
731
737
  str: Client IP address
732
738
  """
@@ -735,23 +741,25 @@ class FastAPISecurityMiddleware(SecurityMiddleware):
735
741
  if forwarded_for:
736
742
  # Take the first IP in the chain
737
743
  return forwarded_for.split(",")[0].strip()
738
-
744
+
739
745
  # Try to get IP from X-Real-IP header
740
746
  real_ip = request.headers.get("X-Real-IP")
741
747
  if real_ip:
742
748
  return real_ip
743
-
749
+
744
750
  # Fall back to client host
745
751
  if request.client:
746
752
  return request.client.host
747
-
753
+
748
754
  # Default fallback
749
755
  # Fallback to default IP from config or environment
750
- default_ip = getattr(self.config, 'default_client_ip', None)
756
+ default_ip = getattr(self.config, "default_client_ip", None)
751
757
  if default_ip:
752
758
  return default_ip
753
-
759
+
754
760
  # Use environment variable or default
755
761
  import os
762
+
756
763
  from ..constants import DEFAULT_CLIENT_IP
757
- return os.environ.get('DEFAULT_CLIENT_IP', DEFAULT_CLIENT_IP)
764
+
765
+ return os.environ.get("DEFAULT_CLIENT_IP", DEFAULT_CLIENT_IP)