From a78a25ea23a940fcc510226a2dd33731d81fb213 Mon Sep 17 00:00:00 2001 From: wangxiyuan Date: Tue, 10 Apr 2018 14:40:13 +0800 Subject: [PATCH] Double quote www_authenticate_uri Based on the RFCs[1], in http header, a string of text is parsed as a single value if it is quoted using double-quote marks. This patch change the single quote to double quote in the header "WWW-Authenticate" which is returned when 401 error raises. [1]: https://tools.ietf.org/html/rfc7230#section-3.2.6 https://tools.ietf.org/html/rfc7235#section-2.1 Change-Id: I524c93d30607ea6ab70de92ceea207ee77f34c25 Closes-bug: #1762362 --- keystonemiddleware/auth_token/__init__.py | 2 +- .../auth_token/test_auth_token_middleware.py | 18 +++++++++--------- .../notes/bug-1762362-3d092b15c7bab3a4.yaml | 6 ++++++ 3 files changed, 16 insertions(+), 10 deletions(-) create mode 100644 releasenotes/notes/bug-1762362-3d092b15c7bab3a4.yaml diff --git a/keystonemiddleware/auth_token/__init__.py b/keystonemiddleware/auth_token/__init__.py index 09a78035..f0d22098 100644 --- a/keystonemiddleware/auth_token/__init__.py +++ b/keystonemiddleware/auth_token/__init__.py @@ -679,7 +679,7 @@ class AuthProtocol(BaseAuthProtocol): @property def _reject_auth_headers(self): - header_val = 'Keystone uri=\'%s\'' % self._www_authenticate_uri + header_val = 'Keystone uri="%s"' % self._www_authenticate_uri return [('WWW-Authenticate', header_val)] def _token_hashes(self, token): diff --git a/keystonemiddleware/tests/unit/auth_token/test_auth_token_middleware.py b/keystonemiddleware/tests/unit/auth_token/test_auth_token_middleware.py index efcd7efd..cd6de8c3 100644 --- a/keystonemiddleware/tests/unit/auth_token/test_auth_token_middleware.py +++ b/keystonemiddleware/tests/unit/auth_token/test_auth_token_middleware.py @@ -955,37 +955,37 @@ class CommonAuthTokenMiddlewareTest(object): resp = self.call_middleware(headers={'X-Auth-Token': 'invalid-token'}, expected_status=401) - self.assertEqual("Keystone uri='https://keystone.example.com:1234'", + self.assertEqual('Keystone uri="https://keystone.example.com:1234"', resp.headers['WWW-Authenticate']) def test_request_invalid_signed_token(self): token = self.examples.INVALID_SIGNED_TOKEN resp = self.call_middleware(headers={'X-Auth-Token': token}, expected_status=401) - self.assertEqual("Keystone uri='https://keystone.example.com:1234'", + self.assertEqual('Keystone uri="https://keystone.example.com:1234"', resp.headers['WWW-Authenticate']) def test_request_invalid_signed_pkiz_token(self): token = self.examples.INVALID_SIGNED_PKIZ_TOKEN resp = self.call_middleware(headers={'X-Auth-Token': token}, expected_status=401) - self.assertEqual("Keystone uri='https://keystone.example.com:1234'", + self.assertEqual('Keystone uri="https://keystone.example.com:1234"', resp.headers['WWW-Authenticate']) def test_request_no_token(self): resp = self.call_middleware(expected_status=401) - self.assertEqual("Keystone uri='https://keystone.example.com:1234'", + self.assertEqual('Keystone uri="https://keystone.example.com:1234"', resp.headers['WWW-Authenticate']) def test_request_no_token_http(self): resp = self.call_middleware(method='HEAD', expected_status=401) - self.assertEqual("Keystone uri='https://keystone.example.com:1234'", + self.assertEqual('Keystone uri="https://keystone.example.com:1234"', resp.headers['WWW-Authenticate']) def test_request_blank_token(self): resp = self.call_middleware(headers={'X-Auth-Token': ''}, expected_status=401) - self.assertEqual("Keystone uri='https://keystone.example.com:1234'", + self.assertEqual('Keystone uri="https://keystone.example.com:1234"', resp.headers['WWW-Authenticate']) def _get_cached_token(self, token, mode='md5'): @@ -1119,7 +1119,7 @@ class CommonAuthTokenMiddlewareTest(object): self.assert_valid_last_url(token) else: self.assertEqual(401, resp.status_int) - msg = "Keystone uri='https://keystone.example.com:1234'" + msg = 'Keystone uri="https://keystone.example.com:1234"' self.assertEqual(msg, resp.headers['WWW-Authenticate']) def test_uuid_bind_token_disabled_with_kerb_user(self): @@ -1645,7 +1645,7 @@ class v2AuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest, """Unscoped requests with no default tenant ID should be rejected.""" resp = self.call_middleware(headers={'X-Auth-Token': token}, expected_status=401) - self.assertEqual("Keystone uri='https://keystone.example.com:1234'", + self.assertEqual('Keystone uri="https://keystone.example.com:1234"', resp.headers['WWW-Authenticate']) def test_unscoped_uuid_token_receives_401(self): @@ -2013,7 +2013,7 @@ class DelayedAuthTests(BaseAuthTokenMiddlewareTest): resp = self.call(middleware, expected_status=401) self.assertEqual(six.b(body), resp.body) - self.assertEqual("Keystone uri='%s'" % www_authenticate_uri, + self.assertEqual('Keystone uri="%s"' % www_authenticate_uri, resp.headers['WWW-Authenticate']) def test_delayed_auth_values(self): diff --git a/releasenotes/notes/bug-1762362-3d092b15c7bab3a4.yaml b/releasenotes/notes/bug-1762362-3d092b15c7bab3a4.yaml new file mode 100644 index 00000000..16deea34 --- /dev/null +++ b/releasenotes/notes/bug-1762362-3d092b15c7bab3a4.yaml @@ -0,0 +1,6 @@ +--- +features: + - > + [`bug 1762362 `_] + The value of the header "WWW-Authenticate" in a 401 (Unauthorized) response + now is double quoted to follow the RFC requirement.