diff --git a/artdag_common/middleware/__pycache__/auth.cpython-310.pyc b/artdag_common/middleware/__pycache__/auth.cpython-310.pyc new file mode 100644 index 0000000..0a26285 Binary files /dev/null and b/artdag_common/middleware/__pycache__/auth.cpython-310.pyc differ diff --git a/artdag_common/middleware/auth.py b/artdag_common/middleware/auth.py index 482e80a..f9d97b1 100644 --- a/artdag_common/middleware/auth.py +++ b/artdag_common/middleware/auth.py @@ -31,8 +31,9 @@ def get_user_from_cookie(request: Request) -> Optional[UserContext]: """ Extract user context from session cookie. - The cookie format is expected to be base64-encoded JSON: - {"username": "user", "actor_id": "@user@server.com"} + Supports two cookie formats: + 1. artdag_session: base64-encoded JSON {"username": "user", "actor_id": "@user@server.com"} + 2. auth_token: raw JWT token (used by L1 servers) Args: request: FastAPI request @@ -40,19 +41,38 @@ def get_user_from_cookie(request: Request) -> Optional[UserContext]: Returns: UserContext if valid cookie found, None otherwise """ + # Try artdag_session cookie first (base64-encoded JSON) cookie = request.cookies.get("artdag_session") - if not cookie: - return None + if cookie: + try: + data = json.loads(base64.b64decode(cookie)) + username = data.get("username", "") + actor_id = data.get("actor_id", "") + if not actor_id and username: + actor_id = f"@{username}" + return UserContext( + username=username, + actor_id=actor_id, + ) + except (json.JSONDecodeError, ValueError, KeyError): + pass - try: - # Decode base64 cookie - data = json.loads(base64.b64decode(cookie)) - return UserContext( - username=data.get("username", ""), - actor_id=data.get("actor_id", ""), - ) - except (json.JSONDecodeError, ValueError, KeyError): - return None + # Try auth_token cookie (raw JWT, used by L1) + token = request.cookies.get("auth_token") + if token: + claims = decode_jwt_claims(token) + if claims: + username = claims.get("username") or claims.get("sub", "") + actor_id = claims.get("actor_id") or claims.get("actor") + if not actor_id and username: + actor_id = f"@{username}" + return UserContext( + username=username, + actor_id=actor_id or "", + token=token, + ) + + return None def get_user_from_header(request: Request) -> Optional[UserContext]: @@ -76,9 +96,14 @@ def get_user_from_header(request: Request) -> Optional[UserContext]: # Attempt to decode JWT claims claims = decode_jwt_claims(token) if claims: + username = claims.get("username") or claims.get("sub", "") + actor_id = claims.get("actor_id") or claims.get("actor") + # Default actor_id to @username if not provided + if not actor_id and username: + actor_id = f"@{username}" return UserContext( - username=claims.get("username", ""), - actor_id=claims.get("actor_id", ""), + username=username, + actor_id=actor_id or "", token=token, )