Describe the bug I'm converting my application from the Spring Security OAuth 2.5.2 version to the 5.6.9 And I see different behavior for the next use case: To get AccessToken for the first time User was asked to Approve Grants. He unchecked all the scopes and clicked "Allow" Spring Security accessToken.getScopes(): Uncheck all the scopes in the Grants Page treated the same as selecting all the scopes

Old implementation returned null for the "all scopes approved" and EmptySet for “no scopes selected” use cases. New implementation returns EmptySet in both cases.

I debugged the issue and found that the problem is in the org.springframework.security.oauth2.core.endpoint.DefaultMapOAuth2AccessTokenResponseConverter#getScopes(Map tokenResponseParameters) For the case "All scopes selected" tokenResponseParameters doesn't contain the "scope" parameter. And for the case "no scopes selected" it contains scope="". For both cases, the function returns EmptySet.

As a result - I can't ditinguish - did the user permitted scopes or not :(

To Reproduce On Approve Grants page - uncheck all the scopes. And then click "Allow". (I used PingFederate as CAS).

Expected behavior "no scopes selected" should return EmptySet. "All scopes selected" should return null

Sample

I don't know how to create an example that contains a CAS server...

Comment From: sjohnr

@ogarber thanks for reaching out!

Based on your description, it seems you are expecting backwards compatibility from the deprecated Spring Security OAuth library to Spring Security 5.x OAuth2 support, which is not the case. In this case, the OAuth2AccessToken class which carries the scopes from the access token response (in the OAuth2AccessTokenResponse class) does not allow for a null value. Changing it to do so would not be backwards compatible with the current support.

Further, while the spec allows for empty/missing scopes to be returned, it does not help clients disambiguate the meaning of the two, and libraries returning empty/null for scopes does not solve issues arising from the fact that is an ambiguous response from authorization servers. We have had issues in the past with such responses. Ideally, your authorization server would not return empty/null/missing for the case where the user selected all scopes, making empty/null/missing unambiguously refer to the same case (no scopes selected).

Given the above explanation, I don't believe this is something we would solve with the framework (nor do I believe it to be a safe thing to rely on in your application), so I'm going to close this. Please feel free to discuss further and if I missed something we can always re-open.