From 549279a36a815468a828a98c3375c1f7b2949285 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Peeters Date: Wed, 9 Oct 2024 16:25:04 +0200 Subject: [PATCH] Make redirect URL auth take precedence over input auth in client --- CHANGES/9436.bugfix.rst | 1 + aiohttp/client.py | 4 +++- docs/client_advanced.rst | 7 +++++++ tests/test_client_functional.py | 9 +++++++++ 4 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 CHANGES/9436.bugfix.rst diff --git a/CHANGES/9436.bugfix.rst b/CHANGES/9436.bugfix.rst new file mode 100644 index 0000000000..7bd7fbcfe2 --- /dev/null +++ b/CHANGES/9436.bugfix.rst @@ -0,0 +1 @@ +Authentication provided by a redirect now takes precedence over provided ``auth`` when making requests with the client -- by :user:`PLPeeters`. diff --git a/aiohttp/client.py b/aiohttp/client.py index 8ff1e1d43e..97f801e2e4 100644 --- a/aiohttp/client.py +++ b/aiohttp/client.py @@ -566,7 +566,9 @@ async def _request( "credentials encoded in URL" ) - if auth is None: + # Override the auth with the one from the URL only if we + # have no auth, or if we got an auth from a redirect URL + if auth is None or (history and auth_from_url is not None): auth = auth_from_url if auth is None and ( diff --git a/docs/client_advanced.rst b/docs/client_advanced.rst index 754f030d23..01ea3e9dc7 100644 --- a/docs/client_advanced.rst +++ b/docs/client_advanced.rst @@ -67,6 +67,13 @@ argument. An instance of :class:`BasicAuth` can be passed in like this:: async with ClientSession(auth=auth) as session: ... +Note that if the request is redirected and the redirect URL contains +credentials, those credentials will supersede any previously set credentials. +In other words, if ``http://user@example.com`` redirects to +``http://other_user@example.com``, the second request will be authenticated +as ``other_user``. Providing both the ``auth`` parameter and authentication in +the *initial* URL will result in a :exc:`ValueError`. + For other authentication flows, the ``Authorization`` header can be set directly:: diff --git a/tests/test_client_functional.py b/tests/test_client_functional.py index 5f46d020b3..2d3abf547d 100644 --- a/tests/test_client_functional.py +++ b/tests/test_client_functional.py @@ -2927,8 +2927,14 @@ async def test_creds_in_auth_and_url() -> None: await session.close() +@pytest.mark.parametrize( + ["check_redirect_auth_precedence"], + ([False], [True]), + ids=("redirect auth clash allowed", "redirect auth precedence"), +) async def test_creds_in_auth_and_redirect_url( create_server_for_url_and_handler: Callable[[URL, Handler], Awaitable[TestServer]], + check_redirect_auth_precedence: bool, ) -> None: url_from = URL("http://example.com") url_to = URL("http://user@example.com") @@ -2984,6 +2990,9 @@ async def close(self) -> None: assert str(resp.url) == "http://example.com" assert resp.status == 200 + if check_redirect_auth_precedence: + assert resp.request_info.headers.get("authorization") == "Basic dXNlcjo=" + @pytest.fixture def create_server_for_url_and_handler(