Skip to content

Commit 11bf0ec

Browse files
author
Omer Katz
authored
Merge branch 'master' into rm-2.7
2 parents 25dee45 + 1f3fc4b commit 11bf0ec

File tree

7 files changed

+103
-83
lines changed

7 files changed

+103
-83
lines changed

.travis.yml

-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ dist: xenial
44
cache: pip
55
matrix:
66
include:
7-
- python: 3.4
8-
env: TOXENV=py34
97
- python: 3.5
108
env: TOXENV=py35
119
- python: 3.6

README.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ OAuthLib - Python Framework for OAuth1 & OAuth2
22
===============================================
33

44
*A generic, spec-compliant, thorough implementation of the OAuth request-signing
5-
logic for Python 3.4+.*
5+
logic for Python 3.5+.
66
77
.. image:: https://travis-ci.org/oauthlib/oauthlib.svg?branch=master
88
:target: https://travis-ci.org/oauthlib/oauthlib

docs/contributing.rst

+11-7
Original file line numberDiff line numberDiff line change
@@ -152,26 +152,30 @@ request that fails this test suite will be **rejected**.
152152
Testing multiple versions of Python
153153
-----------------------------------
154154

155-
OAuthLib supports Python 3.4, 3.5, 3.6 and PyPy. Testing
155+
OAuthLib supports Python 3.5, 3.6, 3.7 and PyPy 2.7 & PyPy 3. Testing
156156
all versions conveniently can be done using `Tox`_.
157157

158158
.. sourcecode:: bash
159159

160160
$ tox
161161

162162
Tox requires you to have `virtualenv`_ installed as well as respective python
163-
version. For Ubuntu you can easily install all after adding one ppa.
163+
version. We recommend using `pyenv`_ to install those Python versions.
164+
165+
We recommend using the latest patch version for each Python version we support and the latest PyPy versions.
166+
The versions beloew may not be up to date.
164167

165168
.. sourcecode:: bash
166169

167-
$ sudo add-apt-repository ppa:fkrull/deadsnakes
168-
$ sudo apt-get update
169-
$ sudo apt-get install python3.2 python3.2-dev
170-
$ sudo apt-get install python3.3 python3.3-dev
171-
$ sudo apt-get install pypy pypy-dev
170+
$ pyenv install 3.5.7
171+
$ pyenv install 3.6.9
172+
$ pyenv install 3.7.4
173+
$ pyenv install pypy2.7-7.1.1
174+
$ pyenv install pypy3.6-7.1.1
172175

173176
.. _`Tox`: https://tox.readthedocs.io/en/latest/install.html
174177
.. _`virtualenv`: https://virtualenv.pypa.io/en/latest/installation/
178+
.. _`pyenv`: https://github.com/pyenv/pyenv
175179

176180
Test upstream applications
177181
-----------------------------------

oauthlib/oauth1/rfc5849/signature.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ def signature_base_string(http_method, base_str_uri,
8484
# (`Section 3.6`_).
8585
#
8686
# .. _`Section 3.4.1.2`: https://tools.ietf.org/html/rfc5849#section-3.4.1.2
87-
# .. _`Section 3.4.6`: https://tools.ietf.org/html/rfc5849#section-3.4.6
87+
# .. _`Section 3.6`: https://tools.ietf.org/html/rfc5849#section-3.6
8888
base_string += utils.escape(base_str_uri)
8989

9090
# 4. An "&" character (ASCII code 38).
@@ -94,7 +94,7 @@ def signature_base_string(http_method, base_str_uri,
9494
# being encoded (`Section 3.6`).
9595
#
9696
# .. _`Section 3.4.1.3.2`: https://tools.ietf.org/html/rfc5849#section-3.4.1.3.2
97-
# .. _`Section 3.4.6`: https://tools.ietf.org/html/rfc5849#section-3.4.6
97+
# .. _`Section 3.6`: https://tools.ietf.org/html/rfc5849#section-3.6
9898
base_string += utils.escape(normalized_encoded_request_parameters)
9999

100100
return base_string

setup.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ def fread(fn):
3636
platforms='any',
3737
license='BSD',
3838
packages=find_packages(exclude=('docs', 'tests', 'tests.*')),
39-
python_requires='>=3.4',
39+
python_requires='>=3.5',
4040
extras_require={
4141
'rsa': rsa_require,
4242
'signedtoken': signedtoken_require,
@@ -53,7 +53,6 @@ def fread(fn):
5353
'Operating System :: POSIX :: Linux',
5454
'Programming Language :: Python',
5555
'Programming Language :: Python :: 3',
56-
'Programming Language :: Python :: 3.4',
5756
'Programming Language :: Python :: 3.5',
5857
'Programming Language :: Python :: 3.6',
5958
'Programming Language :: Python :: 3.7',

tests/oauth1/rfc5849/test_signatures.py

+87-68
Original file line numberDiff line numberDiff line change
@@ -28,44 +28,46 @@ def decode(self):
2828
for k, v in self.items():
2929
self[k] = v.decode('utf-8')
3030

31-
uri_query = "b5=%3D%253D&a3=a&c%40=&a2=r%20b&c2=&a3=2+q"
31+
uri_query = "b5=%3D%253D&a3=a&c%40=&a2=r%20b"
3232
authorization_header = """OAuth realm="Example",
3333
oauth_consumer_key="9djdj82h48djs9d2",
3434
oauth_token="kkk9d7dh3k39sjv7",
3535
oauth_signature_method="HMAC-SHA1",
3636
oauth_timestamp="137131201",
3737
oauth_nonce="7d8f3e4a",
3838
oauth_signature="djosJKDKJSD8743243%2Fjdk33klY%3D" """.strip()
39-
body = "content=This+is+being+the+body+of+things"
39+
body = "c2&a3=2+q"
4040
http_method = b"post"
41-
base_string_url = quote("http://example.com/request?b5=%3D%253D"
42-
"&a3=a&c%40=&a2=r%20b").encode('utf-8')
43-
normalized_encoded_request_parameters = quote(
44-
'OAuth realm="Example",'
45-
'oauth_consumer_key="9djdj82h48djs9d2",'
46-
'oauth_token="kkk9d7dh3k39sjv7",'
47-
'oauth_signature_method="HMAC-SHA1",'
48-
'oauth_timestamp="137131201",'
49-
'oauth_nonce="7d8f3e4a",'
50-
'oauth_signature="bYT5CMsGcbgUdFHObYMEfcx6bsw%3D"'
51-
).encode('utf-8')
41+
base_string_url = (
42+
"http://example.com/request?{}".format(uri_query)).encode('utf-8')
43+
unnormalized_request_parameters =[
44+
('OAuth realm',"Example"),
45+
('oauth_consumer_key',"9djdj82h48djs9d2"),
46+
('oauth_token',"kkk9d7dh3k39sjv7"),
47+
('oauth_signature_method',"HMAC-SHA1"),
48+
('oauth_timestamp',"137131201"),
49+
('oauth_nonce',"7d8f3e4a"),
50+
('oauth_signature',"bYT5CMsGcbgUdFHObYMEfcx6bsw%3D")
51+
]
52+
normalized_encoded_request_params = sorted(
53+
[(quote(k), quote(v)) for k, v in unnormalized_request_parameters
54+
if k.lower() != "oauth realm"])
5255
client_secret = b"ECrDNoq1VYzzzzzzzzzyAK7TwZNtPnkqatqZZZZ"
5356
resource_owner_secret = b"just-a-string asdasd"
5457
control_base_string = (
55-
"POST&http%253A%2F%2Fexample.com%2Frequest%253F"
56-
"b5%253D%25253D%2525253D%2526"
57-
"a3%253D"
58-
"a%2526"
59-
"c%252540%253D%2526"
60-
"a2%253D"
61-
"r%252520b&"
62-
"OAuth%2520realm%253D%2522Example%2522%252C"
63-
"oauth_consumer_key%253D%25229djdj82h48djs9d2%2522%252C"
64-
"oauth_token%253D%2522kkk9d7dh3k39sjv7%2522%252C"
65-
"oauth_signature_method%253D%2522HMAC-SHA1%2522%252C"
66-
"oauth_timestamp%253D%2522137131201%2522%252C"
67-
"oauth_nonce%253D%25227d8f3e4a%2522%252C"
68-
"oauth_signature%253D%2522bYT5CMsGcbgUdFHObYMEfcx6bsw%25253D%2522")
58+
"POST&http%3A%2F%2Fexample.com%2Frequest&"
59+
"a2%3Dr%2520b%26"
60+
"a3%3D2%2520q%26"
61+
"a3%3Da%26"
62+
"b5%3D%253D%25253D%26"
63+
"c%2540%3D%26"
64+
"c2%3D%26"
65+
"oauth_consumer_key%3D9djdj82h48djs9d2%26"
66+
"oauth_nonce%3D7d8f3e4a%26"
67+
"oauth_signature_method%3DHMAC-SHA1%26"
68+
"oauth_timestamp%3D137131201%26"
69+
"oauth_token%3Dkkk9d7dh3k39sjv7"
70+
)
6971

7072
def setUp(self):
7173
self.client = self.MockClient(
@@ -87,34 +89,42 @@ def test_signature_base_string(self):
8789
oauth_timestamp="137131201",
8890
oauth_nonce="7d8f3e4a",
8991
oauth_signature="bYT5CMsGcbgUdFHObYMEfcx6bsw%3D"
92+
c2&a3=2+q
9093
9194
Sample Base string generated and tested against::
92-
93-
POST&http%253A%2F%2Fexample.com%2Frequest%253Fb5%253D%25253D%252525
94-
3D%2526a3%253Da%2526c%252540%253D%2526a2%253Dr%252520b&OAuth%2520re
95-
alm%253D%2522Example%2522%252Coauth_consumer_key%253D%25229djdj82h4
96-
8djs9d2%2522%252Coauth_token%253D%2522kkk9d7dh3k39sjv7%2522%252Coau
97-
th_signature_method%253D%2522HMAC-SHA1%2522%252Coauth_timestamp%253
98-
D%2522137131201%2522%252Coauth_nonce%253D%25227d8f3e4a%2522%252Coau
99-
th_signature%253D%2522bYT5CMsGcbgUdFHObYMEfcx6bsw%25253D%2522
95+
POST&http%3A%2F%2Fexample.com%2Frequest&a2%3Dr%2520b%26a3%3D2%2520q
96+
%26a3%3Da%26b5%3D%253D%25253D%26c%2540%3D%26c2%3D%26oauth_consumer_
97+
key%3D9djdj82h48djs9d2%26oauth_nonce%3D7d8f3e4a%26oauth_signature_m
98+
ethod%3DHMAC-SHA1%26oauth_timestamp%3D137131201%26oauth_token%3Dkkk
99+
9d7dh3k39sjv7
100100
"""
101+
102+
self.assertRaises(ValueError, base_string_uri, self.base_string_url)
103+
base_string_url = base_string_uri(self.base_string_url.decode('utf-8'))
104+
base_string_url = base_string_url.encode('utf-8')
105+
querystring = self.base_string_url.split(b'?', 1)[1]
106+
query_params = collect_parameters(querystring.decode('utf-8'),
107+
body=self.body)
108+
normalized_encoded_query_params = sorted(
109+
[(quote(k), quote(v)) for k, v in query_params])
110+
normalized_request_string = "&".join(sorted(
111+
['='.join((k, v)) for k, v in (
112+
self.normalized_encoded_request_params +
113+
normalized_encoded_query_params)
114+
if k.lower() != 'oauth_signature']))
101115
self.assertRaises(ValueError, signature_base_string,
102116
self.http_method,
103-
self.base_string_url,
104-
self.normalized_encoded_request_parameters)
117+
base_string_url,
118+
normalized_request_string)
105119
self.assertRaises(ValueError, signature_base_string,
106120
self.http_method.decode('utf-8'),
107-
self.base_string_url,
108-
self.normalized_encoded_request_parameters)
109-
self.assertRaises(ValueError, signature_base_string,
110-
self.http_method.decode('utf-8'),
111-
self.base_string_url.decode('utf-8'),
112-
self.normalized_encoded_request_parameters)
121+
base_string_url,
122+
normalized_request_string)
113123

114124
base_string = signature_base_string(
115125
self.http_method.decode('utf-8'),
116-
self.base_string_url.decode('utf-8'),
117-
self.normalized_encoded_request_parameters.decode('utf-8')
126+
base_string_url.decode('utf-8'),
127+
normalized_request_string
118128
)
119129

120130
self.assertEqual(self.control_base_string, base_string)
@@ -182,9 +192,7 @@ def test_collect_parameters(self):
182192
correct_parameters = [('b5', '=%3D'),
183193
('a3', 'a'),
184194
('c@', ''),
185-
('a2', 'r b'),
186-
('c2', ''),
187-
('a3', '2 q')]
195+
('a2', 'r b')]
188196
self.assertEqual(sorted(parameters), sorted(correct_parameters))
189197

190198
headers = {'Authorization': self.authorization_header}
@@ -208,13 +216,14 @@ def test_collect_parameters(self):
208216
sorted(correct_parameters_with_realm))
209217

210218
# Add in the body.
211-
# TODO: Add more content for the body. Daniel Greenfeld 2012/03/12
212219
# Redo again the checks against all the parameters. Duplicated code
213220
# but better safety
214221
parameters = collect_parameters(
215222
uri_query=self.uri_query, body=self.body, headers=headers)
216223
correct_parameters += [
217-
('content', 'This is being the body of things')]
224+
('c2', ''),
225+
('a3', '2 q')
226+
]
218227
self.assertEqual(sorted(parameters), sorted(correct_parameters))
219228

220229
def test_normalize_parameters(self):
@@ -230,7 +239,7 @@ def test_normalize_parameters(self):
230239

231240
# Lets see if things are in order
232241
# check to see that querystring keys come in alphanumeric order:
233-
querystring_keys = ['a2', 'a3', 'b5', 'content', 'oauth_consumer_key',
242+
querystring_keys = ['a2', 'a3', 'b5', 'oauth_consumer_key',
234243
'oauth_nonce', 'oauth_signature_method',
235244
'oauth_timestamp', 'oauth_token']
236245
index = -1 # start at -1 because the 'a2' key starts at index 0
@@ -240,7 +249,8 @@ def test_normalize_parameters(self):
240249

241250
# Control signature created using openssl:
242251
# echo -n $(cat <message>) | openssl dgst -binary -hmac <key> | base64
243-
control_signature = "Uau4O9Kpd2k6rvh7UZN/RN+RG7Y="
252+
control_signature = "mwd09YMxVd2XJ1gudNaBuAuKKuY="
253+
control_signature_s = "wsdNmjGB7lvis0UJuPAmjvX/PXw="
244254

245255
def test_sign_hmac_sha1(self):
246256
"""Verifying HMAC-SHA1 signature against one created by OpenSSL."""
@@ -250,10 +260,22 @@ def test_sign_hmac_sha1(self):
250260

251261
sign = sign_hmac_sha1(self.control_base_string,
252262
self.client_secret.decode('utf-8'),
253-
self.resource_owner_secret.decode('utf-8'))
263+
b'')
254264
self.assertEqual(len(sign), 28)
255265
self.assertEqual(sign, self.control_signature)
256266

267+
def test_sign_hmac_sha1_with_secret(self):
268+
"""Verifying HMAC-SHA1 signature against one created by OpenSSL."""
269+
270+
self.assertRaises(ValueError, sign_hmac_sha1, self.control_base_string,
271+
self.client_secret, self.resource_owner_secret)
272+
273+
sign = sign_hmac_sha1(self.control_base_string,
274+
self.client_secret.decode('utf-8'),
275+
self.resource_owner_secret.decode('utf-8'))
276+
self.assertEqual(len(sign), 28)
277+
self.assertEqual(sign, self.control_signature_s)
278+
257279
def test_sign_hmac_sha1_with_client(self):
258280
self.assertRaises(ValueError,
259281
sign_hmac_sha1_with_client,
@@ -265,19 +287,16 @@ def test_sign_hmac_sha1_with_client(self):
265287
self.control_base_string, self.client)
266288

267289
self.assertEqual(len(sign), 28)
268-
self.assertEqual(sign, self.control_signature)
290+
self.assertEqual(sign, self.control_signature_s)
269291

270292

271293
control_base_string_rsa_sha1 = (
272-
b"POST&http%253A%2F%2Fexample.com%2Frequest%253Fb5%253D"
273-
b"%25253D%2525253D%2526a3%253Da%2526c%252540%253D%2526"
274-
b"a2%253Dr%252520b&OAuth%2520realm%253D%2522Example%25"
275-
b"22%252Coauth_consumer_key%253D%25229djdj82h48djs9d2"
276-
b"%2522%252Coauth_token%253D%2522kkk9d7dh3k39sjv7%2522"
277-
b"%252Coauth_signature_method%253D%2522HMAC-SHA1%2522"
278-
b"%252Coauth_timestamp%253D%2522137131201%2522%252Coau"
279-
b"th_nonce%253D%25227d8f3e4a%2522%252Coauth_signature"
280-
b"%253D%2522bYT5CMsGcbgUdFHObYMEfcx6bsw%25253D%2522")
294+
b"POST&http%3A%2F%2Fexample.com%2Frequest&a2%3Dr%2520b%26a3%3D2%2520q"
295+
b"%26a3%3Da%26b5%3D%253D%25253D%26c%2540%3D%26c2%3D%26oauth_consumer_"
296+
b"key%3D9djdj82h48djs9d2%26oauth_nonce%3D7d8f3e4a%26oauth_signature_m"
297+
b"ethod%3DHMAC-SHA1%26oauth_timestamp%3D137131201%26oauth_token%3Dkkk"
298+
b"9d7dh3k39sjv7"
299+
)
281300

282301
# Generated using: $ openssl genrsa -out <key>.pem 1024
283302
# PEM encoding requires the key to be concatenated with
@@ -301,14 +320,14 @@ def test_sign_hmac_sha1_with_client(self):
301320
@property
302321
def control_signature_rsa_sha1(self):
303322
# Base string saved in "<message>". Signature obtained using:
304-
# $ echo -n $(cat <message>) | openssl dgst -sign <key>.pem | base64
323+
# $ echo -n $(cat <msg>) | openssl dgst -sha1 -sign <key>.pem | base64
305324
# where echo -n suppresses the last linebreak.
306325
return (
307-
"zV5g8ArdMuJuOXlH8XOqfLHS11XdthfIn4HReDm7jz8JmgLabHGmVBqCkCfZoFJPH"
308-
"dka7tLvCplK/jsV4FUOnftrJOQhbXguuBdi87/hmxOFKLmQYqqlEW7BdXmwKLZcki"
309-
"qq3qE5XziBgKSAFRkxJ4gmJAymvJBtrJYN9728rK8="
310-
)
326+
"mFY2KOEnlYWsTvUA+5kxuBIcvBYXu+ljw9ttVJQxKduMueGSVPCB1tK1PlqVLK738"
327+
"HK0t19ecBJfb6rMxUwrriw+MlBO+jpojkZIWccw1J4cAb4qu4M81DbpUAq4j/1w/Q"
328+
"yTR4TWCODlEfN7Zfgy8+pf+TjiXfIwRC1jEWbuL1E="
311329

330+
)
312331

313332
def test_sign_rsa_sha1(self):
314333
"""Verify RSA-SHA1 signature against one created by OpenSSL."""

tox.ini

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[tox]
2-
envlist = py34,py35,py36,py37,pypy,pypy3,docs,readme,bandit
2+
envlist = py35,py36,py37,pypy,pypy3,docs,readme,bandit
33

44
[testenv]
55
deps=

0 commit comments

Comments
 (0)