-
-
Notifications
You must be signed in to change notification settings - Fork 421
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
Problems with Token refreshing. #264
Comments
Thanks for this issue report!
It should not be: the As for issue 2, this was raised in #218 and has not since been resolved. I think we should fix it. In general, though, I would be happy to merge a PR that resolves your problems 2, 3, and 4. 😄 |
I missed #218 yes, the three providers I reference do auth via body not basic auth. New propsed change is to add self.oauthsession = OAuth2Session(..., refresh_kwargs={'url': refresh_url,
'client_id': client_id, 'client_secret': client_secret'})
...
return self.oauthsession.request(method, url, headers=headers, **kwargs) |
Yeah, I think that is reasonable. That, or we'd want to use a separate function to register those: a function you'd call after init. Either would be appropriate. |
There is actually already |
Not tested (yet): Will make PR after I test. |
And actually, in reference to Issue 1 above, there is still a problem with the The API around this is really complicated, since refresh_token() args can come from kwargs to To simplify this would be a breaking change, it would require relying solely on auto_refresh_kwargs, so the caller has explicit control over the authentication. I think it is probably what is wanted since providers are free to implement their own methods... Thoughts? |
The spec leaves authentication method up to the implementer.
While the example shows HTTP basic authentication, there is a reference to section 3.2.1, which covers authentication for the token endpoint as a whole. It states there MUST be authentication for confidential clients, but does not specifically lay out the scheme required.
Some grant types for example "Resource Owner Password Grant" would obviously use HTTP basic auth, others would not. There are OAuth2 profiles for using JWT, SAML etc. for performing authentication. So it is my understanding that there is nothing special about HTTP basic authentication, in fact, I don't use it at all. Letting the caller control this completely seems like the right API. The caller can include the |
Here is a breaking change that makes the API explicit. Caller can call What do you think of this? |
This ambiguity is part of why OAuth2 is a well-loathed specification: it essentially doesn't mandate anything, but is littered with MAYs that grant an astonishing amount of freedom to implementers to do whatever the hell they want. This makes it very difficult to write a single library that has meaningfully helpful automation across a number of OAuth2 providers. That said, the general direction of this change seems reasonable, though I'll want to see a PR before I can really commit to saying that it's the right way to go. 😄 |
I understand. This is why I propose just letting the caller decide. Although my experience so far is only with a handful of providers, my code to deal with them is fairly complex. It seems from the current issues that refreshing tokens is a pain point for a bunch of users, and giving them explicit control would solve those problems. What I don't know however is how many folks would be affected if this "auto authentication" were to go away... I will finalize and test my changes and submit a PR. |
And by the way, I agree, I wish the spec were more explicit. |
PR opened: #265 |
If you want to have secure application, then never keep your secrets in the memory due to the heart bleed attacks. Hence, the
|
@xmedeko Heartbleed is not a sensible thread model in this case. In particular, if More generally, the only way to truly avoid heartbleed style attacks is to keep secret material outside of the process in question altogether. For OAuth2, given that the The best defense against Heartbleed is to upgrade your OpenSSL. |
@Lukasa thanks for the clarification. I didn't realize the problem with the Python memory management. |
Yeah, it's a real problem. It's why, ultimately, most "managed-memory languages" (see: Python, Go, Ruby, etc.) are bad choices for writing any code that handles keying material in cryptography. Those almost always need to be written in languages that do allow low-level control of memory, so that keys can be securely evacuated when they aren't needed. |
Possibly related -- there are numerous issues related to auto refresh auth on this tracker, it seems -- i'm also trying to get Basic auth passed through when auto refresh is called. It seems both custom 'headers' and 'auth' are eaten from auto_refresh_kwargs by the 'prepare_refresh_body' (refresh_token line 285) , so they don't get through to the actual post. (refresh_token line 297). In fact, if i set 'headers' in auto_refresh_kwargs, the custom headers end up in the data section of the request body.. Just tried out PR# 265 and everything worked perfectly - auth went right through and worked - so, thumbs up! |
Recently playing with our internal OAuth provider and inspecting the logs I noticed the following message: |
Just wanted to chime in with a 👍 for issue 3 in the OP. The variable name, I think I must be missing something here... why are they passed through at all? (Is anyone aware of a valid use case?) It seems like this is the wrong behavior for any API where the data endpoints you're attempting to access have parameters that the OAuth2 token endpoint doesn't (which is nearly every API endpoint I've used...) |
First of all, thank you for this wonderful library. It works great and saved me tons of time.
I am having issues with one aspect: auto token refresh. I have identified 3 distinct problems, which I will describe below and for which I will suggest solutions. I will also reference this issue from multiple other related issues. I am happy to provide a PR once we can agree upon a suitable solution.
I derived my solution from the following, as my issue is a variant of the same issue:
#260
All of the problems start here:
https://github.com/requests/requests-oauthlib/blob/master/requests_oauthlib/oauth2_session.py#L338
Issue 1
If I pass an
auth
kwarg intended for therequest()
method, it is eradicated here. I am not sure if this is an issue in practice.Issue 2
Box, Google and Onedrive do not expect the
client_id
andclient_secret
to be provided via Basic authentication alaAuthorization
header. They instead expect these POSTed in the body. There is no way to customize this behavior. Also, I don't know what vendors expect what method here, I only know the 3 above as that is what I am working with.Issue 3
Any kwargs I pass which are intended for the
request()
method end up being passed torefresh_token()
and are used when accessing the token endpoint. For example, if my originalrequest()
uploads a file, that file will be transferred to the token endpoint when attempting to refresh the token.Issue 4
client_id
andclient_secret
are not normally passed torequest()
but are necessary for token refresh. Passing them is not a problem except for unintended consequences of them being passed along tosuper().request()
Proposed solution.
I think all of the above can be solved by making two changes.
Pass the
client_id
andclient_secret
to__init__()
where they are stored as attributes (ofOAuth2Session
or underlyingWebApplicationClient
. In factclient_id
is already handled this way, butfetch_token()
,refresh_token()
etc. do no utilize it and expect it passed again as a kwarg. This addresses issue 4.Add a
refresh_kwargs
argument that accepts a dict, and provides kwargs passed along totoken_refresh()
thus keeping them separate from the regular kwargs intended forrequest()
. This solves issues 1 & 3.Place the
client_id
andclient_secret
into the POST body by default, all three of the providers I have tried expect this instead of basic auth. Callers can userefresh_kwargs
to provide anauth
kwarg if necessary (their provider expects this instead). Optionally, ifauth
is passed, theclient_id
andclient_secret
could be omitted from the POST body (it is unlikely that a provider expects both). This solves issue 3.I present my current workaround, which works perfectly for my providers.
The text was updated successfully, but these errors were encountered: