Leon4gr45's picture
Deploy complete BrainAPI source d15a5889e878
2f1e7ff verified
Raw History Blame Contribute Delete
3.28 kB
"""All HTTP authentication delegates to the shared identity service."""
import secrets
import re
from src.services.console_sessions import SESSION_COOKIE, get_console_sessions
from starlette.exceptions import HTTPException
from starlette.middleware.base import BaseHTTPMiddleware
from src.services.api.console_static import is_console_path
from src.services.api.errors import error_response
from src.services.data.main import data_adapter
from src.services.auth import AuthError, bearer_token, get_auth_service, request_permission
class BrainPATMiddleware(BaseHTTPMiddleware):
excluded_prefixes = {"/docs", "/redoc", "/demo", "/api-docs"}
auth_exempt_paths = {"/", "/health", "/openapi.json", "/favicon.ico", "/auth/session"}
async def dispatch(self, request, call_next):
path = request.url.path
if (request.method == "OPTIONS" or is_console_path(path)
or path in self.auth_exempt_paths
or any(path.startswith(p) for p in self.excluded_prefixes) or re.match(r"^/brains/[^/]+/mcp(?:/|$)", path) or path == "/mcp"):
return await call_next(request)
service = get_auth_service(data_adapter)
try:
token = bearer_token(request.headers)
if token:
principal = service.authenticate_token(token)
else:
principal, csrf = get_console_sessions().resolve(request.cookies.get(SESSION_COOKIE), service)
request.state.csrf_token = csrf
if request.method not in {"GET", "HEAD", "OPTIONS"}:
if not secrets.compare_digest(request.headers.get("X-CSRF-Token", ""), csrf):
raise AuthError(403, "CSRF_INVALID")
from src.services.api.routes.auth import check_origin
check_origin(request)
request.state.principal = principal
request.state.is_system_pat = principal.is_system
if path.startswith("/system"):
discovery = request.method == "GET" and path.startswith("/system/workspaces")
if not principal.is_system and not discovery:
raise AuthError(403, "FORBIDDEN")
if not principal.is_system:
request.state.brain_id = principal.brain_id
elif path not in {"/auth/me", "/auth/logout", "/meta/login-info"}:
brain_id = getattr(request.state, "brain_id", None)
if not brain_id:
return error_response(request, status_code=400, detail="Brain ID is required.", code="BRAIN_ID_REQUIRED")
service.authorize_workspace(principal, brain_id, request_permission(request.method, path))
except AuthError as error:
return error_response(request, status_code=error.status, detail=error.code, code=error.code)
except HTTPException as error:
return error_response(request, status_code=error.status_code, detail=error.detail,
code="CSRF_ORIGIN_INVALID" if error.detail == "CSRF_ORIGIN_INVALID" else None)
except Exception:
return error_response(request, status_code=503, detail="Authentication store unavailable")
return await call_next(request)