Skip to content

Commit 270a30a

Browse files
[3.14] gh-53852 Proxy Auth failure to raise 407 instead of 401 (GH-160917) (#160920)
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 edf93de commit 270a30a

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
@@ -1854,6 +1854,25 @@ def test_unsupported_auth_digest_handler(self):
18541854
opener.add_handler(http_handler)
18551855
self.assertRaises(ValueError, opener.open, "http://www.example.com")
18561856

1857+
def test_digest_auth_failure_code(self):
1858+
# gh-53852: a failed proxy digest auth must report 407, not 401.
1859+
headers = http.client.HTTPMessage()
1860+
for handler_class, auth_header, code in [
1861+
(urllib.request.HTTPDigestAuthHandler,
1862+
'www-authenticate', 401),
1863+
(urllib.request.ProxyDigestAuthHandler,
1864+
'proxy-authenticate', 407)]:
1865+
with self.subTest(handler=handler_class.__name__):
1866+
handler = handler_class()
1867+
handler.retried = 6
1868+
req = Request("http://www.example.com/")
1869+
with self.assertRaises(urllib.error.HTTPError) as cm:
1870+
handler.http_error_auth_reqed(auth_header,
1871+
"www.example.com",
1872+
req, headers)
1873+
self.assertEqual(cm.exception.code, code)
1874+
cm.exception.close()
1875+
18571876
def test_unsupported_auth_basic_handler(self):
18581877
# While using BasicAuthHandler
18591878
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
@@ -1091,7 +1091,11 @@ def http_error_auth_reqed(self, auth_header, host, req, headers):
10911091
# prompting for the information. Crap. This isn't great
10921092
# but it's better than the current 'repeat until recursion
10931093
# depth exceeded' approach <wink>
1094-
raise HTTPError(req.full_url, 401, "digest auth failed",
1094+
if auth_header.lower() == 'proxy-authenticate':
1095+
code = 407
1096+
else:
1097+
code = 401
1098+
raise HTTPError(req.full_url, code, "digest auth failed",
10951099
headers, None)
10961100
else:
10971101
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)