requests / requests-oauthlib

OAuthlib support for Python-Requests!
https://requests-oauthlib.readthedocs.org/
ISC License
1.71k stars 422 forks source link

OAuth1Session.parse_authorization_response breaks with unquoted url #429

Open qria opened 3 years ago

qria commented 3 years ago

With callback url there can be additional parameters such as next as well as the oauth_token and oauth_verificer, and there can be unquoted strings in it.

For example, my callback url was: "/login/twitter-callback?next=ㅋㅋ&oauth_token=<redacted>&oauth_verifier=<redacted>"

Calling OAuth1Session.parse_authorization_response on above url yields an error:

json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

But this is not the culprit because of how urldecode is coded to ignore failed urldecode attempts:

def urldecode(body):
    """Parse query or json to python dictionary"""
    try:
        return _urldecode(body)
    except Exception:   # <-
        import json

        return json.loads(body)

The real error is:

ValueError: Error trying to decode a non urlencoded string. Found invalid characters: {'ㅋ'} in the string: 'next=ㅋ&oauth_token=<redacted>&oauth_verifier=<redacted>'. Please ensure the request/response body is x-www-form-urlencoded.

You can reproduce this error with this code:

import json
from oauthlib.common import urldecode

from urllib.parse import urlparse
url = 'https://www.example.com/login/twitter-callback?next=ㅋㅋ&oauth_token=aaa&oauth_verifier=bbb'
urldecode(urlparse(url).query)
qria commented 3 years ago

As a workaround I am doing this for now:

import urllib.parse

# oauth_session.parse_authorization_response(request.url)  # this is bugged
qs_dict = urllib.parse.parse_qs(urllib.parse.urlparse(request.url).query)
token = {
    'oauth_token': qs_dict['oauth_token'][0],
    'oauth_verifier': qs_dict['oauth_verifier'][0],
}
oauth_session.token = token