mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-06-29 23:41:12 +08:00
fix(auth): return HTTP 401 for token-auth failures (#13420)
Follow-up to #12488 #13386 ### What problem does this PR solve? Previously, token authentication failures returned HTTP 200 with an error code in the response body. This PR updates `token_required` to raise `Unauthorized` and relies on the global error handler to return a structured JSON response with HTTP 401 status. The response body structure (`code`, `message`, `data`) remains unchanged to preserve compatibility with the official SDK. Frontend logic has been updated to handle HTTP 401 responses in addition to checking `data.code`. ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)
This commit is contained in:
@@ -33,7 +33,7 @@ from quart import (
|
||||
request,
|
||||
has_app_context,
|
||||
)
|
||||
from werkzeug.exceptions import BadRequest as WerkzeugBadRequest
|
||||
from werkzeug.exceptions import BadRequest as WerkzeugBadRequest, Unauthorized as WerkzeugUnauthorized
|
||||
|
||||
try:
|
||||
from quart.exceptions import BadRequest as QuartBadRequest
|
||||
@@ -270,39 +270,41 @@ def construct_json_result(code: RetCode = RetCode.SUCCESS, message="success", da
|
||||
|
||||
|
||||
def token_required(func):
|
||||
def get_tenant_id(**kwargs):
|
||||
@wraps(func)
|
||||
async def wrapper(*args, **kwargs):
|
||||
# Validate the token (API Key)
|
||||
if os.environ.get("DISABLE_SDK"):
|
||||
return False, get_json_result(data=False, message="`Authorization` can't be empty")
|
||||
err = WerkzeugUnauthorized(description="`Authorization` can't be empty")
|
||||
err.code = RetCode.SUCCESS
|
||||
raise err
|
||||
|
||||
authorization_str = request.headers.get("Authorization")
|
||||
if not authorization_str:
|
||||
return False, get_json_result(data=False, message="`Authorization` can't be empty")
|
||||
err = WerkzeugUnauthorized(description="`Authorization` can't be empty")
|
||||
err.code = RetCode.SUCCESS
|
||||
raise err
|
||||
|
||||
authorization_list = authorization_str.split()
|
||||
if len(authorization_list) < 2:
|
||||
return False, get_json_result(data=False, message="Please check your authorization format.")
|
||||
err = WerkzeugUnauthorized(description="Please check your authorization format.")
|
||||
err.code = RetCode.AUTHENTICATION_ERROR
|
||||
raise err
|
||||
|
||||
token = authorization_list[1]
|
||||
objs = APIToken.query(token=token)
|
||||
if not objs:
|
||||
return False, get_json_result(data=False, message="Authentication error: API key is invalid!", code=RetCode.AUTHENTICATION_ERROR)
|
||||
err = WerkzeugUnauthorized(description="Authentication error: API key is invalid!")
|
||||
err.code = RetCode.AUTHENTICATION_ERROR
|
||||
raise err
|
||||
|
||||
# On success, inject tenant_id into the route function's kwargs
|
||||
kwargs["tenant_id"] = objs[0].tenant_id
|
||||
return True, kwargs
|
||||
result = func(*args, **kwargs)
|
||||
if inspect.iscoroutine(result):
|
||||
return await result
|
||||
return result
|
||||
|
||||
@wraps(func)
|
||||
def decorated_function(*args, **kwargs):
|
||||
e, kwargs = get_tenant_id(**kwargs)
|
||||
if not e:
|
||||
return kwargs
|
||||
return func(*args, **kwargs)
|
||||
|
||||
@wraps(func)
|
||||
async def adecorated_function(*args, **kwargs):
|
||||
e, kwargs = get_tenant_id(**kwargs)
|
||||
if not e:
|
||||
return kwargs
|
||||
return await func(*args, **kwargs)
|
||||
|
||||
if inspect.iscoroutinefunction(func):
|
||||
return adecorated_function
|
||||
return decorated_function
|
||||
return wrapper
|
||||
|
||||
|
||||
def get_result(code=RetCode.SUCCESS, message="", data=None, total=None):
|
||||
|
||||
Reference in New Issue
Block a user