"""CORS middleware configuration.""" from flask import request, make_response ALLOWED_METHODS = "GET, POST, PUT, PATCH, DELETE, OPTIONS" ALLOWED_HEADERS = ( "Content-Type, Authorization, X-Requested-With, X-Request-ID, " "Cache-Control, Pragma, X-WebAuthn-Session-Token" ) def _is_origin_allowed(origin, cors_origins): """Return True if the origin is permitted by the CORS config. Handles both wildcard ("*") and explicit origin lists. """ if not origin: return False if cors_origins == "*": return True if isinstance(cors_origins, list): if "*" in cors_origins: return True return origin in cors_origins return False def _cors_origin_header(cors_origins, request_origin): """Return the value for Access-Control-Allow-Origin. Per the CORS spec, browsers reject ``*`` when credentials are involved, so we echo the request origin when wildcard + credentials is configured. """ allow_all = cors_origins == "*" or (isinstance(cors_origins, list) and "*" in cors_origins) if allow_all and request_origin: return request_origin if allow_all: return "*" if request_origin and request_origin in cors_origins: return request_origin return None def setup_cors(app): """ Configure CORS for the application. Args: app: Flask application instance """ supports_credentials = app.config.get("CORS_SUPPORTS_CREDENTIALS", True) @app.before_request def handle_preflight(): """Handle CORS preflight OPTIONS requests.""" if request.method == "OPTIONS": origin = request.headers.get("Origin") cors_origins = app.config.get("CORS_ORIGINS", []) if not _is_origin_allowed(origin, cors_origins): return None response = make_response("", 204) response.headers["Access-Control-Allow-Origin"] = _cors_origin_header(cors_origins, origin) response.headers["Access-Control-Allow-Methods"] = ALLOWED_METHODS response.headers["Access-Control-Allow-Headers"] = ALLOWED_HEADERS if supports_credentials: response.headers["Access-Control-Allow-Credentials"] = "true" response.headers["Access-Control-Max-Age"] = "3600" response.headers["Cache-Control"] = "no-cache, no-store" return response @app.after_request def after_request_cors(response): """Add CORS headers to non-preflight responses.""" origin = request.headers.get("Origin") cors_origins = app.config.get("CORS_ORIGINS", []) allow_origin = _cors_origin_header(cors_origins, origin) if allow_origin: response.headers["Access-Control-Allow-Origin"] = allow_origin response.headers["Access-Control-Allow-Methods"] = ALLOWED_METHODS response.headers["Access-Control-Allow-Headers"] = ALLOWED_HEADERS if supports_credentials: response.headers["Access-Control-Allow-Credentials"] = "true" response.headers["Access-Control-Max-Age"] = "3600" return response