From: Marcelo Trylesinski Date: Thu, 20 Mar 2025 12:19:07 +0000 (+0000) Subject: Use 401 instead of 403 in security classes X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fheads%2F401-instead-of-403;p=thirdparty%2Ffastapi%2Ffastapi.git Use 401 instead of 403 in security classes --- diff --git a/fastapi/security/http.py b/fastapi/security/http.py index 9ab2df3c98..4054528b4c 100644 --- a/fastapi/security/http.py +++ b/fastapi/security/http.py @@ -303,18 +303,23 @@ class HTTPBearer(HTTPBase): ) -> Optional[HTTPAuthorizationCredentials]: authorization = request.headers.get("Authorization") scheme, credentials = get_authorization_scheme_param(authorization) + # All fields besides the scheme are optional, as per https://www.rfc-editor.org/rfc/rfc6750.html#section-3. + unauthorized_headers = {"WWW-Authenticate": "Bearer"} if not (authorization and scheme and credentials): if self.auto_error: raise HTTPException( - status_code=HTTP_403_FORBIDDEN, detail="Not authenticated" + status_code=HTTP_401_UNAUTHORIZED, + detail="Not authenticated", + headers=unauthorized_headers, ) else: return None if scheme.lower() != "bearer": if self.auto_error: raise HTTPException( - status_code=HTTP_403_FORBIDDEN, + status_code=HTTP_401_UNAUTHORIZED, detail="Invalid authentication credentials", + headers=unauthorized_headers, ) else: return None @@ -405,18 +410,23 @@ class HTTPDigest(HTTPBase): ) -> Optional[HTTPAuthorizationCredentials]: authorization = request.headers.get("Authorization") scheme, credentials = get_authorization_scheme_param(authorization) + # All fields besides the scheme are optional, as per https://datatracker.ietf.org/doc/html/rfc7616#section-3.3. + unauthorized_headers = {"WWW-Authenticate": "Digest"} if not (authorization and scheme and credentials): if self.auto_error: raise HTTPException( - status_code=HTTP_403_FORBIDDEN, detail="Not authenticated" + status_code=HTTP_401_UNAUTHORIZED, + detail="Not authenticated", + headers=unauthorized_headers, ) else: return None if scheme.lower() != "digest": if self.auto_error: raise HTTPException( - status_code=HTTP_403_FORBIDDEN, + status_code=HTTP_401_UNAUTHORIZED, detail="Invalid authentication credentials", + headers=unauthorized_headers, ) else: return None diff --git a/fastapi/security/oauth2.py b/fastapi/security/oauth2.py index 5ffad59862..9efa65a4cf 100644 --- a/fastapi/security/oauth2.py +++ b/fastapi/security/oauth2.py @@ -7,7 +7,7 @@ from fastapi.param_functions import Form from fastapi.security.base import SecurityBase from fastapi.security.utils import get_authorization_scheme_param from starlette.requests import Request -from starlette.status import HTTP_401_UNAUTHORIZED, HTTP_403_FORBIDDEN +from starlette.status import HTTP_401_UNAUTHORIZED # TODO: import from typing when deprecating Python 3.9 from typing_extensions import Annotated, Doc @@ -381,7 +381,9 @@ class OAuth2(SecurityBase): if not authorization: if self.auto_error: raise HTTPException( - status_code=HTTP_403_FORBIDDEN, detail="Not authenticated" + status_code=HTTP_401_UNAUTHORIZED, + detail="Not authenticated", + headers={"WWW-Authenticate": "Bearer"}, ) else: return None