diff options
author | Omer Katz <omer.drow@gmail.com> | 2019-08-29 13:52:59 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-08-29 13:52:59 +0300 |
commit | 11bf0eca2857f5330237e574630dd916d53cd573 (patch) | |
tree | 71f3d2ecee2ffd32da6f030558d0eed91d953895 | |
parent | 25dee45f9991bf009bcc5eebd5987046a4bf7779 (diff) | |
parent | 1f3fc4bfd4fd51711798186591bf3e3ba5a894be (diff) | |
download | oauthlib-11bf0eca2857f5330237e574630dd916d53cd573.tar.gz |
Merge branch 'master' into rm-2.7
-rw-r--r-- | .travis.yml | 2 | ||||
-rw-r--r-- | README.rst | 2 | ||||
-rw-r--r-- | docs/contributing.rst | 18 | ||||
-rw-r--r-- | oauthlib/oauth1/rfc5849/signature.py | 4 | ||||
-rwxr-xr-x | setup.py | 3 | ||||
-rw-r--r-- | tests/oauth1/rfc5849/test_signatures.py | 155 | ||||
-rw-r--r-- | tox.ini | 2 |
7 files changed, 103 insertions, 83 deletions
diff --git a/.travis.yml b/.travis.yml index c7ec677..fbf676b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,8 +4,6 @@ dist: xenial cache: pip matrix: include: - - python: 3.4 - env: TOXENV=py34 - python: 3.5 env: TOXENV=py35 - python: 3.6 @@ -2,7 +2,7 @@ OAuthLib - Python Framework for OAuth1 & OAuth2 =============================================== *A generic, spec-compliant, thorough implementation of the OAuth request-signing -logic for Python 3.4+.* +logic for Python 3.5+. .. image:: https://travis-ci.org/oauthlib/oauthlib.svg?branch=master :target: https://travis-ci.org/oauthlib/oauthlib diff --git a/docs/contributing.rst b/docs/contributing.rst index 8244afd..4a46e3b 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -152,7 +152,7 @@ request that fails this test suite will be **rejected**. Testing multiple versions of Python ----------------------------------- -OAuthLib supports Python 3.4, 3.5, 3.6 and PyPy. Testing +OAuthLib supports Python 3.5, 3.6, 3.7 and PyPy 2.7 & PyPy 3. Testing all versions conveniently can be done using `Tox`_. .. sourcecode:: bash @@ -160,18 +160,22 @@ all versions conveniently can be done using `Tox`_. $ tox Tox requires you to have `virtualenv`_ installed as well as respective python -version. For Ubuntu you can easily install all after adding one ppa. +version. We recommend using `pyenv`_ to install those Python versions. + +We recommend using the latest patch version for each Python version we support and the latest PyPy versions. +The versions beloew may not be up to date. .. sourcecode:: bash - $ sudo add-apt-repository ppa:fkrull/deadsnakes - $ sudo apt-get update - $ sudo apt-get install python3.2 python3.2-dev - $ sudo apt-get install python3.3 python3.3-dev - $ sudo apt-get install pypy pypy-dev + $ pyenv install 3.5.7 + $ pyenv install 3.6.9 + $ pyenv install 3.7.4 + $ pyenv install pypy2.7-7.1.1 + $ pyenv install pypy3.6-7.1.1 .. _`Tox`: https://tox.readthedocs.io/en/latest/install.html .. _`virtualenv`: https://virtualenv.pypa.io/en/latest/installation/ +.. _`pyenv`: https://github.com/pyenv/pyenv Test upstream applications ----------------------------------- diff --git a/oauthlib/oauth1/rfc5849/signature.py b/oauthlib/oauth1/rfc5849/signature.py index 43688cb..fdc359e 100644 --- a/oauthlib/oauth1/rfc5849/signature.py +++ b/oauthlib/oauth1/rfc5849/signature.py @@ -84,7 +84,7 @@ def signature_base_string(http_method, base_str_uri, # (`Section 3.6`_). # # .. _`Section 3.4.1.2`: https://tools.ietf.org/html/rfc5849#section-3.4.1.2 - # .. _`Section 3.4.6`: https://tools.ietf.org/html/rfc5849#section-3.4.6 + # .. _`Section 3.6`: https://tools.ietf.org/html/rfc5849#section-3.6 base_string += utils.escape(base_str_uri) # 4. An "&" character (ASCII code 38). @@ -94,7 +94,7 @@ def signature_base_string(http_method, base_str_uri, # being encoded (`Section 3.6`). # # .. _`Section 3.4.1.3.2`: https://tools.ietf.org/html/rfc5849#section-3.4.1.3.2 - # .. _`Section 3.4.6`: https://tools.ietf.org/html/rfc5849#section-3.4.6 + # .. _`Section 3.6`: https://tools.ietf.org/html/rfc5849#section-3.6 base_string += utils.escape(normalized_encoded_request_parameters) return base_string @@ -36,7 +36,7 @@ setup( platforms='any', license='BSD', packages=find_packages(exclude=('docs', 'tests', 'tests.*')), - python_requires='>=3.4', + python_requires='>=3.5', extras_require={ 'rsa': rsa_require, 'signedtoken': signedtoken_require, @@ -53,7 +53,6 @@ setup( 'Operating System :: POSIX :: Linux', 'Programming Language :: Python', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', diff --git a/tests/oauth1/rfc5849/test_signatures.py b/tests/oauth1/rfc5849/test_signatures.py index 2c1700f..89219f7 100644 --- a/tests/oauth1/rfc5849/test_signatures.py +++ b/tests/oauth1/rfc5849/test_signatures.py @@ -28,7 +28,7 @@ class SignatureTests(TestCase): for k, v in self.items(): self[k] = v.decode('utf-8') - uri_query = "b5=%3D%253D&a3=a&c%40=&a2=r%20b&c2=&a3=2+q" + uri_query = "b5=%3D%253D&a3=a&c%40=&a2=r%20b" authorization_header = """OAuth realm="Example", oauth_consumer_key="9djdj82h48djs9d2", oauth_token="kkk9d7dh3k39sjv7", @@ -36,36 +36,38 @@ class SignatureTests(TestCase): oauth_timestamp="137131201", oauth_nonce="7d8f3e4a", oauth_signature="djosJKDKJSD8743243%2Fjdk33klY%3D" """.strip() - body = "content=This+is+being+the+body+of+things" + body = "c2&a3=2+q" http_method = b"post" - base_string_url = quote("http://example.com/request?b5=%3D%253D" - "&a3=a&c%40=&a2=r%20b").encode('utf-8') - normalized_encoded_request_parameters = quote( - 'OAuth realm="Example",' - 'oauth_consumer_key="9djdj82h48djs9d2",' - 'oauth_token="kkk9d7dh3k39sjv7",' - 'oauth_signature_method="HMAC-SHA1",' - 'oauth_timestamp="137131201",' - 'oauth_nonce="7d8f3e4a",' - 'oauth_signature="bYT5CMsGcbgUdFHObYMEfcx6bsw%3D"' - ).encode('utf-8') + base_string_url = ( + "http://example.com/request?{}".format(uri_query)).encode('utf-8') + unnormalized_request_parameters =[ + ('OAuth realm',"Example"), + ('oauth_consumer_key',"9djdj82h48djs9d2"), + ('oauth_token',"kkk9d7dh3k39sjv7"), + ('oauth_signature_method',"HMAC-SHA1"), + ('oauth_timestamp',"137131201"), + ('oauth_nonce',"7d8f3e4a"), + ('oauth_signature',"bYT5CMsGcbgUdFHObYMEfcx6bsw%3D") + ] + normalized_encoded_request_params = sorted( + [(quote(k), quote(v)) for k, v in unnormalized_request_parameters + if k.lower() != "oauth realm"]) client_secret = b"ECrDNoq1VYzzzzzzzzzyAK7TwZNtPnkqatqZZZZ" resource_owner_secret = b"just-a-string asdasd" control_base_string = ( - "POST&http%253A%2F%2Fexample.com%2Frequest%253F" - "b5%253D%25253D%2525253D%2526" - "a3%253D" - "a%2526" - "c%252540%253D%2526" - "a2%253D" - "r%252520b&" - "OAuth%2520realm%253D%2522Example%2522%252C" - "oauth_consumer_key%253D%25229djdj82h48djs9d2%2522%252C" - "oauth_token%253D%2522kkk9d7dh3k39sjv7%2522%252C" - "oauth_signature_method%253D%2522HMAC-SHA1%2522%252C" - "oauth_timestamp%253D%2522137131201%2522%252C" - "oauth_nonce%253D%25227d8f3e4a%2522%252C" - "oauth_signature%253D%2522bYT5CMsGcbgUdFHObYMEfcx6bsw%25253D%2522") + "POST&http%3A%2F%2Fexample.com%2Frequest&" + "a2%3Dr%2520b%26" + "a3%3D2%2520q%26" + "a3%3Da%26" + "b5%3D%253D%25253D%26" + "c%2540%3D%26" + "c2%3D%26" + "oauth_consumer_key%3D9djdj82h48djs9d2%26" + "oauth_nonce%3D7d8f3e4a%26" + "oauth_signature_method%3DHMAC-SHA1%26" + "oauth_timestamp%3D137131201%26" + "oauth_token%3Dkkk9d7dh3k39sjv7" + ) def setUp(self): self.client = self.MockClient( @@ -87,34 +89,42 @@ class SignatureTests(TestCase): oauth_timestamp="137131201", oauth_nonce="7d8f3e4a", oauth_signature="bYT5CMsGcbgUdFHObYMEfcx6bsw%3D" + c2&a3=2+q Sample Base string generated and tested against:: - - POST&http%253A%2F%2Fexample.com%2Frequest%253Fb5%253D%25253D%252525 - 3D%2526a3%253Da%2526c%252540%253D%2526a2%253Dr%252520b&OAuth%2520re - alm%253D%2522Example%2522%252Coauth_consumer_key%253D%25229djdj82h4 - 8djs9d2%2522%252Coauth_token%253D%2522kkk9d7dh3k39sjv7%2522%252Coau - th_signature_method%253D%2522HMAC-SHA1%2522%252Coauth_timestamp%253 - D%2522137131201%2522%252Coauth_nonce%253D%25227d8f3e4a%2522%252Coau - th_signature%253D%2522bYT5CMsGcbgUdFHObYMEfcx6bsw%25253D%2522 + POST&http%3A%2F%2Fexample.com%2Frequest&a2%3Dr%2520b%26a3%3D2%2520q + %26a3%3Da%26b5%3D%253D%25253D%26c%2540%3D%26c2%3D%26oauth_consumer_ + key%3D9djdj82h48djs9d2%26oauth_nonce%3D7d8f3e4a%26oauth_signature_m + ethod%3DHMAC-SHA1%26oauth_timestamp%3D137131201%26oauth_token%3Dkkk + 9d7dh3k39sjv7 """ + + self.assertRaises(ValueError, base_string_uri, self.base_string_url) + base_string_url = base_string_uri(self.base_string_url.decode('utf-8')) + base_string_url = base_string_url.encode('utf-8') + querystring = self.base_string_url.split(b'?', 1)[1] + query_params = collect_parameters(querystring.decode('utf-8'), + body=self.body) + normalized_encoded_query_params = sorted( + [(quote(k), quote(v)) for k, v in query_params]) + normalized_request_string = "&".join(sorted( + ['='.join((k, v)) for k, v in ( + self.normalized_encoded_request_params + + normalized_encoded_query_params) + if k.lower() != 'oauth_signature'])) self.assertRaises(ValueError, signature_base_string, self.http_method, - self.base_string_url, - self.normalized_encoded_request_parameters) + base_string_url, + normalized_request_string) self.assertRaises(ValueError, signature_base_string, self.http_method.decode('utf-8'), - self.base_string_url, - self.normalized_encoded_request_parameters) - self.assertRaises(ValueError, signature_base_string, - self.http_method.decode('utf-8'), - self.base_string_url.decode('utf-8'), - self.normalized_encoded_request_parameters) + base_string_url, + normalized_request_string) base_string = signature_base_string( self.http_method.decode('utf-8'), - self.base_string_url.decode('utf-8'), - self.normalized_encoded_request_parameters.decode('utf-8') + base_string_url.decode('utf-8'), + normalized_request_string ) self.assertEqual(self.control_base_string, base_string) @@ -182,9 +192,7 @@ class SignatureTests(TestCase): correct_parameters = [('b5', '=%3D'), ('a3', 'a'), ('c@', ''), - ('a2', 'r b'), - ('c2', ''), - ('a3', '2 q')] + ('a2', 'r b')] self.assertEqual(sorted(parameters), sorted(correct_parameters)) headers = {'Authorization': self.authorization_header} @@ -208,13 +216,14 @@ class SignatureTests(TestCase): sorted(correct_parameters_with_realm)) # Add in the body. - # TODO: Add more content for the body. Daniel Greenfeld 2012/03/12 # Redo again the checks against all the parameters. Duplicated code # but better safety parameters = collect_parameters( uri_query=self.uri_query, body=self.body, headers=headers) correct_parameters += [ - ('content', 'This is being the body of things')] + ('c2', ''), + ('a3', '2 q') + ] self.assertEqual(sorted(parameters), sorted(correct_parameters)) def test_normalize_parameters(self): @@ -230,7 +239,7 @@ class SignatureTests(TestCase): # Lets see if things are in order # check to see that querystring keys come in alphanumeric order: - querystring_keys = ['a2', 'a3', 'b5', 'content', 'oauth_consumer_key', + querystring_keys = ['a2', 'a3', 'b5', 'oauth_consumer_key', 'oauth_nonce', 'oauth_signature_method', 'oauth_timestamp', 'oauth_token'] index = -1 # start at -1 because the 'a2' key starts at index 0 @@ -240,7 +249,8 @@ class SignatureTests(TestCase): # Control signature created using openssl: # echo -n $(cat <message>) | openssl dgst -binary -hmac <key> | base64 - control_signature = "Uau4O9Kpd2k6rvh7UZN/RN+RG7Y=" + control_signature = "mwd09YMxVd2XJ1gudNaBuAuKKuY=" + control_signature_s = "wsdNmjGB7lvis0UJuPAmjvX/PXw=" def test_sign_hmac_sha1(self): """Verifying HMAC-SHA1 signature against one created by OpenSSL.""" @@ -250,10 +260,22 @@ class SignatureTests(TestCase): sign = sign_hmac_sha1(self.control_base_string, self.client_secret.decode('utf-8'), - self.resource_owner_secret.decode('utf-8')) + b'') self.assertEqual(len(sign), 28) self.assertEqual(sign, self.control_signature) + def test_sign_hmac_sha1_with_secret(self): + """Verifying HMAC-SHA1 signature against one created by OpenSSL.""" + + self.assertRaises(ValueError, sign_hmac_sha1, self.control_base_string, + self.client_secret, self.resource_owner_secret) + + sign = sign_hmac_sha1(self.control_base_string, + self.client_secret.decode('utf-8'), + self.resource_owner_secret.decode('utf-8')) + self.assertEqual(len(sign), 28) + self.assertEqual(sign, self.control_signature_s) + def test_sign_hmac_sha1_with_client(self): self.assertRaises(ValueError, sign_hmac_sha1_with_client, @@ -265,19 +287,16 @@ class SignatureTests(TestCase): self.control_base_string, self.client) self.assertEqual(len(sign), 28) - self.assertEqual(sign, self.control_signature) + self.assertEqual(sign, self.control_signature_s) control_base_string_rsa_sha1 = ( - b"POST&http%253A%2F%2Fexample.com%2Frequest%253Fb5%253D" - b"%25253D%2525253D%2526a3%253Da%2526c%252540%253D%2526" - b"a2%253Dr%252520b&OAuth%2520realm%253D%2522Example%25" - b"22%252Coauth_consumer_key%253D%25229djdj82h48djs9d2" - b"%2522%252Coauth_token%253D%2522kkk9d7dh3k39sjv7%2522" - b"%252Coauth_signature_method%253D%2522HMAC-SHA1%2522" - b"%252Coauth_timestamp%253D%2522137131201%2522%252Coau" - b"th_nonce%253D%25227d8f3e4a%2522%252Coauth_signature" - b"%253D%2522bYT5CMsGcbgUdFHObYMEfcx6bsw%25253D%2522") + b"POST&http%3A%2F%2Fexample.com%2Frequest&a2%3Dr%2520b%26a3%3D2%2520q" + b"%26a3%3Da%26b5%3D%253D%25253D%26c%2540%3D%26c2%3D%26oauth_consumer_" + b"key%3D9djdj82h48djs9d2%26oauth_nonce%3D7d8f3e4a%26oauth_signature_m" + b"ethod%3DHMAC-SHA1%26oauth_timestamp%3D137131201%26oauth_token%3Dkkk" + b"9d7dh3k39sjv7" + ) # Generated using: $ openssl genrsa -out <key>.pem 1024 # PEM encoding requires the key to be concatenated with @@ -301,14 +320,14 @@ Ga6FHdjGPcfajt+nrpB1n8UQBEH9ZxniokR/IPvdMlxqXA== @property def control_signature_rsa_sha1(self): # Base string saved in "<message>". Signature obtained using: - # $ echo -n $(cat <message>) | openssl dgst -sign <key>.pem | base64 + # $ echo -n $(cat <msg>) | openssl dgst -sha1 -sign <key>.pem | base64 # where echo -n suppresses the last linebreak. return ( - "zV5g8ArdMuJuOXlH8XOqfLHS11XdthfIn4HReDm7jz8JmgLabHGmVBqCkCfZoFJPH" - "dka7tLvCplK/jsV4FUOnftrJOQhbXguuBdi87/hmxOFKLmQYqqlEW7BdXmwKLZcki" - "qq3qE5XziBgKSAFRkxJ4gmJAymvJBtrJYN9728rK8=" - ) + "mFY2KOEnlYWsTvUA+5kxuBIcvBYXu+ljw9ttVJQxKduMueGSVPCB1tK1PlqVLK738" + "HK0t19ecBJfb6rMxUwrriw+MlBO+jpojkZIWccw1J4cAb4qu4M81DbpUAq4j/1w/Q" + "yTR4TWCODlEfN7Zfgy8+pf+TjiXfIwRC1jEWbuL1E=" + ) def test_sign_rsa_sha1(self): """Verify RSA-SHA1 signature against one created by OpenSSL.""" @@ -1,5 +1,5 @@ [tox] -envlist = py34,py35,py36,py37,pypy,pypy3,docs,readme,bandit +envlist = py35,py36,py37,pypy,pypy3,docs,readme,bandit [testenv] deps= |