When connecting to a user provider, the script should provide a getScopes() callback.
Background:
A user logs in → the ProviderClass fetches the user from the external service, sets the profile, and commits the login action. Different users in the store can have different scopes. Currently, all scopes requested by the client are accepted as long as they are allowed by the client; there is no filtering based on the user repository yet. The ProviderClass should be able to add additional scopes.
What happens if a user requests scopes A, B, and D, but the client is only allowed to request A, B, and C, and the user storage returns scopes B and C for that user?
Proposal:
The final granted scopes should be the intersection of:
-
Scopes the client is allowed to request
-
Scopes the user requested
-
Scopes your user storage allows for that user
Step-by-step for your example:
-
User requested: A, B, D
-
Client allowed: A, B, C
-
User storage: B, C
Now compute intersections:
-
Request ∩ ClientAllowed
→ A, B -
(Request ∩ ClientAllowed) ∩ UserStorage
→ B
Final granted scopes: B
Because:
-
D is not allowed for the client → rejected
-
A is not allowed by user storage → rejected
-
C was never requested → not included
-
B is requested, allowed, and granted → included
Should we allow setting a scope if the user did not request it?
For example: a user store may need to handle different permissions for applications during login. If we only set scopes that the application explicitly requests, then the application would have to request all possible scopes in order to receive the ones defined for the user — because we cannot assign a scope that was not requested.
If the user does not request any scopes, we could instead assign the ones returned by the user store.
Follow-up question: Should this behavior be the default (no requested scopes = set it, requested scopes = filtering) , or should it be explicitly set by the UserProvider using something like overwriteScopes(:scopes)?
ref:
