Skip to content

Commit 32e8510

Browse files
committed
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.
1 parent 1fcc1a6 commit 32e8510

File tree

2 files changed

+18
-3
lines changed

2 files changed

+18
-3
lines changed

oauth2/__init__.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -470,11 +470,11 @@ def get_normalized_parameters(self):
470470
query = urlparse.urlparse(self.url)[4]
471471

472472
url_items = self._split_url_string(query).items()
473-
url_items = [(to_utf8(k), to_utf8(v)) for k, v in url_items if k != 'oauth_signature' ]
473+
url_items = [(to_utf8(k), to_utf8_optional_iterator(v)) for k, v in url_items if k != 'oauth_signature' ]
474474
items.extend(url_items)
475475

476476
items.sort()
477-
encoded_str = urllib.urlencode(items)
477+
encoded_str = urllib.urlencode(items, True)
478478
# Encode signature parameters per Oauth Core 1.0 protocol
479479
# spec draft 7, section 3.6
480480
# (http://tools.ietf.org/html/draft-hammer-oauth-07#section-3.6)
@@ -608,7 +608,10 @@ def _split_url_string(param_str):
608608
"""Turn URL string into parameters."""
609609
parameters = parse_qs(param_str.encode('utf-8'), keep_blank_values=True)
610610
for k, v in parameters.iteritems():
611-
parameters[k] = urllib.unquote(v[0])
611+
if len(v) == 1:
612+
parameters[k] = urllib.unquote(v[0])
613+
else:
614+
parameters[k] = sorted([urllib.unquote(s) for s in v])
612615
return parameters
613616

614617

tests/test_oauth.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,18 @@ def test_get_normalized_parameters_duplicate(self):
574574

575575
self.assertEquals(expected, res)
576576

577+
def test_get_normalized_parameters_multiple(self):
578+
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"
579+
580+
req = oauth.Request("GET", url)
581+
582+
res = req.get_normalized_parameters()
583+
584+
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'
585+
586+
self.assertEquals(expected, res)
587+
588+
577589
def test_get_normalized_parameters_from_url(self):
578590
# example copied from
579591
# https://github.com/ciaranj/node-oauth/blob/master/tests/oauth.js

0 commit comments

Comments
 (0)