Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Warn the user when Authorization header is dropped from the request #9694

Open
1 task done
mananapr opened this issue Nov 7, 2024 · 10 comments
Open
1 task done

Warn the user when Authorization header is dropped from the request #9694

mananapr opened this issue Nov 7, 2024 · 10 comments
Labels
enhancement reproducer: missing This PR or issue lacks code, which reproduce the problem described or clearly understandable STR

Comments

@mananapr
Copy link

mananapr commented Nov 7, 2024

Is your feature request related to a problem?

As per the documentation -

Authorization header will be removed if you get redirected to a different host or protocol.

However this happens silently and can lead to confusion for the programmer.

Describe the solution you'd like

The library should throw a warning letting the user know that the header has been dropped.
I went through the code and it seems the change below should be sufficient -

diff --git a/aiohttp/client.py b/aiohttp/client.py
index dc1ab674..8154b11f 100644
--- a/aiohttp/client.py
+++ b/aiohttp/client.py
@@ -756,7 +756,13 @@ class ClientSession:
                             and url.origin() != redirect_origin
                         ):
                             auth = None
-                            headers.pop(hdrs.AUTHORIZATION, None)
+                            auth_header = headers.pop(hdrs.AUTHORIZATION, None)
+                            if auth_header:
+                                warnings.warn(
+                                    message = "Authorization header has been removed from the request",
+                                    category = RuntimeWarning,
+                                    source = self,
+                                )
 
                         url = parsed_redirect_url

Describe alternatives you've considered

Related component

Client

Additional context

No response

Code of Conduct

  • I agree to follow the aio-libs Code of Conduct
@asvetlov
Copy link
Member

asvetlov commented Nov 7, 2024

Sorry, I really doubt if the warning is suitable for described scenario.

Do you have an example of any alternative library that raises a warning on redirection?
For example, requests strips auth silently IIRC.

@mananapr
Copy link
Author

mananapr commented Nov 7, 2024

Actually I was previously using the requests library, and everything was functioning well. However, after transitioning the same code to aiohttp, I noticed that the authentication header was getting dropped due to the HTTP to HTTPS redirect.

I think it would be save debugging time for developers if they would know of this behavior either through a warning or through some other means.

@bdraco
Copy link
Member

bdraco commented Nov 7, 2024

Might be ok to keep the auth header on redirect to same origin when it's an upgrade from http to https but not when it's a downgrade from https to http. I couldn't find RFC guidance on the topic but maybe someone else knows

@Dreamsorcerer
Copy link
Member

I thought this had come up before and we did change it to that behaviour...

@Dreamsorcerer
Copy link
Member

Yeah, looks to me like that should work:

aiohttp/aiohttp/client.py

Lines 740 to 744 in 753460d

is_same_host_https_redirect = (
url.host == parsed_redirect_url.host
and parsed_redirect_url.scheme == "https"
and url.scheme == "http"
)

@asvetlov
Copy link
Member

asvetlov commented Nov 7, 2024

Maybe logging is slightly better than raising a warning?

@Dreamsorcerer
Copy link
Member

Logging would be more appropriate, but I'm not too sure that it's worth doing as this should be standard behaviour on all libraries.

@Dreamsorcerer
Copy link
Member

Actually I was previously using the requests library, and everything was functioning well. However, after transitioning the same code to aiohttp, I noticed that the authentication header was getting dropped due to the HTTP to HTTPS redirect.

Do you have a reproducer for this? Seems like this should have been working, so there may be an actual bug here.

@bdraco bdraco added the reproducer: missing This PR or issue lacks code, which reproduce the problem described or clearly understandable STR label Nov 7, 2024
@Dreamsorcerer Dreamsorcerer added the needs-info Issue is lacking sufficient information and will be closed if not provided label Nov 7, 2024
@mananapr
Copy link
Author

mananapr commented Nov 8, 2024

Actually I was previously using the requests library, and everything was functioning well. However, after transitioning the same code to aiohttp, I noticed that the authentication header was getting dropped due to the HTTP to HTTPS redirect.

Do you have a reproducer for this? Seems like this should have been working, so there may be an actual bug here.

If aiohttp preserve the auth headers for a HTTP -> HTTPS redirect then it indeed is a bug. I am making requests to a self-hosted Pocketbase instance. I'll share a minimal code snippet to demonstrate this issue

@mananapr
Copy link
Author

mananapr commented Nov 8, 2024

I wrote a small script to test this issue -

import aiohttp
import asyncio

base_url = "https://pocketbase.url/api"
auth_endpoint = f"{base_url}/collections/users/auth-with-password"
data_endpoint = f"{base_url}/collections/users/records"
username = "pocketbase-user"
password = "pocketbase-pass"
client_headers = {}

payload = {
    "identity": username,
    "password": password
}

async def main():
    async with aiohttp.ClientSession() as client:
        async with client.post(auth_endpoint, json=payload) as r:
            res = await r.json()
    assert "token" in res, "Invalid credentials"

    client_headers["Authorization"] = f"Bearer {res['token']}"

    async with aiohttp.ClientSession() as client:
        async with client.get(data_endpoint, headers=client_headers) as r:
            res = await r.json()

asyncio.run(main())

Below is the screenshot from pocketbase log dashboard when the request was made using HTTPS:
Screenshot 2024-11-08 at 12-19-41 Logs - Digantara's OCS - PocketBase

With HTTP:
Screenshot 2024-11-08 at 12-18-29 Logs - Digantara's OCS - PocketBase

As you can see, with HTTP the auth type is guest.
Below are the response headers for the HTTP request -

Alt-Svc :  h3=":443"; ma=2592000
Content-Length :  65
Content-Type :  application/json; charset=UTF-8
Date :  Fri, 08 Nov 2024 07:01:08 GMT
Server :  Caddy
Vary :  Origin
X-Content-Type-Options :  nosniff
X-Frame-Options :  SAMEORIGIN
X-Xss-Protection :  1; mode=block

@Dreamsorcerer Dreamsorcerer removed the needs-info Issue is lacking sufficient information and will be closed if not provided label Nov 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement reproducer: missing This PR or issue lacks code, which reproduce the problem described or clearly understandable STR
Projects
None yet
Development

No branches or pull requests

4 participants