From 32e85109c656e8607d486c0f2f1b0189960c70ee Mon Sep 17 00:00:00 2001 From: Jon Parise Date: Tue, 16 Aug 2011 17:28:05 -0700 Subject: [PATCH] Adding support for repeated URL parameters. It is legal for a URL parameter to be repeated multiple times in the query string with different values. The previous code was only using the first occurence of the parameter when normalizing the URL, which ultimately causes a signature mismatch. --- oauth2/__init__.py | 9 ++++++--- tests/test_oauth.py | 12 ++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/oauth2/__init__.py b/oauth2/__init__.py index 835270e3..095614c3 100644 --- a/oauth2/__init__.py +++ b/oauth2/__init__.py @@ -470,11 +470,11 @@ def get_normalized_parameters(self): query = urlparse.urlparse(self.url)[4] url_items = self._split_url_string(query).items() - url_items = [(to_utf8(k), to_utf8(v)) for k, v in url_items if k != 'oauth_signature' ] + url_items = [(to_utf8(k), to_utf8_optional_iterator(v)) for k, v in url_items if k != 'oauth_signature' ] items.extend(url_items) items.sort() - encoded_str = urllib.urlencode(items) + encoded_str = urllib.urlencode(items, True) # Encode signature parameters per Oauth Core 1.0 protocol # spec draft 7, section 3.6 # (http://tools.ietf.org/html/draft-hammer-oauth-07#section-3.6) @@ -608,7 +608,10 @@ def _split_url_string(param_str): """Turn URL string into parameters.""" parameters = parse_qs(param_str.encode('utf-8'), keep_blank_values=True) for k, v in parameters.iteritems(): - parameters[k] = urllib.unquote(v[0]) + if len(v) == 1: + parameters[k] = urllib.unquote(v[0]) + else: + parameters[k] = sorted([urllib.unquote(s) for s in v]) return parameters diff --git a/tests/test_oauth.py b/tests/test_oauth.py index 099e5794..f212fc65 100644 --- a/tests/test_oauth.py +++ b/tests/test_oauth.py @@ -574,6 +574,18 @@ def test_get_normalized_parameters_duplicate(self): self.assertEquals(expected, res) + def test_get_normalized_parameters_multiple(self): + url = "http://example.com/v2/search/videos?oauth_nonce=79815175&oauth_timestamp=1295397962&oauth_consumer_key=mykey&oauth_signature_method=HMAC-SHA1&oauth_version=1.0&offset=10&oauth_signature=spWLI%2FGQjid7sQVd5%2FarahRxzJg%3D&tag=one&tag=two" + + req = oauth.Request("GET", url) + + res = req.get_normalized_parameters() + + expected='oauth_consumer_key=mykey&oauth_nonce=79815175&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1295397962&oauth_version=1.0&offset=10&tag=one&tag=two' + + self.assertEquals(expected, res) + + def test_get_normalized_parameters_from_url(self): # example copied from # https://github.com/ciaranj/node-oauth/blob/master/tests/oauth.js