diff --git a/starlette/middleware/cors.py b/starlette/middleware/cors.py index 36ba9f93f..fd23658f0 100644 --- a/starlette/middleware/cors.py +++ b/starlette/middleware/cors.py @@ -162,10 +162,11 @@ async def send(self, message: Message, send: Send, request_headers: Headers) -> headers.update(self.simple_headers) origin = request_headers["Origin"] has_cookie = "cookie" in request_headers + has_authorization = "authorization" in request_headers - # If request includes any cookie headers, then we must respond - # with the specific origin instead of '*'. - if self.allow_all_origins and has_cookie: + # If request includes any cookie or authorization headers, then we must + # respond with the specific origin instead of '*'. + if self.allow_all_origins and (has_cookie or has_authorization): self.allow_explicit_origin(headers, origin) # If we only allow specific origins, then we have to mirror back diff --git a/tests/middleware/test_cors.py b/tests/middleware/test_cors.py index cbee7d6e7..ec5773b53 100644 --- a/tests/middleware/test_cors.py +++ b/tests/middleware/test_cors.py @@ -425,6 +425,28 @@ def homepage(request: Request) -> PlainTextResponse: assert "access-control-allow-credentials" not in response.headers +def test_cors_authorization_header_returns_specific_origin( + test_client_factory: TestClientFactory, +) -> None: + def homepage(request: Request) -> PlainTextResponse: + return PlainTextResponse("Homepage", status_code=200) + + app = Starlette( + routes=[Route("/", endpoint=homepage)], + middleware=[Middleware(CORSMiddleware, allow_origins=["*"])], + ) + client = test_client_factory(app) + + # Test request with Authorization header returns specific origin instead of '*' + headers = {"Origin": "https://example.org", "Authorization": "Bearer token123"} + response = client.get("/", headers=headers) + assert response.status_code == 200 + assert response.text == "Homepage" + assert response.headers["access-control-allow-origin"] == "https://example.org" + assert response.headers["vary"] == "Origin" + assert "access-control-allow-credentials" not in response.headers + + def test_cors_vary_header_defaults_to_origin( test_client_factory: TestClientFactory, ) -> None: