Skip to content

Commit 14d9694

Browse files
[3.15] gh-53852 Proxy Auth failure to raise 407 instead of 401 (GH-160917) (#160919)
gh-53852 Proxy Auth failure to raise 407 instead of 401 (GH-160917) Proxy Auth failure to raise 407 instead of 401 https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/407 is the correct status code to raise for the Proxy Authentication. https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/401 is the generic code that can be raised for unauthorized response. (cherry picked from commit 2e1666f) Co-authored-by: Senthil Kumaran <senthil@python.org>
1 parent f4be2e5 commit 14d9694

4 files changed

Lines changed: 29 additions & 1 deletion

File tree

‎Lib/test/test_urllib2.py‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1871,6 +1871,25 @@ def test_unsupported_auth_digest_handler(self):
18711871
opener.add_handler(http_handler)
18721872
self.assertRaises(ValueError, opener.open, "http://www.example.com")
18731873

1874+
def test_digest_auth_failure_code(self):
1875+
# gh-53852: a failed proxy digest auth must report 407, not 401.
1876+
headers = http.client.HTTPMessage()
1877+
for handler_class, auth_header, code in [
1878+
(urllib.request.HTTPDigestAuthHandler,
1879+
'www-authenticate', 401),
1880+
(urllib.request.ProxyDigestAuthHandler,
1881+
'proxy-authenticate', 407)]:
1882+
with self.subTest(handler=handler_class.__name__):
1883+
handler = handler_class()
1884+
handler.retried = 6
1885+
req = Request("http://www.example.com/")
1886+
with self.assertRaises(urllib.error.HTTPError) as cm:
1887+
handler.http_error_auth_reqed(auth_header,
1888+
"www.example.com",
1889+
req, headers)
1890+
self.assertEqual(cm.exception.code, code)
1891+
cm.exception.close()
1892+
18741893
def test_unsupported_auth_basic_handler(self):
18751894
# While using BasicAuthHandler
18761895
opener = OpenerDirector()

‎Lib/test/test_urllib2_localnet.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,12 +368,14 @@ def test_proxy_with_bad_password_raises_httperror(self):
368368
self.digest_auth_handler.set_qop("auth")
369369
with self.assertRaises(urllib.error.HTTPError) as cm:
370370
self.opener.open(self.URL)
371+
self.assertEqual(cm.exception.code, 407)
371372
cm.exception.close()
372373

373374
def test_proxy_with_no_password_raises_httperror(self):
374375
self.digest_auth_handler.set_qop("auth")
375376
with self.assertRaises(urllib.error.HTTPError) as cm:
376377
self.opener.open(self.URL)
378+
self.assertEqual(cm.exception.code, 407)
377379
cm.exception.close()
378380

379381
def test_proxy_qop_auth_works(self):

‎Lib/urllib/request.py‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1093,7 +1093,11 @@ def http_error_auth_reqed(self, auth_header, host, req, headers):
10931093
# prompting for the information. Crap. This isn't great
10941094
# but it's better than the current 'repeat until recursion
10951095
# depth exceeded' approach <wink>
1096-
raise HTTPError(req.full_url, 401, "digest auth failed",
1096+
if auth_header.lower() == 'proxy-authenticate':
1097+
code = 407
1098+
else:
1099+
code = 401
1100+
raise HTTPError(req.full_url, code, "digest auth failed",
10971101
headers, None)
10981102
else:
10991103
self.retried += 1
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
:class:`urllib.request.ProxyDigestAuthHandler` now raises
2+
:exc:`~urllib.error.HTTPError` with status code 407 (Proxy Authentication
3+
Required) instead of 401 when proxy authentication fails.

0 commit comments

Comments
 (0)