- Issue created by @tregismoreira
- Merge request !30fix(drupal): Fix GraphQL OAuth access issue by ensuring full user entity is... → (Open) created by tregismoreira
- 🇳🇱Netherlands kingdutch
Access should be checked on the account proxy of the current user. Loading the user and checking directly on the user would create a security issue of escalated permissions since it ignores the token's restrictions.
Although the Access Policy API now somewhat changes this and reloading the user wouldn't actually change the permissions (since User::hasPermission delegates to the Access Policy API as of 10.3 → ), there are still implementations (such as Simple OAuth) which decorate the user object and change permission management that way (which was one of the few options available pre-10.3).
The hasPermission function of TokenAuthUser (which itself contains a fully loaded user object) looks as follows
public function hasPermission($permission) { // When the 'auth_user_id' isn't available on the token (which can happen // with the 'client credentials' grant type): // has permission checks are then only performed on the scopes. if ($this->token->get('auth_user_id')->isEmpty()) { return $this->token->hasPermission($permission); } // User #1 has all permissions. if ((int) $this->id() === 1) { return TRUE; } return $this->token->hasPermission($permission) && $this->subject->hasPermission($permission); }
In case of a system token (client credentials) only the permissions actually on the token will be used. In case of a user token (authorization code) then the token will only be allowed to do what both the user and token have access to. This ensures that 1) The external application using a token can not do things it wasn't allowed to do (e.g. delete a user) even if the user can take those actions 2) The user can not take actions they otherwise wouldn't be able to take (e.g. an application can offer user deletion to sufficiently permissioned users, but the user must still be allowed to do this through the normal UI).
The issue that you're running into is likely that the scopes being provided do not grant sufficient permissions. There's currently no way in simple_oauth to grant a base-set of permissions and the choice to make scopes point to a single permission was a conscious design decision implemented in #3283821: Support individual permission and role reference in the new scope data model → . The original job of scopes was described as follows (from an internal Open Social document before our contribution to Simple OAuth).
OAuth scopes exist not to indicate what a user may do, for this we have an extensive permission system built within Open Social. Instead OAuth scopes define what an application may do, either standalone or on behalf of a user. It's possible that an application may have permission from a user to take an action on their behalf but still encounter an access denied error because the user themselves does not have the permission to perform that action.
It's therefor important to realise that when talking about OAuth scopes the scopes indicate what type of trust the user (either acting on their behalf, or the site manager giving access to the platform) places in the application.My suggestion would be to map out your scenario and the permissions you need. It may either be solvable by changing your scope hierarchy, implementing a set of base permissions in Simple OAuth (anyone with a token regardless of scopes gets this), or by allowing multiple permissions to be assigned to a scope. (Those options are presented in order of author preference).