- Over time, the API surface covered by the user authorization grant is expanded without further consent from the user
The default scope merging strategy will include all scopes registered by modules into respective global READ/WRITE scopes that can be granted. The problem is that this can lead to TOCTOU if a user grants one of these general scopes ahead of new scopes being registered, most likely by new modules.
This leads to a OAuth2 client having access to a broader API surface than what the Portal User consented to.
- Portal User grants an OAuth2 Application a global scope, say READ
- A new banking related module is deployed and this introduces a new scope called “BANKACCOUNT_READ” which is required to access its banking API
- The OAuth2 Application is now able to also call the banking API without needing to ask the Portal User for consent
- The OAuth2 Application should not be able to call the banking API without first obtaining further consent from the Portal User
- However unless the OAuth2 Application was incorrectly configured originally (missing scopes), the application will not contain any code for calling the banking API
- Only when the OAuth2 Application is upgraded might it need access to the banking API. At that stage the OAuth2 Application Administrator can include the BANKACCOUNT_READ into the global scope, by modifying the OAuth2 Application configuration
- The OAuth2 Application should then redirect the user to the Authorization Service and it should list all the scopes that are included in the global scope, including the new one, so the Portal User can provide consent.
- All scopes should be registered with a module namespace
- When the OAuth2 Application Administrator assigns scopes to the OAuth2 Application, they will have the option to add global scopes/aliases. However if doing so the stored configuration should only contain scopes of the corresponding type (READ/WRITE) that were available at the time
- When a scope is checked from an API, the aforementioned configuration for the scope will determine if the scope checker should take the namespace into account