Browse Source

Fix HTTPBasic to always include realm in WWW-Authenticate

pull/14647/head
westinjiang 6 months ago
parent
commit
39c87b0a2f
  1. 5
      fastapi/security/http.py
  2. 20
      tests/test_security_http_basic_default_realm.py
  3. 9
      tests/test_security_http_basic_optional.py

5
fastapi/security/http.py

@ -197,9 +197,8 @@ class HTTPBasic(HTTPBase):
self.auto_error = auto_error
def make_authenticate_headers(self) -> dict[str, str]:
if self.realm:
return {"WWW-Authenticate": f'Basic realm="{self.realm}"'}
return {"WWW-Authenticate": "Basic"}
realm = self.realm or "FastAPI"
return {"WWW-Authenticate": f'Basic realm="{realm}"'}
async def __call__( # type: ignore
self, request: Request

20
tests/test_security_http_basic_default_realm.py

@ -0,0 +1,20 @@
from fastapi import Depends, FastAPI
from fastapi.security import HTTPBasic, HTTPBasicCredentials
from starlette.testclient import TestClient
def test_http_basic_includes_realm_by_default():
app = FastAPI()
security = HTTPBasic() # no realm provided
@app.get("/protected")
def protected(credentials: HTTPBasicCredentials = Depends(security)):
return {"username": credentials.username}
client = TestClient(app)
resp = client.get("/protected")
assert resp.status_code == 401
www_auth = resp.headers.get("www-authenticate")
assert www_auth is not None
assert www_auth.startswith('Basic realm="')

9
tests/test_security_http_basic_optional.py

@ -36,8 +36,10 @@ def test_security_http_basic_invalid_credentials():
response = client.get(
"/users/me", headers={"Authorization": "Basic notabase64token"}
)
www_auth = response.headers["WWW-Authenticate"]
assert response.status_code == 401, response.text
assert response.headers["WWW-Authenticate"] == "Basic"
assert www_auth.lower().startswith("basic")
assert 'realm="' in www_auth.lower()
assert response.json() == {"detail": "Not authenticated"}
@ -45,8 +47,11 @@ def test_security_http_basic_non_basic_credentials():
payload = b64encode(b"johnsecret").decode("ascii")
auth_header = f"Basic {payload}"
response = client.get("/users/me", headers={"Authorization": auth_header})
www_auth = response.headers["WWW-Authenticate"]
assert response.status_code == 401, response.text
assert response.headers["WWW-Authenticate"] == "Basic"
assert www_auth.lower().startswith("basic")
assert 'realm="' in www_auth.lower()
assert response.json() == {"detail": "Not authenticated"}

Loading…
Cancel
Save