requests / requests-oauthlib Goto Github PK
View Code? Open in Web Editor NEWOAuthlib support for Python-Requests!
Home Page: https://requests-oauthlib.readthedocs.org/
License: ISC License
OAuthlib support for Python-Requests!
Home Page: https://requests-oauthlib.readthedocs.org/
License: ISC License
Using requests 0.14.2 (tried 1.0.4 too and think I got the same thing) and Python 2.7.3. Getting this error when trying to make a request. Relevant part of stack trace:
File "/Users/john/.virtualenvs/dashboard/lib/python2.7/site-packages/oauthlib/oauth1/rfc5849/__init__.py", line 215, in sign
request.oauth_params.append(('oauth_signature', self.get_oauth_signature(request)))
File "/Users/john/.virtualenvs/dashboard/lib/python2.7/site-packages/oauthlib/oauth1/rfc5849/__init__.py", line 67, in get_oauth_signature
uri, headers, body = self._render(request)
File "/Users/john/.virtualenvs/dashboard/lib/python2.7/site-packages/oauthlib/oauth1/rfc5849/__init__.py", line 137, in _render
headers = parameters.prepare_headers(request.oauth_params, request.headers, realm=realm)
File "/Users/john/.virtualenvs/dashboard/lib/python2.7/site-packages/oauthlib/oauth1/rfc5849/utils.py", line 32, in wrapper
return target(params, *args, **kwargs)
File "/Users/john/.virtualenvs/dashboard/lib/python2.7/site-packages/oauthlib/oauth1/rfc5849/parameters.py", line 58, in prepare_headers
escaped_value = utils.escape(value)
File "/Users/john/.virtualenvs/dashboard/lib/python2.7/site-packages/oauthlib/oauth1/rfc5849/utils.py", line 56, in escape
raise ValueError('Only unicode objects are escapable.')
ValueError: Only unicode objects are escapable.
oauthlib.common.extract_params returns a somewhat nonsensical list (but a value python considers true nonetheless) for most JSON values, and the code in OAuth1.call doesn't check if we've set a Content-Type before overriding it, so JSON-bodied posts have their Content-Type overridden, causing them to fail with most JSON-based REST APIs.
Would be nice if they could be formally coupled. Such as maybe rename the former to something like fetch_token_kwargs
, which can serve as the default if no fetch_token(..., **kwargs)
are provided as an override?
extract_params might guess form encoding on certain non form encoded bodies, such as a json string literal. Guessing should only be done when no content type is given.
See https://plus.google.com/u/0/116864647864271086168/posts/Vg7tzeGAcEK for more details.
OAuth2Session always calls self.new_state()
in authorization_url
even if the user specified a state in the constructor. I think that should be changed.
As a side note I think the state
and state_generator
arguments should be mutually exclusive to prevent errors on the user side.
The documentation at https://oauthlib.readthedocs.org/en/latest/client.html says:
The OAuth 1 spec only covers signing of x-www-url-formencoded information. If you are sending some other kind of data in the body (say, multipart file uploads), these don’t count as a body for the purposes of signing. Don’t provide the body to Client.sign() if it isn’t x-www-url-formencoded data.
I can't see any way of doing this with requests-oauthlib - there doesn't seem to be a way of preventing it from signing the body when called like so:
r = requests.post(url, files=files, auth=oauth)
...or am I missing something?
session.fetch_token('https://foo.bar.com:8001/access_token/', client_id=client_id, client_secret=client_secret)
Traceback (most recent call last):
File "", line 1, in
File "/home/omer/.virtualenvs/deployment/local/lib/python2.7/site-packages/requests_oauthlib/oauth2_session.py", line 160, in fetch_token
self._client.parse_request_body_response(r.text, scope=self.scope)
File "/home/omer/.virtualenvs/deployment/local/lib/python2.7/site-packages/oauthlib/oauth2/rfc6749/clients/backend_application.py", line 156, in parse_request_body_response
self.token = parse_token_response(body, scope=scope)
File "/home/omer/.virtualenvs/deployment/local/lib/python2.7/site-packages/oauthlib/oauth2/rfc6749/parameters.py", line 297, in parse_token_response
validate_token_parameters(params, scope)
File "/home/omer/.virtualenvs/deployment/local/lib/python2.7/site-packages/oauthlib/oauth2/rfc6749/parameters.py", line 310, in validate_token_parameters
raise MissingTokenTypeError()
oauthlib.oauth2.rfc6749.errors.MissingTokenTypeError
In OAuth{1,2}Session Response.content (byte-like string) might be used in a way that can cause problems, especially in py3, and should be replaced with Response.text (unicode string). See #42 for how this was problematic with json parsing.
Tests should be added to make sure regressions are not introduced as well.
I recently tried requests-oauthlib with django-oauth-toolkit following the webapplication flow tutorial.
If the provider use '' char in client_id
and client_secret
strings that will be interpreted as an escape sequence and you'll obtain an InvalidClientId error when you try to exchange the token.
For instance if the client_id XQcKemTaz}^1GW6C@_;@KHDh@yo\4Br\jv/,;5\1
:
>>> client_id = 'XQcKemTaz}^1GW6C@_;@KHDh@yo\4Br\jv/,;5\1'
>>> print client_id
XQcKemTaz}^1GW6C@_;@KHDh@yo�Br\jv/,;5�
As you can see the input value and output value are different.
To avoid this behavior you can use raw python string syntax:
>>> client_id = r'XQcKemTaz}^1GW6C@_;@KHDh@yo\4Br\jv/,;5\1'
>>> print client_id
XQcKemTaz}^1GW6C@_;@KHDh@yo\4Br\jv/,;5\1
I can open a PR if you want
Would be great to have a docs directory setup. One with path set properly for syntax highlighting =)
Bonus would be to create a few .rst files in there that uses autodoc to generate docs from existing source files.
the documentation at the cheese factory & on Crate has the wrong library:
from requests_authlib import OAuth1
instead of
from requests_oauthlib import OAuth1
@Lukasa asked me to raise this error in this repo as well:
Hey guys, just wanted to bring this issue forward. With requests 1.0.0
So the error came from when I went to test Twython
with the new requests
release.
And because it bothered me, I removed self
from all variables that used self
like self.callback_url
Also, I striped the code out of the actual function get_authentication_tokens
(so that's why you'll see ref to that function in the traceback)
import requests
from requests_oauthlib import OAuth1
app_key = u'SUPERDUPERSECRETKEY'
app_secret = u'SUPERDUPERSECRETSECRET'
callback_url = 'http://example.com'
headers = {'User-Agent': 'Twython v2.5.5'}
auth = OAuth1(app_key, app_secret,
signature_type='auth_header')
request_args['oauth_callback'] = callback_url
response = requests.get('https://api.twitter.com/oauth/request_token', params=request_args, headers=headers, auth=auth)
if response.status_code != 200:
raise TwythonAuthError("Seems something couldn't be verified with your OAuth junk. Error: %s, Message: %s" % (response.status_code, response.content))
request_tokens = dict(parse_qsl(response.content))
if not request_tokens:
raise TwythonError('Unable to decode request tokens.')
oauth_callback_confirmed = request_tokens.get('oauth_callback_confirmed') == 'true'
auth_url_params = {
'oauth_token': request_tokens['oauth_token'],
}
# Use old-style callback argument if server didn't accept new-style
if callback_url and not oauth_callback_confirmed:
auth_url_params['oauth_callback'] = callback_url
request_tokens['auth_url'] = 'https://api.twitter.com/oauth/authenticate?' + urllib.urlencode(auth_url_params)
return request_tokens
Anyways, when I try to run this code I get the error:
Traceback (most recent call last):
File "twython.py", line 585, in <module>
auth_props = t.get_authentication_tokens()
File "twython.py", line 271, in get_authentication_tokens
response = requests.get('https://api.twitter.com/oauth/request_token', params=request_args, headers=headers, auth=self.auth)
File "/Users/mikehelmick/.virtualenv/twython/lib/python2.7/site-packages/requests/api.py", line 49, in get
return request('get', url, **kwargs)
File "/Users/mikehelmick/.virtualenv/twython/lib/python2.7/site-packages/requests/api.py", line 38, in request
return session.request(method=method, url=url, **kwargs)
File "/Users/mikehelmick/.virtualenv/twython/lib/python2.7/site-packages/requests/sessions.py", line 253, in request
prep = req.prepare()
File "/Users/mikehelmick/.virtualenv/twython/lib/python2.7/site-packages/requests/models.py", line 200, in prepare
p.prepare_auth(self.auth)
File "/Users/mikehelmick/.virtualenv/twython/lib/python2.7/site-packages/requests/models.py", line 336, in prepare_auth
r = auth(self)
File "/Users/mikehelmick/.virtualenv/twython/lib/python2.7/site-packages/requests_oauthlib/core.py", line 41, in __call__
decoded_body = extract_params(r.data)
AttributeError: 'PreparedRequest' object has no attribute 'data'
Hello im using requests-oauthlib in windows 7 and i installed the module from pip. I get this error every time i'm using it to call the Oauth1 class.
from requests_oauthlib import OAuth1
File "C:\Python27\lib\site-packages\requests_oauthlib\__init__.py", line 1, in <module> from .core import OAuth1
File "C:\Python27\lib\site-packages\requests_oauthlib\core.py", line 3, in <module> from oauthlib.common import extract_params
ImportError: No module named oauthlib.common
Can you help me figure out why i get this error ?
Thank you for your help.
The current 0.3.0 release is pretty old and we've fixed a few bugs, as well as added a massive amount of functionality. I want to get this library into a shape where we can pass it to Kenneth all he has to do is tag it and go. @ib-lundgren, @sigmavirus24, is there anything we need to do?
I've been trying to wrap my head around refresh tokens and the OAuth2 web example (https://requests-oauthlib.readthedocs.org/en/latest/examples/real_world_example.html). Would it be possible to provide an example usage of refresh tokens in that context? Where in the code it would go, etc?
Just a suggestion! 😁
I raised this issue with flask-oauthlib but maybe this is more appropriate here? I've been having an issue trying to fetch a token on a flask-oauthlib server. The complete details are here (along with logging info for the client and the server):
Since I have not gotten a response or even acknowledgement I'm wondering if I posted it in the right place and thought it might be more appropriate to post here. I'm completely out of ideas and have been trying to resolve this for quite some days now.
I started using requests-oauthlib a few days ago. I came to the point where I need to use oauth_nonce, oauth_timestamp and oauth_version in the program that I am using to learn REST. I reviewed the code and went over the tutorial but I didn't find any of the above-mentioned parameters. I am new to REST and I may have missed or didn't fully understand the library, therefore I wanted to ask if you have support for oauth_nonce, oauth_timestamp and oauth_version.
Thanks in advance.
Python 3. Unable to make Post requests with versions later than 0.3.0.
0.3.1 introduced a TypeError that's been fixed. 0.3.2 and 0.3.2 produce a Duplicate Content-Length header bug on post requests. Get requests work properly.
I made the following modifications to core.py on 0.3.3 to make it work:
Replaced return string.decode('utf-8') with return string on line 17
Removed decoding='utf-8' from line 32
Removed decoding=decoding from line 41
This part is still missing documentation https://requests-oauthlib.readthedocs.org/en/latest/oauth2_workflow.html#mobile-application-flow
Does anybody have an example on hand? I'll write the docs, but would be nice to have some working code to start from. Is this tested?
OAuth2 requires a secure communication channel, i.e. HTTPS, and the library refuses connections on HTTPS. This is inconvenient when developing OAuth2-based applications. Setting up HTTPS locally is quite some work, especially with clients that verify the certificate chain.
Would you accept a pull request that adds an option to disable the HTTPS check?
Or alternatively, is there another way for requests-oauthlib to address this issue that I could implement?
Hi,
I'm adapting the GitHub Flask example on RTD to my own use case (the Beatport API). I continue to get the same error when attempting the final step, fetch_access_token:
"ValueError: Not a valid urlencoded string."
I'm wondering if anyone has any pointers?
Gist:
https://gist.github.com/newsomc/7974765
Thanks,
Clint
I tried running the tests and got a failure in tests.test_oauth1_session.OAuth1SessionTest.test_signature_methods. Basically the test is using the rsa functionality of oauthlib, which isn't installed by default. I've listed my steps to reproduce below.
Here are some ways I can think of to rectify the situation. If you pick which one you like, or suggest another, I'll make the fix and submit a pull request.
My OS is Ubuntu 13.04 and for this test I used python 2.7. virtualenv version is 1.9.1
Reproduce steps:
virtualenv env --no-site-packages
python setup.py install
pip install nose mock
nosetests tests
. I get the stack trace below.I have confirmed that option (1) makes the tests pass.
Stack trace:
(env)frank@frank-leoben-ubuntu:~/boxes/requests-oauthlib-notmine$ nosetests tests
..........E..........
======================================================================
ERROR: test_signature_methods (tests.test_oauth1_session.OAuth1SessionTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/frank/boxes/requests-oauthlib-notmine/env/local/lib/python2.7/site-packages/mock.py", line 1201, in patched
return func(*args, **keywargs)
File "/home/frank/boxes/requests-oauthlib-notmine/tests/test_oauth1_session.py", line 100, in test_signature_methods
auth.post('https://i.b')
File "/home/frank/boxes/requests-oauthlib-notmine/env/local/lib/python2.7/site-packages/requests-1.2.3-py2.7.egg/requests/sessions.py", line 377, in post
return self.request('POST', url, data=data, **kwargs)
File "/home/frank/boxes/requests-oauthlib-notmine/env/local/lib/python2.7/site-packages/requests-1.2.3-py2.7.egg/requests/sessions.py", line 324, in request
prep = req.prepare()
File "/home/frank/boxes/requests-oauthlib-notmine/env/local/lib/python2.7/site-packages/requests-1.2.3-py2.7.egg/requests/models.py", line 226, in prepare
p.prepare_auth(self.auth, self.url)
File "/home/frank/boxes/requests-oauthlib-notmine/env/local/lib/python2.7/site-packages/requests-1.2.3-py2.7.egg/requests/models.py", line 428, in prepare_auth
r = auth(self)
File "/home/frank/boxes/requests-oauthlib-notmine/requests_oauthlib/core.py", line 65, in __call__
unicode(r.url), unicode(r.method), None, r.headers)
File "build/bdist.linux-x86_64/egg/oauthlib/oauth1/rfc5849/__init__.py", line 281, in sign
request.oauth_params.append(('oauth_signature', self.get_oauth_signature(request)))
File "build/bdist.linux-x86_64/egg/oauthlib/oauth1/rfc5849/__init__.py", line 135, in get_oauth_signature
sig = signature.sign_rsa_sha1(base_string, self.rsa_key)
File "build/bdist.linux-x86_64/egg/oauthlib/oauth1/rfc5849/signature.py", line 479, in sign_rsa_sha1
from Crypto.PublicKey import RSA
ImportError: No module named Crypto.PublicKey
-------------------- >> begin captured logging << --------------------
oauthlib: DEBUG: Collected params: [(u'oauth_version', u'1.0'), (u'oauth_consumer_key', u'foo'), (u'oauth_signature_method', u'HMAC-SHA1'), (u'oauth_nonce', u'abc'), (u'oauth_timestamp', u'123')]
oauthlib: DEBUG: Normalized params: oauth_consumer_key=foo&oauth_nonce=abc&oauth_signature_method=HMAC-SHA1&oauth_timestamp=123&oauth_version=1.0
oauthlib: DEBUG: Normalized URI: https://i.b/
oauthlib: DEBUG: Base signing string: POST&https%3A%2F%2Fi.b%2F&oauth_consumer_key%3Dfoo%26oauth_nonce%3Dabc%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D123%26oauth_version%3D1.0
oauthlib: DEBUG: Signature: h2sRqLArjhlc5p3FTkuNogVHlKE=
oauthlib: DEBUG: Encoding URI, headers and body to utf-8.
oauthlib: DEBUG: Encoding URI, headers and body to utf-8.
oauthlib: DEBUG: Collected params: [(u'oauth_version', u'1.0'), (u'oauth_consumer_key', u'foo'), (u'oauth_signature_method', u'RSA-SHA1'), (u'oauth_nonce', u'abc'), (u'oauth_timestamp', u'123')]
oauthlib: DEBUG: Normalized params: oauth_consumer_key=foo&oauth_nonce=abc&oauth_signature_method=RSA-SHA1&oauth_timestamp=123&oauth_version=1.0
oauthlib: DEBUG: Normalized URI: https://i.b/
oauthlib: DEBUG: Base signing string: POST&https%3A%2F%2Fi.b%2F&oauth_consumer_key%3Dfoo%26oauth_nonce%3Dabc%26oauth_signature_method%3DRSA-SHA1%26oauth_timestamp%3D123%26oauth_version%3D1.0
--------------------- >> end captured logging << ---------------------
----------------------------------------------------------------------
Ran 21 tests in 0.640s
FAILED (errors=1)
The acronym uri
is used all over the place in code and documentation, where it should be url
. Also url
is used in a bunch of places too, where it is already correct.
This is a semantic nitpick, and probably not worth breaking backwards compatibility over. But worth keeping in mind in case you ever end up doing a big refactor and see an opportunity to clean this up. :)
Feel free to close this bug if it doesn't make sense to pursue at this time.
The code provided in the Google OAuth 2 tutorial (https://requests-oauthlib.readthedocs.org/en/latest/examples/google.html) gives an exception:
raise MissingCodeError("Missing code parameter in response.")
oauthlib.oauth2.rfc6749.errors.MissingCodeError: Missing code parameter in response.
The problem is not in the web application client that I created with the Google API console, because I wrote another piece of code doing the same thing but using the Python library google-api-python-client and it works.
Any idea?
In the file: core.py, the following line of code causes a TypeError Exception to be thrown when you are trying to send a multipart data post request.
The error message that I'm seeing is: TypeError: Type str doesn't support the buffer API
Here's the problematic line of code in core.py:
is_form_encoded = (CONTENT_TYPE_FORM_URLENCODED in headers.get('Content-Type', ''))
Use-case: When sending a POST request (with the Requests API) using the "files" parameter like so:
response = requests.request(method='POST', url=api_url, auth=self.oauth, params=params, files=file_payload)
When this call makes its way down to core.py, Python3.3 is not happy. Why? It appears the "in" operator in the above statement (in core.py) performs a problematic comparison. r.headers.get('Content-Type', '') returns a byte-stream instead of a string when multipart data is being sent from the Requests API. CONTENT_TYPE_FORM_URLENCODED, however, is a 'str' type. This comparison causes a TypeError exception to be thrown.
Here's a hack I implemented to get around this problem:
#-----------------------------------------------------------------------
#
# SketchUp modified code starts here.
content_type = r.headers.get('Content-Type', '')
try:
if (CONTENT_TYPE_FORM_URLENCODED in content_type):
is_form_encoded = True
else:
is_form_encoded = False
except Exception as e:
# print("OAuth BUG: comparing 'byte stream' with 'str' type when "
# "a multipart request header is encountered.")
is_form_encoded = False
#
# SketchUp modified code ends here.
#-----------------------------------------------------------------------
#-----------------------------------------------------------------------
# This is the OAuth block of code that SketchUp has commented out:
#
# is_form_encoded = (CONTENT_TYPE_FORM_URLENCODED in
# r.headers.get('Content-Type', ''))
#
#-----------------------------------------------------------------------
I think you should be aware of this issue as it caused me some serious pain. My "fix" is just a hack and I'm sure there's a better way to solve this problem.
~Gabriel
Facebook's client_credentials grants return an unencoded pipe character in the string, which oauthlib.common.urldecode balks at. Since this code is in the Facebook compliance fix, it really ought to actually work with what Facebook sends.
I've filed a bug with Facebook, but until that is resolved I propose we use urllib.parse_qs instead.
One of the few issues I see people run into is that they are using an old version of requests, pre 1.0 that is but might now also include the odd pre 2.0.
It might be helpful if we raised a Warning telling users to upgrade their version of requests. I am not sure how/where to best do this. @Lukasa thoughts?
The most obvious place which would address most of the pre 1.0 issues is in OAuth 1 where we expect a PreparedRequest and instead get a Request. However with the encoding changes in 2.0 the places/cases impacted will be much more subtle. Although still most likely in OAuth 1.
if requests.__version__ < '2.0.0':
raise Warning('You are using requests version %s, which is older than requests-oauthlib expects, please upgrade to 2.0.0 or later." % requests.__version__)
Bump the minimum version of oauthlib in setup.py install_requires to 0.4.2.
The following tests fail with oauthlib 0.4.0:
running test
running egg_info
writing requirements to requests_oauthlib.egg-info/requires.txt
writing requests_oauthlib.egg-info/PKG-INFO
writing top-level names to requests_oauthlib.egg-info/top_level.txt
writing dependency_links to requests_oauthlib.egg-info/dependency_links.txt
reading manifest file 'requests_oauthlib.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
writing manifest file 'requests_oauthlib.egg-info/SOURCES.txt'
running build_ext
test_authorization_url (tests.test_oauth1_session.OAuth1SessionTest) ... ok
test_binary_upload (tests.test_oauth1_session.OAuth1SessionTest) ... ERROR
test_fetch_access_token (tests.test_oauth1_session.OAuth1SessionTest) ... ERROR
test_fetch_request_token (tests.test_oauth1_session.OAuth1SessionTest) ... ERROR
test_nonascii (tests.test_oauth1_session.OAuth1SessionTest) ... ERROR
test_parse_response_url (tests.test_oauth1_session.OAuth1SessionTest) ... ok
test_signature_methods (tests.test_oauth1_session.OAuth1SessionTest) ... ERROR
test_signature_types (tests.test_oauth1_session.OAuth1SessionTest) ... ERROR
testCanPostBinaryData (tests.test_core.OAuth1Test) ... ERROR
testFormEncoded (tests.test_core.OAuth1Test)
OAuth1 assumes form encoded if content type is not specified. ... ERROR
testNonFormEncoded (tests.test_core.OAuth1Test)
OAuth signature only depend on body if it is form encoded. ... ERROR
test_url_is_native_str (tests.test_core.OAuth1Test) ... ERROR
test_add_nonexisting_token (tests.test_oauth2_auth.OAuth2AuthTest) ... ok
test_add_token_to_body (tests.test_oauth2_auth.OAuth2AuthTest) ... ok
test_add_token_to_headers (tests.test_oauth2_auth.OAuth2AuthTest) ... ok
test_add_token_to_url (tests.test_oauth2_auth.OAuth2AuthTest) ... ok
test_add_token (tests.test_oauth2_session.OAuth2SessionTest) ... ok
test_authorization_url (tests.test_oauth2_session.OAuth2SessionTest) ... ok
test_fetch_token (tests.test_oauth2_session.OAuth2SessionTest) ... ok
test_refresh_token_request (tests.test_oauth2_session.OAuth2SessionTest) ... ok
test_token_from_fragment (tests.test_oauth2_session.OAuth2SessionTest) ... ok
======================================================================
ERROR: test_binary_upload (tests.test_oauth1_session.OAuth1SessionTest)
File "/usr/local/lib/python2.7/site-packages/requests-1.2.3-py2.7.egg/requests/models.py", line 226, in prepare
p.prepare_auth(self.auth, self.url)
File "/usr/local/lib/python2.7/site-packages/requests-1.2.3-py2.7.egg/requests/models.py", line 428, in prepare_auth
r = auth(self)
File "/mnt/home/user/repos/freebsd/ports/www/py-requests-oauthlib/work/requests-requests-oauthlib-0b1fe5c/requests_oauthlib/core.py", line 61, in __call__
unicode(r.url), unicode(r.method), r.body or '', r.headers)
File "/usr/local/lib/python2.7/site-packages/oauthlib-0.4.0-py2.7.egg/oauthlib/oauth1/rfc5849/__init__.py", line 225, in sign
encoding=self.encoding)
File "/usr/local/lib/python2.7/site-packages/oauthlib-0.4.0-py2.7.egg/oauthlib/common.py", line 332, in __init__
self.headers = CaseInsensitiveDict(encode(headers or {}))
File "/usr/local/lib/python2.7/site-packages/oauthlib-0.4.0-py2.7.egg/oauthlib/common.py", line 328, in <lambda>
encode = lambda x: to_unicode(x, encoding) if encoding else x
File "/usr/local/lib/python2.7/site-packages/oauthlib-0.4.0-py2.7.egg/oauthlib/common.py", line 276, in to_unicode
return dict(((to_unicode(k, encoding), to_unicode(v, encoding)) for k, v in data))
File "/usr/local/lib/python2.7/site-packages/oauthlib-0.4.0-py2.7.egg/oauthlib/common.py", line 276, in <genexpr>
return dict(((to_unicode(k, encoding), to_unicode(v, encoding)) for k, v in data))
ValueError: too many values to unpack
======================================================================
ERROR: testNonFormEncoded (tests.test_core.OAuth1Test)
OAuth signature only depend on body if it is form encoded.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/local/lib/python2.7/site-packages/mock-1.0.1-py2.7.egg/mock.py", line 1201, in patched
return func(*args, **keywargs)
File "/mnt/home/user/repos/freebsd/ports/www/py-requests-oauthlib/work/requests-requests-oauthlib-0b1fe5c/tests/test_core.py", line 67, in testNonFormEncoded
a = r.prepare()
File "/usr/local/lib/python2.7/site-packages/requests-1.2.3-py2.7.egg/requests/models.py", line 226, in prepare
p.prepare_auth(self.auth, self.url)
File "/usr/local/lib/python2.7/site-packages/requests-1.2.3-py2.7.egg/requests/models.py", line 428, in prepare_auth
r = auth(self)
File "/mnt/home/user/repos/freebsd/ports/www/py-requests-oauthlib/work/requests-requests-oauthlib-0b1fe5c/requests_oauthlib/core.py", line 65, in __call__
unicode(r.url), unicode(r.method), None, r.headers)
File "/usr/local/lib/python2.7/site-packages/oauthlib-0.4.0-py2.7.egg/oauthlib/oauth1/rfc5849/__init__.py", line 225, in sign
encoding=self.encoding)
File "/usr/local/lib/python2.7/site-packages/oauthlib-0.4.0-py2.7.egg/oauthlib/common.py", line 332, in __init__
self.headers = CaseInsensitiveDict(encode(headers or {}))
File "/usr/local/lib/python2.7/site-packages/oauthlib-0.4.0-py2.7.egg/oauthlib/common.py", line 328, in <lambda>
encode = lambda x: to_unicode(x, encoding) if encoding else x
File "/usr/local/lib/python2.7/site-packages/oauthlib-0.4.0-py2.7.egg/oauthlib/common.py", line 276, in to_unicode
return dict(((to_unicode(k, encoding), to_unicode(v, encoding)) for k, v in data))
File "/usr/local/lib/python2.7/site-packages/oauthlib-0.4.0-py2.7.egg/oauthlib/common.py", line 276, in <genexpr>
return dict(((to_unicode(k, encoding), to_unicode(v, encoding)) for k, v in data))
ValueError: too many values to unpack
======================================================================
ERROR: test_url_is_native_str (tests.test_core.OAuth1Test)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/local/lib/python2.7/site-packages/mock-1.0.1-py2.7.egg/mock.py", line 1201, in patched
return func(*args, **keywargs)
File "/mnt/home/user/repos/freebsd/ports/www/py-requests-oauthlib/work/requests-requests-oauthlib-0b1fe5c/tests/test_core.py", line 108, in test_url_is_native_str
r = requests.get('http://httpbin.org/get', auth=oauth)
File "/usr/local/lib/python2.7/site-packages/requests-1.2.3-py2.7.egg/requests/api.py", line 55, in get
return request('get', url, **kwargs)
File "/usr/local/lib/python2.7/site-packages/requests-1.2.3-py2.7.egg/requests/api.py", line 44, in request
return session.request(method=method, url=url, **kwargs)
File "/usr/local/lib/python2.7/site-packages/requests-1.2.3-py2.7.egg/requests/sessions.py", line 324, in request
prep = req.prepare()
File "/usr/local/lib/python2.7/site-packages/requests-1.2.3-py2.7.egg/requests/models.py", line 226, in prepare
p.prepare_auth(self.auth, self.url)
File "/usr/local/lib/python2.7/site-packages/requests-1.2.3-py2.7.egg/requests/models.py", line 428, in prepare_auth
r = auth(self)
File "/mnt/home/user/repos/freebsd/ports/www/py-requests-oauthlib/work/requests-requests-oauthlib-0b1fe5c/requests_oauthlib/core.py", line 65, in __call__
unicode(r.url), unicode(r.method), None, r.headers)
File "/usr/local/lib/python2.7/site-packages/oauthlib-0.4.0-py2.7.egg/oauthlib/oauth1/rfc5849/__init__.py", line 225, in sign
encoding=self.encoding)
File "/usr/local/lib/python2.7/site-packages/oauthlib-0.4.0-py2.7.egg/oauthlib/common.py", line 332, in __init__
self.headers = CaseInsensitiveDict(encode(headers or {}))
File "/usr/local/lib/python2.7/site-packages/oauthlib-0.4.0-py2.7.egg/oauthlib/common.py", line 328, in <lambda>
encode = lambda x: to_unicode(x, encoding) if encoding else x
File "/usr/local/lib/python2.7/site-packages/oauthlib-0.4.0-py2.7.egg/oauthlib/common.py", line 276, in to_unicode
return dict(((to_unicode(k, encoding), to_unicode(v, encoding)) for k, v in data))
File "/usr/local/lib/python2.7/site-packages/oauthlib-0.4.0-py2.7.egg/oauthlib/common.py", line 276, in <genexpr>
return dict(((to_unicode(k, encoding), to_unicode(v, encoding)) for k, v in data))
ValueError: too many values to unpack
----------------------------------------------------------------------
Ran 21 tests in 0.046s
FAILED (errors=10)
It seems to me we should rename core.py
to oauth1_auth.py
to match the naming scheme of the rest of the files in the library.
Facebook returns an access token in a urlencoded format, but on error, it returns a JSON encoded error message.
The facebook compliance fix attempts to urldecode the response body without any attempt to handle non-urlencoded data, or raise a sensible warning.
There are a few options to solve this:
We could check for errors before the compliance fixes are run. This might save us from code duplication, but it seems like the compliance fixes ought to be the first thing to touch the response.
We could also leave it up to the compliance fixes to handle weird conditions like this. In the facebook case, I would wrap the urldecode bit in a try, and simply return the unaltered response in the exception block.
I think the second solution is the better one. I'll submit a pull request to do just that.
Hello,
I've got the following error when I try the snippet of code
oauthlib.oauth2.rfc6749.errors.InsecureTransportError
I got the redirection but returning to the callback throws this exception.
The exception is triggered by the line :
token = github.fetch_token(token_url, client_secret=client_secret, authorization_response=request.url)
Since I'm new to requests-oauth, I don't know if the blunder is coming from me or not. But I almost copy/paste the code and replaced all that have to be replaced.
Can anyone confirm the example is working ?
Oauth lib client constructor changed, token is now named access_token, so requests_oauthlib is now incompatible with recent version of authlib (there are maybe other incompatibilites, I did'nt search for more and just installed version 0.4.2)
We've finally got some stuff up on ReadTheDocs, but it's not great. This issue is an umbrella tracking issue, so I can tick stuff off as we go. Here are some things we need to do: feel free to suggest more in the comments.
While the spec only defines grant_type and refresh_token other parameters like client_id and client_secret are often used (Google, WindowsLive).
We should investigate what the major providers use and see if we can come up with a good way to provide these by default as a smart alternative to auto_refresh_kwargs
or whether it would be better to subclass OAuth2Session with provider specific versions such as GoogleWebApplication.
Flickr API for file uploading (http://www.flickr.com/services/api/upload.api.html) uses a tricky approach: they require a single POST parameter photo and support some optional params.
The tricky part is that this photo parameter needs to be excluded from the OAuth signature, while all the other params (the optional ones) should be included in it (as explained under the link above).
Is it possible to exclude some parameters from including in the signature using requests-oauthlib?
With 2.0 support!
As documented here:
https://developers.facebook.com/docs/facebook-login/access-tokens/#apptokens
This issue is in reference to
https://github.com/requests/requests-oauthlib/blob/master/requests_oauthlib/oauth2_session.py#L148.
It should probably be considered with #96, which is another barrier to using the backend client.
I'm using django-allauth with linkedin, and line 52 of the core.py (if is_form_encoded...) throws an exception "Request object has no attribute body". Strangely, this does not occur with direct calls to the linkedin API. Nonetheless, would you mind a short-circuit hasattr(r, 'body') in the if statement to prevent this? Thanks!
When I attempt to add the requests-oauthlib github repo to my requirements.txt, I receive this error:
ImportError: No module named compliance_fixes
This can simply be fixed by using setuptools.find_packages() to located all of the included packages. Going to submit a pull request for this.
We should support OAuth2 if we possibly can.
Is there already work in supporting Oauth2? If not, I think I may tackle it as I need it for PRAW. My question is, should support be added as part of this package, or a separate requests-oauth2lib package?
There already exists a simple package sanction that could probably be adapted to work with requests. That package is under the MIT license, so I think the code can be "borrowed" assuming the copyright notice is also copied. Thoughts?
Currently this is impossible to solve directly from this library as requests itself is at fault, as it does not provide facilities in the SessionRedirectMixin.resolve_redirects
to call prepare_auth
on the local PreparedRequest
object to recalculate the OAuth signatures. This can probably be called after the prepare_cookies
call.
Edit: can probably be done by overriding the send method so that it calls prepare_auth
again, but that's hideous.
I'm trying to get Facebook Oauth2 login working correctly, and I hit something interesting. I keep getting the following traceback:
File "/opt/webapp/clusterlogin/lib/python2.7/site-packages/pyramid/router.py", line 161, in handle_request
response = view_callable(context, request)
File "/opt/webapp/clusterlogin/lib/python2.7/site-packages/pyramid/config/views.py", line 375, in viewresult_to_response
result = view(context, request)
File "/opt/webapp/clusterlogin/lib/python2.7/site-packages/pyramid/config/views.py", line 491, in _requestonly_view
response = view(request)
File "/opt/webapp/clusterlogin/src/clusterlogin/views/facebook_auth.py", line 40, in facebook_login
client_secret=settings['facebook.client_secret'])
File "/opt/webapp/clusterlogin/lib/python2.7/site-packages/requests_oauthlib/oauth2_session.py", line 125, in fetch_token
self._client.parse_request_body_response(r.content, scope=self.scope)
File "/opt/webapp/clusterlogin/lib/python2.7/site-packages/oauthlib/oauth2/rfc6749/clients/web_application.py", line 271, in parse_request_body_response
self.token = parse_token_response(body, scope=scope)
File "/opt/webapp/clusterlogin/lib/python2.7/site-packages/oauthlib/oauth2/rfc6749/parameters.py", line 292, in parse_token_response
params = json.loads(body)
File "/opt/python-2.7.3/lib/python2.7/json/__init__.py", line 326, in loads
return _default_decoder.decode(s)
File "/opt/python-2.7.3/lib/python2.7/json/decoder.py", line 366, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/opt/python-2.7.3/lib/python2.7/json/decoder.py", line 384, in raw_decode
raise ValueError("No JSON object could be decoded")
ValueError: No JSON object could be decoded
What seems to be happening is that the request to gain an access_token is succeeding, but is responding with the following string in the response body: 'access_token=#####&expires=#####'. requests-oauthlib expects a JSON response, so it isn't able to parse the string returned. Is this a bug, or am I doing something incorrect?
Examples are sorely needed for this new library - Twitter and Facebook being the most obvious ones, but it'd be nice to see it demo'd as a provider as well. Python-oauth2 has some decent examples, for instance: https://github.com/simplegeo/python-oauth2
The README example has "from requests_authlib" when it should be "requests_oauthlib"
Also, the link from requests to here could be a lot clearer :-)
The Auth1Session example code mentioned on the requests-oauthlib documentation page doesn't actually work.
The twitter response page just shows a number that you're supposed to give back to the client, rather than a URL with oauth_token
and verifier
specified in the params. The code then fails with this stack trace:
Traceback (most recent call last):
File "oauth_example.py", line 37, in <module>
oauth_tokens = oauth.fetch_access_token(access_token_url)
File "/Users/nhooey/git/github/vine/vineweb/.venv/lib/python2.7/site-packages/requests_oauthlib/oauth1_session.py",
line 228, in fetch_access_token
token = self._fetch_token(url)
File "/Users/nhooey/git/github/vine/vineweb/.venv/lib/python2.7/site-packages/requests_oauthlib/oauth1_session.py",
line 264, in _fetch_token
token = dict(urldecode(self.post(url).text))
File "/Users/nhooey/git/github/vine/vineweb/.venv/lib/python2.7/site-packages/oauthlib/common.py", line 137, in urld
ecode
raise ValueError('Not a valid urlencoded string.')
ValueError: Not a valid urlencoded string.
Because the response from Twitter is this:
<?xml version="1.0" encoding="UTF-8"?>
<hash>
<error>Required oauth_verifier parameter not provided</error>
<request>/oauth/access_token</request>
</hash>
The Using OAuth1 auth helper
example from that page works fine with Twitter, though.
In the callback view like Web App Example of OAuth 2 web application flow, I instantiated OAuth2Session with state parameter and called fetch_token() method but fetch_token() does not use the given state value.
So an arbitrary state parameter bypasses OAuth2Session's CSRF protection:
github = OAuth2Session(client_id, state='wrong state')
github.fetch_token(
token_url, client_secret=client_secret,
authorization_response=request.url) # does not raise MismatchingStateError
This happens here and possibly other places:
from oauthlib.common import log
...
log.debug(...)
This is bad because all the logs show up as coming from oauthlib, whereas some happen actually in oauthlib and some in requests_oauthlib. Differentiating them would be useful for debugging where things are happening.
I suggest using...
import logging
log = logging.getLogger(__name__)
...
log.debug(...)
This will also allow the user to turn off oauthlib logs but keep requests_oauthlib logs, and vice versa.
5570360 fixed a giant bug that some people have run into: with revisions before 5570360 (including v0.3.2) it's simply impossible to fetch access token from Twitter, Tumblr, and possibly any other site using the code below (that's basically a simplified example from the docs).
from requests_oauthlib import OAuth1Session
CLIENT_KEY = 'blah'
CLIENT_SECRET = 'blah'
REQUEST_TOKEN_URL = 'https://api.twitter.com/oauth/request_token'
BASE_AUTHORIZATION_URL = 'https://api.twitter.com/oauth/authorize'
ACCESS_TOKEN_URL = 'https://api.twitter.com/oauth/access_token'
if __name__ == '__main__':
oauth = OAuth1Session(client_key=CLIENT_KEY,
client_secret=CLIENT_SECRET)
oauth.fetch_request_token(REQUEST_TOKEN_URL)
print oauth.authorization_url(BASE_AUTHORIZATION_URL)
redirect_response = raw_input('Redirect response: ')
oauth.parse_authorization_response(redirect_response)
print oauth.fetch_access_token(ACCESS_TOKEN_URL)
On previous revisions it will fail with this:
Traceback (most recent call last):
File "a.py", line 20, in <module>
print oauth.fetch_access_token(ACCESS_TOKEN_URL)
File "/tmp/requests-oauthlib/requests_oauthlib/oauth1_session.py", line 221, in fetch_access_token
token = self._fetch_token(url)
File "/tmp/requests-oauthlib/requests_oauthlib/oauth1_session.py", line 257, in _fetch_token
self._populate_attributes(token)
File "/tmp/requests-oauthlib/requests_oauthlib/oauth1_session.py", line 249, in _populate_attributes
raise ValueError('Response does not contain a token. %s', token)
ValueError: (u'Response does not contain a token. %s', {})
I've already said it in a comment under the commit – this is a big issue. It breaks the OAuth 1 functionality completely, assuming you use OAuth1Session to obtain the tokens.
I think a lot of users of requests_oauthlib would lead much happier lives if a version that includes this fix would be available on PyPI.
We are using state
param to follow the relation between our app and authentication requests. Think of them, as some uuid
values.
It is fine by Google (link):
state - any string - Indicates any state which may be useful to your application upon receipt of the response. The Google Authorization Server roundtrips this parameter, so your application receives the same value it sent. Possible uses include redirecting the user to the correct resource in your site, nonces, and cross-site-request-forgery mitigations.
However, OAuthSession2.authorization_url
ignores the value being passed to the constructor, and replaces with a self-generated one (line 102).
def authorization_url(self, url, **kwargs):
state = self.new_state()
return self._client.prepare_request_uri(url,
redirect_uri=self.redirect_uri,
scope=self.scope,
state=state,
**kwargs), state
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.