mcp-security-framework 0.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.
- mcp_security_framework/__init__.py +26 -15
- mcp_security_framework/cli/__init__.py +1 -1
- mcp_security_framework/cli/cert_cli.py +233 -197
- mcp_security_framework/cli/security_cli.py +324 -234
- mcp_security_framework/constants.py +21 -27
- mcp_security_framework/core/auth_manager.py +49 -20
- mcp_security_framework/core/cert_manager.py +398 -104
- mcp_security_framework/core/permission_manager.py +13 -9
- mcp_security_framework/core/rate_limiter.py +10 -0
- mcp_security_framework/core/security_manager.py +286 -229
- mcp_security_framework/examples/__init__.py +6 -0
- mcp_security_framework/examples/comprehensive_example.py +954 -0
- mcp_security_framework/examples/django_example.py +276 -202
- mcp_security_framework/examples/fastapi_example.py +897 -393
- mcp_security_framework/examples/flask_example.py +311 -200
- mcp_security_framework/examples/gateway_example.py +373 -214
- mcp_security_framework/examples/microservice_example.py +337 -172
- mcp_security_framework/examples/standalone_example.py +719 -478
- mcp_security_framework/examples/test_all_examples.py +572 -0
- mcp_security_framework/middleware/__init__.py +46 -55
- mcp_security_framework/middleware/auth_middleware.py +62 -63
- mcp_security_framework/middleware/fastapi_auth_middleware.py +179 -110
- mcp_security_framework/middleware/fastapi_middleware.py +156 -148
- mcp_security_framework/middleware/flask_auth_middleware.py +267 -107
- mcp_security_framework/middleware/flask_middleware.py +183 -157
- mcp_security_framework/middleware/mtls_middleware.py +106 -117
- mcp_security_framework/middleware/rate_limit_middleware.py +105 -101
- mcp_security_framework/middleware/security_middleware.py +109 -124
- mcp_security_framework/schemas/config.py +2 -1
- mcp_security_framework/schemas/models.py +19 -6
- mcp_security_framework/utils/cert_utils.py +14 -8
- mcp_security_framework/utils/datetime_compat.py +116 -0
- {mcp_security_framework-0.1.0.dist-info → mcp_security_framework-1.1.1.dist-info}/METADATA +2 -1
- mcp_security_framework-1.1.1.dist-info/RECORD +84 -0
- tests/conftest.py +303 -0
- tests/test_cli/test_cert_cli.py +194 -174
- tests/test_cli/test_security_cli.py +274 -247
- tests/test_core/test_cert_manager.py +33 -19
- tests/test_core/test_security_manager.py +2 -2
- tests/test_examples/test_comprehensive_example.py +613 -0
- tests/test_examples/test_fastapi_example.py +290 -169
- tests/test_examples/test_flask_example.py +304 -162
- tests/test_examples/test_standalone_example.py +106 -168
- tests/test_integration/test_auth_flow.py +214 -198
- tests/test_integration/test_certificate_flow.py +181 -150
- tests/test_integration/test_fastapi_integration.py +140 -149
- tests/test_integration/test_flask_integration.py +144 -141
- tests/test_integration/test_standalone_integration.py +331 -300
- tests/test_middleware/test_fastapi_auth_middleware.py +745 -0
- tests/test_middleware/test_fastapi_middleware.py +147 -132
- tests/test_middleware/test_flask_auth_middleware.py +696 -0
- tests/test_middleware/test_flask_middleware.py +201 -179
- tests/test_middleware/test_security_middleware.py +151 -130
- tests/test_utils/test_datetime_compat.py +147 -0
- mcp_security_framework-0.1.0.dist-info/RECORD +0 -76
- {mcp_security_framework-0.1.0.dist-info → mcp_security_framework-1.1.1.dist-info}/WHEEL +0 -0
- {mcp_security_framework-0.1.0.dist-info → mcp_security_framework-1.1.1.dist-info}/entry_points.txt +0 -0
- {mcp_security_framework-0.1.0.dist-info → mcp_security_framework-1.1.1.dist-info}/top_level.txt +0 -0
@@ -28,71 +28,70 @@ Last Modified: 2024-01-20
|
|
28
28
|
|
29
29
|
import json
|
30
30
|
import logging
|
31
|
-
from typing import Any, Dict, Optional
|
31
|
+
from typing import Any, Dict, List, Optional
|
32
32
|
|
33
33
|
from fastapi import Request, Response, status
|
34
34
|
from fastapi.responses import JSONResponse
|
35
35
|
from starlette.middleware.base import BaseHTTPMiddleware
|
36
36
|
|
37
37
|
from mcp_security_framework.middleware.auth_middleware import AuthMiddleware
|
38
|
-
from mcp_security_framework.schemas.models import AuthResult, AuthStatus, AuthMethod
|
39
38
|
from mcp_security_framework.schemas.config import SecurityConfig
|
39
|
+
from mcp_security_framework.schemas.models import AuthMethod, AuthResult, AuthStatus
|
40
40
|
|
41
41
|
|
42
42
|
class FastAPIAuthMiddleware(AuthMiddleware):
|
43
43
|
"""
|
44
44
|
FastAPI Authentication Middleware Implementation
|
45
|
-
|
45
|
+
|
46
46
|
This class provides FastAPI-specific authentication middleware that
|
47
47
|
handles authentication-only processing for FastAPI applications.
|
48
|
-
|
48
|
+
|
49
49
|
The middleware implements:
|
50
50
|
- FastAPI request/response handling
|
51
51
|
- Authentication caching and optimization
|
52
52
|
- Framework-specific error responses
|
53
53
|
- Security event logging
|
54
|
-
|
54
|
+
|
55
55
|
Attributes:
|
56
56
|
config (SecurityConfig): Security configuration settings
|
57
57
|
security_manager: Security manager instance
|
58
58
|
logger (Logger): Logger instance for authentication operations
|
59
59
|
_auth_cache (Dict): Authentication result cache
|
60
|
-
|
60
|
+
|
61
61
|
Example:
|
62
62
|
>>> from mcp_security_framework.middleware import create_auth_middleware
|
63
63
|
>>> middleware = create_auth_middleware(config, framework="fastapi")
|
64
64
|
>>> app.add_middleware(middleware)
|
65
|
-
|
65
|
+
|
66
66
|
Raises:
|
67
67
|
AuthMiddlewareError: When authentication processing fails
|
68
68
|
"""
|
69
|
-
|
70
|
-
def __init__(self,
|
69
|
+
|
70
|
+
def __init__(self, security_manager: Any):
|
71
71
|
"""
|
72
72
|
Initialize FastAPI Authentication Middleware.
|
73
|
-
|
73
|
+
|
74
74
|
Args:
|
75
|
-
config (SecurityConfig): Security configuration settings
|
76
75
|
security_manager: Security manager instance
|
77
76
|
"""
|
78
|
-
super().__init__(
|
77
|
+
super().__init__(security_manager)
|
79
78
|
self.logger = logging.getLogger(__name__)
|
80
|
-
|
79
|
+
|
81
80
|
async def __call__(self, request: Request, call_next: Any) -> Response:
|
82
81
|
"""
|
83
82
|
Process FastAPI request through authentication middleware.
|
84
|
-
|
83
|
+
|
85
84
|
This method implements the authentication-only processing
|
86
85
|
pipeline for FastAPI requests, focusing solely on user
|
87
86
|
authentication without authorization checks.
|
88
|
-
|
87
|
+
|
89
88
|
Args:
|
90
89
|
request (Request): FastAPI request object
|
91
90
|
call_next: FastAPI call_next function
|
92
|
-
|
91
|
+
|
93
92
|
Returns:
|
94
93
|
Response: FastAPI response object
|
95
|
-
|
94
|
+
|
96
95
|
Raises:
|
97
96
|
AuthMiddlewareError: If authentication processing fails
|
98
97
|
"""
|
@@ -100,73 +99,75 @@ class FastAPIAuthMiddleware(AuthMiddleware):
|
|
100
99
|
# Check if path is public (bypasses authentication)
|
101
100
|
if self._is_public_path(request):
|
102
101
|
return await call_next(request)
|
103
|
-
|
102
|
+
|
104
103
|
# Perform authentication
|
105
|
-
auth_result =
|
106
|
-
|
104
|
+
auth_result = self._authenticate_only(request)
|
105
|
+
|
107
106
|
if not auth_result.is_valid:
|
108
107
|
return self._auth_error_response(auth_result)
|
109
|
-
|
108
|
+
|
110
109
|
# Add authentication info to request state
|
111
110
|
request.state.auth_result = auth_result
|
112
111
|
request.state.username = auth_result.username
|
113
112
|
request.state.user_roles = auth_result.roles
|
114
113
|
request.state.auth_method = auth_result.auth_method
|
115
|
-
|
114
|
+
|
116
115
|
# Process request
|
117
116
|
response = await call_next(request)
|
118
|
-
|
117
|
+
|
119
118
|
# Log successful authentication
|
120
|
-
self._log_auth_event(
|
121
|
-
"
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
119
|
+
self._log_auth_event(
|
120
|
+
"authentication_successful",
|
121
|
+
{
|
122
|
+
"ip_address": self._get_client_ip(request),
|
123
|
+
"username": auth_result.username,
|
124
|
+
"path": str(request.url.path),
|
125
|
+
"method": request.method,
|
126
|
+
"auth_method": auth_result.auth_method,
|
127
|
+
},
|
128
|
+
)
|
129
|
+
|
128
130
|
return response
|
129
|
-
|
131
|
+
|
130
132
|
except Exception as e:
|
131
133
|
self.logger.error(
|
132
134
|
"FastAPI authentication middleware processing failed",
|
133
135
|
extra={"error": str(e)},
|
134
|
-
exc_info=True
|
136
|
+
exc_info=True,
|
135
137
|
)
|
136
138
|
raise AuthMiddlewareError(
|
137
|
-
f"Authentication processing failed: {str(e)}",
|
138
|
-
error_code=-32035
|
139
|
+
f"Authentication processing failed: {str(e)}", error_code=-32035
|
139
140
|
)
|
140
|
-
|
141
|
+
|
141
142
|
def _is_public_path(self, request: Request) -> bool:
|
142
143
|
"""
|
143
144
|
Check if the request path is public (bypasses authentication).
|
144
|
-
|
145
|
+
|
145
146
|
Args:
|
146
147
|
request (Request): FastAPI request object
|
147
|
-
|
148
|
+
|
148
149
|
Returns:
|
149
150
|
bool: True if path is public, False otherwise
|
150
151
|
"""
|
151
152
|
path = str(request.url.path)
|
152
|
-
|
153
|
+
|
153
154
|
# Check configured public paths
|
154
|
-
if hasattr(self.config.auth,
|
155
|
+
if hasattr(self.config.auth, "public_paths"):
|
155
156
|
for public_path in self.config.auth.public_paths:
|
156
157
|
if path.startswith(public_path):
|
157
158
|
return True
|
158
|
-
|
159
|
+
|
159
160
|
# Check common public paths
|
160
161
|
public_paths = ["/health", "/status", "/metrics", "/docs", "/openapi.json"]
|
161
162
|
return any(path.startswith(public_path) for public_path in public_paths)
|
162
|
-
|
163
|
+
|
163
164
|
def _get_client_ip(self, request: Request) -> str:
|
164
165
|
"""
|
165
166
|
Get client IP address from FastAPI request.
|
166
|
-
|
167
|
+
|
167
168
|
Args:
|
168
169
|
request (Request): FastAPI request object
|
169
|
-
|
170
|
+
|
170
171
|
Returns:
|
171
172
|
str: Client IP address
|
172
173
|
"""
|
@@ -174,33 +175,35 @@ class FastAPIAuthMiddleware(AuthMiddleware):
|
|
174
175
|
forwarded_for = request.headers.get("X-Forwarded-For")
|
175
176
|
if forwarded_for:
|
176
177
|
return forwarded_for.split(",")[0].strip()
|
177
|
-
|
178
|
+
|
178
179
|
# Try X-Real-IP header
|
179
180
|
real_ip = request.headers.get("X-Real-IP")
|
180
181
|
if real_ip:
|
181
182
|
return real_ip
|
182
|
-
|
183
|
+
|
183
184
|
# Use client host
|
184
|
-
if hasattr(request,
|
185
|
+
if hasattr(request, "client") and request.client:
|
185
186
|
return request.client.host
|
186
|
-
|
187
|
+
|
187
188
|
# Fallback to default IP from config or environment
|
188
|
-
default_ip = getattr(self.config,
|
189
|
+
default_ip = getattr(self.config, "default_client_ip", None)
|
189
190
|
if default_ip:
|
190
191
|
return default_ip
|
191
|
-
|
192
|
+
|
192
193
|
# Use environment variable or default
|
193
194
|
import os
|
195
|
+
|
194
196
|
from ..constants import DEFAULT_CLIENT_IP
|
195
|
-
|
196
|
-
|
197
|
+
|
198
|
+
return os.environ.get("DEFAULT_CLIENT_IP", DEFAULT_CLIENT_IP)
|
199
|
+
|
197
200
|
def _get_cache_key(self, request: Request) -> str:
|
198
201
|
"""
|
199
202
|
Generate cache key for authentication result.
|
200
|
-
|
203
|
+
|
201
204
|
Args:
|
202
205
|
request (Request): FastAPI request object
|
203
|
-
|
206
|
+
|
204
207
|
Returns:
|
205
208
|
str: Cache key
|
206
209
|
"""
|
@@ -208,27 +211,27 @@ class FastAPIAuthMiddleware(AuthMiddleware):
|
|
208
211
|
ip = self._get_client_ip(request)
|
209
212
|
user_agent = request.headers.get("User-Agent", "")
|
210
213
|
return f"auth:{ip}:{hash(user_agent)}"
|
211
|
-
|
212
|
-
|
214
|
+
|
215
|
+
def _try_auth_method(self, request: Request, method: str) -> AuthResult:
|
213
216
|
"""
|
214
217
|
Try authentication using specific method with FastAPI request.
|
215
|
-
|
218
|
+
|
216
219
|
Args:
|
217
220
|
request (Request): FastAPI request object
|
218
221
|
method (str): Authentication method to try
|
219
|
-
|
222
|
+
|
220
223
|
Returns:
|
221
224
|
AuthResult: Authentication result
|
222
225
|
"""
|
223
226
|
try:
|
224
227
|
if method == "api_key":
|
225
|
-
return
|
228
|
+
return self._try_api_key_auth(request)
|
226
229
|
elif method == "jwt":
|
227
|
-
return
|
230
|
+
return self._try_jwt_auth(request)
|
228
231
|
elif method == "certificate":
|
229
|
-
return
|
232
|
+
return self._try_certificate_auth(request)
|
230
233
|
elif method == "basic":
|
231
|
-
return
|
234
|
+
return self._try_basic_auth(request)
|
232
235
|
else:
|
233
236
|
return AuthResult(
|
234
237
|
is_valid=False,
|
@@ -237,13 +240,13 @@ class FastAPIAuthMiddleware(AuthMiddleware):
|
|
237
240
|
roles=[],
|
238
241
|
auth_method=None,
|
239
242
|
error_code=-32022,
|
240
|
-
error_message=f"Unsupported authentication method: {method}"
|
243
|
+
error_message=f"Unsupported authentication method: {method}",
|
241
244
|
)
|
242
245
|
except Exception as e:
|
243
246
|
self.logger.error(
|
244
247
|
f"Authentication method {method} failed",
|
245
248
|
extra={"error": str(e)},
|
246
|
-
exc_info=True
|
249
|
+
exc_info=True,
|
247
250
|
)
|
248
251
|
return AuthResult(
|
249
252
|
is_valid=False,
|
@@ -252,16 +255,16 @@ class FastAPIAuthMiddleware(AuthMiddleware):
|
|
252
255
|
roles=[],
|
253
256
|
auth_method=None,
|
254
257
|
error_code=-32023,
|
255
|
-
error_message=f"Authentication method {method} failed: {str(e)}"
|
258
|
+
error_message=f"Authentication method {method} failed: {str(e)}",
|
256
259
|
)
|
257
|
-
|
258
|
-
|
260
|
+
|
261
|
+
def _try_api_key_auth(self, request: Request) -> AuthResult:
|
259
262
|
"""
|
260
263
|
Try API key authentication with FastAPI request.
|
261
|
-
|
264
|
+
|
262
265
|
Args:
|
263
266
|
request (Request): FastAPI request object
|
264
|
-
|
267
|
+
|
265
268
|
Returns:
|
266
269
|
AuthResult: Authentication result
|
267
270
|
"""
|
@@ -272,7 +275,7 @@ class FastAPIAuthMiddleware(AuthMiddleware):
|
|
272
275
|
auth_header = request.headers.get("Authorization")
|
273
276
|
if auth_header and auth_header.startswith("Bearer "):
|
274
277
|
api_key = auth_header[7:] # Remove "Bearer " prefix
|
275
|
-
|
278
|
+
|
276
279
|
if not api_key:
|
277
280
|
return AuthResult(
|
278
281
|
is_valid=False,
|
@@ -281,19 +284,19 @@ class FastAPIAuthMiddleware(AuthMiddleware):
|
|
281
284
|
roles=[],
|
282
285
|
auth_method=AuthMethod.API_KEY,
|
283
286
|
error_code=-32012,
|
284
|
-
error_message="API key not found in request"
|
287
|
+
error_message="API key not found in request",
|
285
288
|
)
|
286
|
-
|
289
|
+
|
287
290
|
# Authenticate using security manager
|
288
291
|
return self.security_manager.auth_manager.authenticate_api_key(api_key)
|
289
|
-
|
290
|
-
|
292
|
+
|
293
|
+
def _try_jwt_auth(self, request: Request) -> AuthResult:
|
291
294
|
"""
|
292
295
|
Try JWT authentication with FastAPI request.
|
293
|
-
|
296
|
+
|
294
297
|
Args:
|
295
298
|
request (Request): FastAPI request object
|
296
|
-
|
299
|
+
|
297
300
|
Returns:
|
298
301
|
AuthResult: Authentication result
|
299
302
|
"""
|
@@ -307,21 +310,21 @@ class FastAPIAuthMiddleware(AuthMiddleware):
|
|
307
310
|
roles=[],
|
308
311
|
auth_method=AuthMethod.JWT,
|
309
312
|
error_code=-32013,
|
310
|
-
error_message="JWT token not found in Authorization header"
|
313
|
+
error_message="JWT token not found in Authorization header",
|
311
314
|
)
|
312
|
-
|
315
|
+
|
313
316
|
token = auth_header[7:] # Remove "Bearer " prefix
|
314
|
-
|
317
|
+
|
315
318
|
# Authenticate using security manager
|
316
319
|
return self.security_manager.auth_manager.authenticate_jwt_token(token)
|
317
|
-
|
318
|
-
|
320
|
+
|
321
|
+
def _try_certificate_auth(self, request: Request) -> AuthResult:
|
319
322
|
"""
|
320
323
|
Try certificate authentication with FastAPI request.
|
321
|
-
|
324
|
+
|
322
325
|
Args:
|
323
326
|
request (Request): FastAPI request object
|
324
|
-
|
327
|
+
|
325
328
|
Returns:
|
326
329
|
AuthResult: Authentication result
|
327
330
|
"""
|
@@ -335,16 +338,16 @@ class FastAPIAuthMiddleware(AuthMiddleware):
|
|
335
338
|
roles=[],
|
336
339
|
auth_method=AuthMethod.CERTIFICATE,
|
337
340
|
error_code=-32014,
|
338
|
-
error_message="Certificate authentication not implemented"
|
341
|
+
error_message="Certificate authentication not implemented",
|
339
342
|
)
|
340
|
-
|
341
|
-
|
343
|
+
|
344
|
+
def _try_basic_auth(self, request: Request) -> AuthResult:
|
342
345
|
"""
|
343
346
|
Try basic authentication with FastAPI request.
|
344
|
-
|
347
|
+
|
345
348
|
Args:
|
346
349
|
request (Request): FastAPI request object
|
347
|
-
|
350
|
+
|
348
351
|
Returns:
|
349
352
|
AuthResult: Authentication result
|
350
353
|
"""
|
@@ -358,9 +361,9 @@ class FastAPIAuthMiddleware(AuthMiddleware):
|
|
358
361
|
roles=[],
|
359
362
|
auth_method=AuthMethod.BASIC,
|
360
363
|
error_code=-32015,
|
361
|
-
error_message="Basic authentication credentials not found"
|
364
|
+
error_message="Basic authentication credentials not found",
|
362
365
|
)
|
363
|
-
|
366
|
+
|
364
367
|
# Basic auth is not implemented in this version
|
365
368
|
return AuthResult(
|
366
369
|
is_valid=False,
|
@@ -369,16 +372,16 @@ class FastAPIAuthMiddleware(AuthMiddleware):
|
|
369
372
|
roles=[],
|
370
373
|
auth_method=AuthMethod.BASIC,
|
371
374
|
error_code=-32016,
|
372
|
-
error_message="Basic authentication not implemented"
|
375
|
+
error_message="Basic authentication not implemented",
|
373
376
|
)
|
374
|
-
|
377
|
+
|
375
378
|
def _auth_error_response(self, auth_result: AuthResult) -> JSONResponse:
|
376
379
|
"""
|
377
380
|
Create authentication error response for FastAPI.
|
378
|
-
|
381
|
+
|
379
382
|
Args:
|
380
383
|
auth_result (AuthResult): Authentication result with error
|
381
|
-
|
384
|
+
|
382
385
|
Returns:
|
383
386
|
JSONResponse: FastAPI error response
|
384
387
|
"""
|
@@ -386,24 +389,23 @@ class FastAPIAuthMiddleware(AuthMiddleware):
|
|
386
389
|
"error": "Authentication failed",
|
387
390
|
"error_code": auth_result.error_code,
|
388
391
|
"error_message": auth_result.error_message,
|
389
|
-
"auth_method":
|
390
|
-
|
391
|
-
|
392
|
-
headers = {
|
393
|
-
"WWW-Authenticate": "Bearer",
|
394
|
-
"Content-Type": "application/json"
|
392
|
+
"auth_method": (
|
393
|
+
auth_result.auth_method.value if auth_result.auth_method else None
|
394
|
+
),
|
395
395
|
}
|
396
|
-
|
396
|
+
|
397
|
+
headers = {"WWW-Authenticate": "Bearer", "Content-Type": "application/json"}
|
398
|
+
|
397
399
|
return JSONResponse(
|
398
400
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
399
401
|
content=error_data,
|
400
|
-
headers=headers
|
402
|
+
headers=headers,
|
401
403
|
)
|
402
|
-
|
404
|
+
|
403
405
|
def _log_auth_event(self, event_type: str, details: Dict[str, Any]) -> None:
|
404
406
|
"""
|
405
407
|
Log authentication event.
|
406
|
-
|
408
|
+
|
407
409
|
Args:
|
408
410
|
event_type (str): Type of authentication event
|
409
411
|
details (Dict[str, Any]): Event details
|
@@ -419,28 +421,95 @@ class FastAPIAuthMiddleware(AuthMiddleware):
|
|
419
421
|
"path": details.get("path"),
|
420
422
|
"method": details.get("method"),
|
421
423
|
"auth_method": details.get("auth_method"),
|
422
|
-
**details
|
423
|
-
}
|
424
|
+
**details,
|
425
|
+
},
|
424
426
|
)
|
425
427
|
except Exception as e:
|
426
428
|
self.logger.error(
|
427
429
|
"Failed to log authentication event",
|
428
430
|
extra={"error": str(e)},
|
429
|
-
exc_info=True
|
431
|
+
exc_info=True,
|
430
432
|
)
|
431
433
|
|
434
|
+
# Abstract method implementations
|
435
|
+
|
436
|
+
def _get_rate_limit_identifier(self, request: Request) -> str:
|
437
|
+
"""
|
438
|
+
Get rate limit identifier from FastAPI request.
|
439
|
+
|
440
|
+
Args:
|
441
|
+
request (Request): FastAPI request object
|
442
|
+
|
443
|
+
Returns:
|
444
|
+
str: Rate limit identifier (IP address)
|
445
|
+
"""
|
446
|
+
return self._get_client_ip(request)
|
447
|
+
|
448
|
+
def _get_request_path(self, request: Request) -> str:
|
449
|
+
"""
|
450
|
+
Get request path from FastAPI request.
|
451
|
+
|
452
|
+
Args:
|
453
|
+
request (Request): FastAPI request object
|
454
|
+
|
455
|
+
Returns:
|
456
|
+
str: Request path
|
457
|
+
"""
|
458
|
+
return str(request.url.path)
|
459
|
+
|
460
|
+
def _get_required_permissions(self, request: Request) -> List[str]:
|
461
|
+
"""
|
462
|
+
Get required permissions for FastAPI request.
|
463
|
+
|
464
|
+
Args:
|
465
|
+
request (Request): FastAPI request object
|
466
|
+
|
467
|
+
Returns:
|
468
|
+
List[str]: List of required permissions
|
469
|
+
"""
|
470
|
+
# For authentication-only middleware, no permissions are required
|
471
|
+
return []
|
472
|
+
|
473
|
+
def _apply_security_headers(
|
474
|
+
self, response: Response, headers: Dict[str, str]
|
475
|
+
) -> None:
|
476
|
+
"""
|
477
|
+
Apply security headers to FastAPI response.
|
478
|
+
|
479
|
+
Args:
|
480
|
+
response (Response): FastAPI response object
|
481
|
+
headers (Dict[str, str]): Headers to apply
|
482
|
+
"""
|
483
|
+
for header, value in headers.items():
|
484
|
+
response.headers[header] = value
|
485
|
+
|
486
|
+
def _create_error_response(self, status_code: int, message: str) -> JSONResponse:
|
487
|
+
"""
|
488
|
+
Create error response for FastAPI.
|
489
|
+
|
490
|
+
Args:
|
491
|
+
status_code (int): HTTP status code
|
492
|
+
message (str): Error message
|
493
|
+
|
494
|
+
Returns:
|
495
|
+
JSONResponse: FastAPI error response object
|
496
|
+
"""
|
497
|
+
return JSONResponse(
|
498
|
+
status_code=status_code, content={"error": message, "error_code": -32000}
|
499
|
+
)
|
500
|
+
|
432
501
|
|
433
502
|
class AuthMiddlewareError(Exception):
|
434
503
|
"""
|
435
504
|
Authentication Middleware Error
|
436
|
-
|
505
|
+
|
437
506
|
This exception is raised when authentication middleware processing fails.
|
438
|
-
|
507
|
+
|
439
508
|
Attributes:
|
440
509
|
message (str): Error message
|
441
510
|
error_code (int): Error code for programmatic handling
|
442
511
|
"""
|
443
|
-
|
512
|
+
|
444
513
|
def __init__(self, message: str, error_code: int = -32030):
|
445
514
|
self.message = message
|
446
515
|
self.error_code = error_code
|