-
-
Notifications
You must be signed in to change notification settings - Fork 367
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
Fix: Use proper scopes in refresh token handler #698
Fix: Use proper scopes in refresh token handler #698
Conversation
Fixing the OAuth2 token refresh handler to: - Read and use the optional 'scope' form parameter, if present. - Otherwise default to requesting the originally granted scopes. This endpoint should be completely agnostic of: - The originally **requested** scopes - The **client scopes** (both current and past client scopes) Fixes ory#696
Updating our OAuth2 token refresh handler tests to completely ignore the **Client Scopes** and **Originally Requested Scopes**. Instead, the originally granted scopes should be the only scopes validated against. Also adding some tests to validate the optional 'scope' parameter, as outlined in https://www.rfc-editor.org/rfc/rfc6749#section-6 Note that this implementation returns an ErrInvalidScope if the 'scope' form parameter is defined but empty.
cfcbd40
to
d9ecd46
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you very much for the detailed issue and PR! I think this is working though as intended for a reason, please check my comment. Thanks!
request.SetRequestedAudience(originalRequest.GetRequestedAudience()) | ||
|
||
for _, scope := range originalRequest.GetGrantedScopes() { | ||
if !c.Config.GetScopeStrategy(ctx)(request.GetClient().GetScopes(), scope) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For context: This design decision was originally made to cover the use case where a client could gain access to scopes that are not in its allowed list. This can happen when a client is updated. I'd say this behavior is correct. The client should not receive scopes which are not in its allowed list.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check was merely moved here from what I can tell: https://github.com/ory/fosite/pull/698/files#diff-e733adcae5e1fe83d4192fc112318cfd1d77b5ad76b6d71d383ae705ea29e3f2R111-R112
From looking purely at the code change what happens is if the request to the token endpoint is a refresh and the form contains a scopes
key it uses that as the source of the intended scopes, if it doesn't it uses the original request as a source of the intended scopes, then performs the original check to ensure the client is allowed to issue those scopes.
I can see another issue with this PR though. I'll make a review.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is strange that the conformity test failed though...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For context: This design decision was originally made to cover the use case where a client could gain access to scopes that are not in its allowed list. This can happen when a client is updated. I'd say this behavior is correct. The client should not receive scopes which are not in its allowed list.
@aeneasr Please let me know if James' response makes sense, or if you still have issues you'd like to chat through with this implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see the issue, we should probably still check the intended scopes against the client to ensure it absolutely can issue them (even though it theoretically did before). But lets see what Aeneasr says.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @aeneasr , the above does NOT follow RFC6749. This is precisely the bug that I am encountering in Fosite, and the reason I filed this PR to fix it. The implementation according to the RFC should be:
- Authorization Grant is done with scope a, b, c - client is granted scopes a, b, c
- Refresh grant is executed without ?scope parameter, thus scope a, b, c is granted
- Refresh grant is executed again with ?scope=a,b, and scope a,b is granted
- Client is updated to only allow scope a, b
- Refresh grant is executed without ?scope parameter, scope a, b
, c
is granted - Refresh grant is executed with ?scope=a,b,c parameter, refresh
failssucceeds
- Refresh grant is executed with ?scope=a,b parameter, and scope a,b is granted
Refreshing an access token should be completely agnostic to the currently configured client scopes. Note that the entire RFC makes no mention of the term client scope
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The other issue that this PR attempts to resolve is that steps (3) and (7) are broken in Fosite, since Fosite does not read the ?scope=a,b
parameter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I respectfully disagree. #698 (comment) is not what I trust the correct sequence to be, I think it reduces security, and it's also not how I interpret the RFC. What could work to convince me otherwise is to get the conformance tests (which test OIDC conformity ...) to pass since they are failing on this PR (potentially due to the changes made), and to get someone from the OAuth2 IETF authors or maintainers to agree with your interpretation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @aeneasr I can understand your reservations, and desire to get sign-off from the OAuth2 IETF authors. How about we focus on the more clear-cut issue of Fosite not honoring the ?scope=a,b
parameter for now? That would at least unblock my particular use case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, Fosite should definitely respect that parameter! :)
Perhaps we can put aside the "client scope" discussion for a moment, and simply agree that the Fosite library DOES have a bug whereby the |
Yeah I agree with focusing on the one aspect, it's more efficient. Especially with focusing on something I think is less ambiguous/open to interpretation/not explicitly stated in the spec, is a good idea. |
@aeneasr please let me know if you have time to discuss #698 (comment) |
Given the discussion and reasoning above I will close this PR. Any ideas for future work outlined in this PR we‘ll happily accept though :) |
Fixes #696
The token refresh handler currently has two issues related to scopes:
scope
form parameterclient
scopes, rather than the originallygranted
scopes. One issue related to this is that if the client scopes are narrowed, then the existing refresh tokens may fail to refresh, even if the user originally consented to those scopes.This PR fixes the OAuth2 token refresh handler to:
The token refresh handler endpoint should be completely agnostic of:
Related Issue or Design Document
#696
Checklist
If this pull request addresses a security vulnerability,
I confirm that I got green light (please contact [email protected]) from the maintainers to push the changes.
Further comments