eigent/backend/app/auth/brain_auth.py
Tong Chen cf3cb8cbcd
feat: Space layer above Project + RunContext + Single Agent CDP (#1655)
Co-authored-by: Douglas Lai <115660088+Douglasymlai@users.noreply.github.com>
Co-authored-by: Douglas <douglas.ym.lai@gmail.com>
2026-05-29 16:19:48 +08:00

91 lines
2.9 KiB
Python

# ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
from collections.abc import Iterator
from contextlib import contextmanager
from dataclasses import dataclass
from fastapi import HTTPException, Request
from app.auth.interface import IAuthProvider, NoneAuth
@dataclass(frozen=True)
class BrainAuthContext:
user_id: str
tenant_id: str
authorization_present: bool
token_scheme: str | None = None
_auth_provider: IAuthProvider = NoneAuth()
def set_brain_auth_provider(provider: IAuthProvider) -> None:
global _auth_provider
_auth_provider = provider
@contextmanager
def with_brain_auth_provider(provider: IAuthProvider) -> Iterator[None]:
previous = get_brain_auth_provider()
set_brain_auth_provider(provider)
try:
yield
finally:
set_brain_auth_provider(previous)
def get_brain_auth_provider() -> IAuthProvider:
return _auth_provider
async def get_brain_auth_context(request: Request) -> BrainAuthContext:
"""
Bridge auth dependency for Brain routes.
Local Brain still uses NoneAuth, but every non-health route now has a
stable auth hook and request.state.brain_auth for future JWT/API-key
verification without changing controller call sites again.
"""
authorization = request.headers.get("authorization")
token_scheme = None
if authorization:
token_scheme = authorization.split(" ", 1)[0].lower()
provider = get_brain_auth_provider()
identity = await provider.authenticate(
{
"headers": dict(request.headers),
"state": getattr(request, "state", None),
"authorization_present": bool(authorization),
}
)
if not identity.get("user_id") and not isinstance(provider, NoneAuth):
raise HTTPException(
status_code=401,
detail={
"code": "brain_auth_required",
"message": "Brain authentication did not resolve a user.",
},
)
context = BrainAuthContext(
user_id=identity.get("user_id") or "local",
tenant_id=identity.get("tenant_id") or "default",
authorization_present=bool(authorization),
token_scheme=token_scheme,
)
request.state.brain_auth = context
return context