-
-
Notifications
You must be signed in to change notification settings - Fork 9.4k
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
Default Authentication Overwrites Authentication Header #2062
Comments
Hey @joe42 There are several headers we don't expect users to set on their own because they really shouldn't be. If you want to prevent us from overwriting the header you should use the |
@sigmavirus24 Sorry, I should have mentioned that I already circumvented the problem by writing an authentication handler that does not modify the request. My post was meant as a suggestion to improve requests, as I suppose other users might run into the same problem.
I see. I do set several headers directly. Can you point me to a resource explaining which headers should not be set and why? Setting the headers directly seemed to be the way to go after reading the documentation's "Custom Headers" section. Thx, |
This is another of those situations where the right thing to do is not entirely obvious. For instance, what should the output be if this happens: import requests
r = requests.get(url, headers={'Authorization': auth}, auth=(user, pass)) Which of the two do we respect first? Our general principle is to respect the specific argument over the general one: For this reason, if you can auth via an Auth handler you should: that's how requests expects you to do it. |
@Lukasa : I can understand why you choose to design it this way. But I think that the result of the following request with default credentials in .netrc is not obvious at all. The point I do still not get is that I cannot imagine a case where a user would actually set a specific header (like in your example) and not expect it to be used by requests. Why should he bother doing this? So it might be good to either make it obvious (by documentation/warning/error) or to respect the users explicit settings.
|
I appreciate that you've shared your opinion @joe42. You're right that |
I had a related problem in #2066. My issue arose using Heroku’s API, which has two confusing factors relevant to this issue. The toolbelt quietly creates a .netrc file (mine was a year old; I didn't know it existed) and Heroku asks users to create a custom Authorization header:
I am now using |
First, I'd like to address something:
Your searching was not terribly effective. The docs front page contains a heading entitled 'Authentication'. That section contains a heading entitled netrc Authentication. This is not very difficult to find, and it's in exactly the location in the documentation I'd expect to find it. I'm open to linking to the Authentication section from the Custom Authentication section, but anything more seems incredible to me. Now, I feel like we've seen several related issues recently that warrant a more careful and broader response. The key problem is this: lots of users with previous HTTP client experience are expecting that requests will treat the headers they set as a fundamental source of truth: anything set in the headers should be treated as true by requests, or at least not removed. Requests has the opposite approach: headers are the lowest source of truth, and we feel quite happy to replace many kinds of headers that the user sets. Some examples:
We do this for very good reason: a headers-based API is utterly terrible. Affecting the library behaviour based on arbitrary key-value pairs set in the headers dictionary is asking for all kinds of terrible bugs, and is the kind of API-design-footgunnery that I'd expect to see from the OpenSSL project. Perhaps we need a section of the docs that explicitly says: you cannot trust that your headers will remain unmodified. Maybe even a list of the headers you absolutely should not set yourself (currently I think it's |
You’re right, I don't know how I missed that section and it mentions .netrc. My mistake! |
@migurski Whew, I was worried we had a bigger discoverability problem. Our docs are pretty large, sadly, which makes it easy to miss things. =( |
A central explanation of the headers approach you describe linked throughout the docs, wherever |
@Lukasa: Thanks for your detailed answer.
It would be great if you could add this sentence to the "Custom Headers" section, after it states:
|
@sigmavirus24 Do you feel like this would be a good addition to the docs? |
I feel like there have been a small number of users very violently surprised by the fact that we don't analyze the headers and do "smart" things based upon their presence (or lack thereof). I think adding to the Custom Headers section to say "By the way, we do no analysis of the headers you set so setting different headers will have no effect on the way requests handles your request." We should also mention the fact that we will happily (and with good reason) ignore headers set by the user in preference for headers we generate ourselves. That said, the idea of linking this throughout the docs wherever headers are mentioned is clearly overkill so please don't do that. |
At minimum, include a link from places where the |
Borrowing from past comments, here's what I think would address the issue well in the documentation:
Is there anything this doesn't address? Also, I feel like it should be more concise. Thoughts? |
@benjaminran Agreed, that looks like extremely useful documentation to me. If you open a pull request that adds it, I'll happily merge it. =) |
@benjaminran one thing: documentation shouldn't be overly verbose but they also shouldn't be too concise. The difficulty in writing documentation is finding the right balance such that everyone can understand what's going on without reading a novel. ;) |
As long as it’s made clear what is covered by “any alternative auth source,” then yes. |
That's a good point--that would probably confuse me if I saw it in unfamiliar documentation. How's this?
Also, is it clear from context that 'Authorization headers' refers to custom headers? |
A more accurate description would be:
The latter part is the root of this issue. |
I was about to suggest that we close this issue, since the documentation given by @benjaminran is now merged into the master docs (in Quickstart->Custom Headers). However I have one more question: what happens when the I suspect that |
+1 to preferring that |
This closes psf#2062 by clarifying which auth header takes precedence: 1. auth= 2. .netrc 3. headers=
@ibnIrshad please do not create a PR. That would be a breaking change that we will not accept until 3.0.0 |
What I meant is I will create a PR to clarify the current expected behaviour in the docs, not to change anything. Is it true that |
After scouring the tests, it seems
# Given auth should override and fail.
r = requests.get(url, auth=wrong_auth)
assert r.status_code == 401 |
This closes psf#2062 by clarifying in the docs which auth header takes precedence: 1st auth= 2nd .netrc 3rd headers= This precedence order is already tested in test_requests.py, in the test_basicauth_with_netrc method. Perhaps we should add further tests for non-basic auth schemes.
In my experience previously, |
Well the tests only cover basic auth. What kind of auth are you doing? |
Looking back on my original issue, looks I was setting and Authorization header: https://github.com/kennethreitz/requests/issues/2066 |
Hi,
And thanks for maintaining requests. When I set an Authorization header in a request, I do not expect it to be overwritten. I set up default credentials in my .netrc file (for automatizing the cadaver command line tool), and suddenly I could not authenticate to my service any longer.
Please check if an Authorization header does already exist in your default authorization handler, instead of overwriting it. I see that you documented this behaviour in the authentication section, but since I never used this form of authentication it took quite some time to find the problem. Also, overwriting a header that the user set does not seem to be a sensible implementation.
Thanks,
Joe
The text was updated successfully, but these errors were encountered: