summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOmer Katz <omer.drow@gmail.com>2019-08-29 13:52:59 +0300
committerGitHub <noreply@github.com>2019-08-29 13:52:59 +0300
commit11bf0eca2857f5330237e574630dd916d53cd573 (patch)
tree71f3d2ecee2ffd32da6f030558d0eed91d953895
parent25dee45f9991bf009bcc5eebd5987046a4bf7779 (diff)
parent1f3fc4bfd4fd51711798186591bf3e3ba5a894be (diff)
downloadoauthlib-11bf0eca2857f5330237e574630dd916d53cd573.tar.gz
Merge branch 'master' into rm-2.7
-rw-r--r--.travis.yml2
-rw-r--r--README.rst2
-rw-r--r--docs/contributing.rst18
-rw-r--r--oauthlib/oauth1/rfc5849/signature.py4
-rwxr-xr-xsetup.py3
-rw-r--r--tests/oauth1/rfc5849/test_signatures.py155
-rw-r--r--tox.ini2
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
diff --git a/README.rst b/README.rst
index 48b9853..0b42133 100644
--- a/README.rst
+++ b/README.rst
@@ -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
diff --git a/setup.py b/setup.py
index 438b8ae..9e248dd 100755
--- a/setup.py
+++ b/setup.py
@@ -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."""
diff --git a/tox.ini b/tox.ini
index 1e325ae..22f6f33 100644
--- a/tox.ini
+++ b/tox.ini
@@ -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=