feat: rebuild as multi-user web agent
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import hmac
|
||||
from dataclasses import dataclass
|
||||
from typing import Annotated
|
||||
|
||||
import jwt
|
||||
from fastapi import Header, HTTPException, status
|
||||
|
||||
from agent_platform.config import get_settings
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class UserIdentity:
|
||||
user_id: str
|
||||
email: str
|
||||
name: str
|
||||
role: str
|
||||
|
||||
|
||||
def verify_service_bearer(authorization: str | None, expected: str) -> None:
|
||||
if not expected:
|
||||
raise HTTPException(status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail="Service secret is not configured")
|
||||
scheme, _, token = (authorization or "").partition(" ")
|
||||
if scheme.lower() != "bearer" or not hmac.compare_digest(token, expected):
|
||||
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid service credentials")
|
||||
|
||||
|
||||
def decode_openwebui_identity(token: str | None, secret: str) -> UserIdentity:
|
||||
if not secret:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
||||
detail="Identity verification is unavailable",
|
||||
)
|
||||
if not token:
|
||||
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Missing signed user identity")
|
||||
try:
|
||||
claims = jwt.decode(
|
||||
token,
|
||||
secret,
|
||||
algorithms=["HS256"],
|
||||
issuer="open-webui",
|
||||
options={"require": ["sub", "iss", "iat", "exp"]},
|
||||
)
|
||||
except jwt.PyJWTError as exc:
|
||||
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid signed user identity") from exc
|
||||
user_id = str(claims.get("sub", "")).strip()
|
||||
if not user_id:
|
||||
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Signed identity has no subject")
|
||||
return UserIdentity(
|
||||
user_id=user_id,
|
||||
email=str(claims.get("email", "")),
|
||||
name=str(claims.get("name", "")),
|
||||
role=str(claims.get("role", "user")),
|
||||
)
|
||||
|
||||
|
||||
def require_gateway_identity(
|
||||
authorization: Annotated[
|
||||
str | None,
|
||||
Header(alias="Authorization", include_in_schema=False),
|
||||
] = None,
|
||||
user_jwt: Annotated[
|
||||
str | None,
|
||||
Header(alias="X-OpenWebUI-User-Jwt", include_in_schema=False),
|
||||
] = None,
|
||||
) -> UserIdentity:
|
||||
settings = get_settings()
|
||||
verify_service_bearer(authorization, settings.internal_gateway_key)
|
||||
return decode_openwebui_identity(user_jwt, settings.openwebui_forward_jwt_secret)
|
||||
Reference in New Issue
Block a user