Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(Security Flaw) requests-oauthlib sends json payloads while refreshing tokens #451

Open
slmtpz opened this issue Aug 12, 2021 · 2 comments

Comments

@slmtpz
Copy link

slmtpz commented Aug 12, 2021

Walkthrough

When intercepting a request(), request-oauthlib doesn't take payload data passed with json parameter into account. This leads to kwargs having json parameter value.
Notice that the same kwargs are passed to refresh_token() call. The data then is included in the body data to be sent to the identity provider's refresh token endpoint.

Security Problem

As of requests 2.4.2 POST data can be sent with json parameter. The data might include private information as it is intended for the POST body. The data then is further exposed to an identity provider when refreshing expired tokens if auto_refresh functionality is enabled while instantiating an OAuth2Session instance.

For the users

You can safely use data parameter to pass your POST data instead of json.

@JonathanHuot
Copy link
Contributor

Hi,
Thanks for the report, however I have difficulties to understand a concrete example and possible dev mistakes which can lead to info leaking. Based on the code highlights, it seems json is not used when calling requests library, no matter the content of kwargs.

@furious-luke
Copy link

Even though this is a bit old, I might be able to help explain as I've just encountered the same issue.

With requests, we're able to use the json argument as a shortcut, like this:

requests.post(MY_URL, json={"foo": "bar"})

Now we can also use the same format to call OAuth2Session.post, and it will work just fine. That is, until the provided token expires. To understand why, if we examine the OAuth2Session.request method signature:

    def request(
        self,
        method,
        url,
        data=None,
        headers=None,
        withhold_token=False,
        client_id=None,
        client_secret=None,
        files=None,
        **kwargs
    ):

You can see that if we call with data, it gets extracted and removed from kwargs. But, if we call with json, that parameter will not be removed from kwargs, and will be kept around. Now, take a look at how the refresh_token method is called from within:

token = self.refresh_token(
    self.auto_refresh_url, auth=auth, **kwargs
)

So, the value for json will get passed into refresh_token. This is a problem, as the kwargs in that method will get added to the payload sent to the refresh token endpoint.

I encountered this issue while working with Microsoft's OAuth2 token endpoint. It fails with a 400 error if additional values are passed in to the endpoint's body.

Let me know if that makes sense, happy to elaborate if needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants