From ab90dde9e3d86d58fe122a06d702837cd8eb5b65 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Sat, 28 Jun 2025 02:04:03 +0000 Subject: [PATCH] Fix HTTP auth status codes: return 401 instead of 403 for authentication failures - Change HTTPBase, HTTPBearer, and HTTPDigest classes to return HTTP_401_UNAUTHORIZED instead of HTTP_403_FORBIDDEN for missing or malformed authorization headers - Update corresponding tests to expect 401 status codes - Aligns with HTTP standards where 401 is for authentication failures and 403 is for authorization failures - Makes all HTTP authentication classes consistent with HTTPBasic which already used 401 Co-Authored-By: The Coding Gopher --- fastapi/security/http.py | 10 +++++----- tests/test_security_http_base_description.py | 2 +- tests/test_security_http_bearer.py | 4 ++-- tests/test_security_http_digest.py | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/fastapi/security/http.py b/fastapi/security/http.py index 9ab2df3c98e1e..e2c5fe475a9ec 100644 --- a/fastapi/security/http.py +++ b/fastapi/security/http.py @@ -87,7 +87,7 @@ async def __call__( 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" ) else: return None @@ -306,14 +306,14 @@ async def __call__( 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" ) 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", ) else: @@ -408,14 +408,14 @@ async def __call__( 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" ) 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", ) else: diff --git a/tests/test_security_http_base_description.py b/tests/test_security_http_base_description.py index bc79f32424b6a..06ae9299a2620 100644 --- a/tests/test_security_http_base_description.py +++ b/tests/test_security_http_base_description.py @@ -23,7 +23,7 @@ def test_security_http_base(): def test_security_http_base_no_credentials(): response = client.get("/users/me") - assert response.status_code == 403, response.text + assert response.status_code == 401, response.text assert response.json() == {"detail": "Not authenticated"} diff --git a/tests/test_security_http_bearer.py b/tests/test_security_http_bearer.py index 5b9e2d6919b09..044fe8d78f75a 100644 --- a/tests/test_security_http_bearer.py +++ b/tests/test_security_http_bearer.py @@ -23,13 +23,13 @@ def test_security_http_bearer(): def test_security_http_bearer_no_credentials(): response = client.get("/users/me") - assert response.status_code == 403, response.text + assert response.status_code == 401, response.text assert response.json() == {"detail": "Not authenticated"} def test_security_http_bearer_incorrect_scheme_credentials(): response = client.get("/users/me", headers={"Authorization": "Basic notreally"}) - assert response.status_code == 403, response.text + assert response.status_code == 401, response.text assert response.json() == {"detail": "Invalid authentication credentials"} diff --git a/tests/test_security_http_digest.py b/tests/test_security_http_digest.py index 133d35763c3ed..11b69d670b94f 100644 --- a/tests/test_security_http_digest.py +++ b/tests/test_security_http_digest.py @@ -23,7 +23,7 @@ def test_security_http_digest(): def test_security_http_digest_no_credentials(): response = client.get("/users/me") - assert response.status_code == 403, response.text + assert response.status_code == 401, response.text assert response.json() == {"detail": "Not authenticated"} @@ -31,7 +31,7 @@ def test_security_http_digest_incorrect_scheme_credentials(): response = client.get( "/users/me", headers={"Authorization": "Other invalidauthorization"} ) - assert response.status_code == 403, response.text + assert response.status_code == 401, response.text assert response.json() == {"detail": "Invalid authentication credentials"}