Skip to content

Scope in refresh_token grant type is ignored. #104

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

Closed
jorenvandeweyer opened this issue Dec 11, 2021 · 7 comments
Closed

Scope in refresh_token grant type is ignored. #104

jorenvandeweyer opened this issue Dec 11, 2021 · 7 comments
Labels
backwards breaking ✂️ This change will not work with the current version of the module. compliance 📜 OAuth 2.0 standard compliance good first issue ✅ Good for newcomers
Milestone

Comments

@jorenvandeweyer
Copy link
Member

While checking the compliance of the refresh_token grant. I discovered that the optional scope parameter in the body is ignored.

return Promise.bind(this)
.then(function() {
return this.getRefreshToken(request, client);
})
.tap(function(token) {
return this.revokeToken(token);
})
.then(function(token) {
return this.saveToken(token.user, client, token.scope);
});

https://datatracker.ietf.org/doc/html/rfc6749#section-6

@jankapunkt
Copy link
Member

@jorenvandeweyer great you found this!

@jankapunkt jankapunkt added compliance 📜 OAuth 2.0 standard compliance good first issue ✅ Good for newcomers labels Dec 11, 2021
@Uzlopak
Copy link
Collaborator

Uzlopak commented Dec 13, 2021

I thought about this issue yesterday.

We have to be careful how we implement this. With the current ignored scope parameter there is no potential security issue. You always get the scope of the original requested scope (?).

But Imagine following case:

Authorization Code Grant: User can select three scopes: "read write delete" but selects only read scope. Now if refresh token would contains scope value, it could contain "read write delete" scope. What you would expect is that you have again only "read"-scope as the user specified in the authorization code flow specified that he only wants to grant "read" permission to the resource server.

If we would just check if the user has the scope allowed by using the usual validateScope-method, an attacker could get with a refresh token more privileges than actually allowed by the user in the first password or authorization- grant. So we actually have to persist the original requested scope from the user then always check against that original scope when a scope is specified in the refresh token flow.

@jankapunkt
Copy link
Member

@jorenvandeweyer is this still an issue?

@jorenvandeweyer
Copy link
Member Author

Yes this is still an issue and it is not that easy to fix.

  1. We should check our scope input better
scope       = scope-token *( SP scope-token )
scope-token = 1*( %x21 / %x23-5B / %x5D-7E )

regex: ^[\x21\x23-\x5B\x5D-\x7E]+(?:\s+[\x21\x23-\x5B\x5D-\x7E]+)*$

  1. We should always parse the scope into an array of strings, this would be breaking.

  2. Then we can validate the scope input against the original scope with something like this

const previousScopes = ['user:read', 'user:write']
const newScopes = ['user:read']

const valid = newScopes.every(newScope => previousScopes.includes(newScope))

@jankapunkt
Copy link
Member

We should always parse the scope into an array of strings, this would be breaking

If it's entirely internal (transforming any incoming scope to an array before furhter) I think it's at least non-breaking for "the outside", right?

I think this should be implemented in the formats package, what do you think?

@jorenvandeweyer
Copy link
Member Author

I think we should also change it for the outside.

validateScope?(user: User, client: Client, scope: string | string[], callback?: Callback<string | Falsey>): Promise<string | string[] | Falsey>;

would become:

validateScope?(user: User, client: Client, scope: string[]): Promise<string[] | Falsey>;

which means that all implementations of validateScope functions should return a string instead of an array of strings.

@jankapunkt
Copy link
Member

Then let's target this for 5.x and mark it breaking

@jankapunkt jankapunkt added the backwards breaking ✂️ This change will not work with the current version of the module. label Aug 28, 2023
@jankapunkt jankapunkt added this to the v5 milestone Aug 28, 2023
@jankapunkt jankapunkt mentioned this issue Sep 6, 2023
1 task
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backwards breaking ✂️ This change will not work with the current version of the module. compliance 📜 OAuth 2.0 standard compliance good first issue ✅ Good for newcomers
Projects
None yet
Development

No branches or pull requests

3 participants