Skip to content
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

Incorrect scope map fix #12144

Closed
DamianFekete opened this issue Nov 7, 2022 · 4 comments
Closed

Incorrect scope map fix #12144

DamianFekete opened this issue Nov 7, 2022 · 4 comments
Assignees
Labels
in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) type: bug A general bug
Milestone

Comments

@DamianFekete
Copy link

Describe the bug
Scope mapping handling changed with #12112.

2915a70#diff-73bd44f873d78e3d71e6a0fa18644a304d562a4a9fd2e303e913f6ed20a0ad16R78-R83

image

  • OidcAuthorizationCodeAuthenticationProvider.authenticate() calls OidcAuthorizationCodeAuthenticationProvider.getResponse())
  • DefaultAuthorizationCodeTokenResponseClient.getTokenResponse does NOT add the scopes anymore. If no scopes are returned by default by the IdP, the scopes list is empty.
    • The comment If AccessTokenResponse.scope is empty, then we assume all requested scopes were granted. seems to say something completely different.
  • Back in OidcAuthorizationCodeAuthenticationProvider.authenticate() the user info has to be loaded: this.userService.loadUser().
  • OidcUserService.loadUser calls this.shouldRetrieveUserInfo(userRequest) which returns false now, because the scopes (userRequest.getAccessToken().getScopes()) is empty.
  • Because of this the userInfo is not loaded (it is null) and can't be used for example in the userAuthoritiesMapper.

To Reproduce
Our scopes are configured like this:

spring.security.oauth2.client.registration.default.scope=openid,profile,entitlements

Use the userAuthoritiesMapper with a token-uri endpoint that doesn't return a list of scopes.

        http.oauth2Login()
                .userInfoEndpoint().userAuthoritiesMapper(this.userAuthoritiesMapper());

In the authorities mapper try to use the oidcUserAuthority.getUserInfo() (which is now null).

Expected behavior
oidcUserAuthority.getUserInfo() should not be null.

Sample
No sample yet.

Ping @sjohnr

@DamianFekete DamianFekete added status: waiting-for-triage An issue we've not yet triaged type: bug A general bug labels Nov 7, 2022
@marcusdacoregio marcusdacoregio added the in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) label Nov 7, 2022
@sjohnr
Copy link
Member

sjohnr commented Nov 7, 2022

Thanks @DamianFekete. Please see the blog post on cve-2022-31690 and related advisory for details about the fix and why it was applied.

The comment If AccessTokenResponse.scope is empty, then we assume all requested scopes were granted. seems to say something completely different.

See RFC 6749, Section 5.1 for details on why we assume that all scopes were granted. The unfortunate reality is that we cannot rely on that assumption in all cases, hence the fix.

I'll look into a fix for OidcUserService. In the meantime, you can apply the following workaround to consume the latest version of Spring Security:

@Configuration
@EnableWebSecurity
public class SecurityConfiguration {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            // ...
            .oauth2Login(Customizer.withDefaults());
        return http.build();
    }

    @Bean
    public OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService() {
        OidcUserService oidcUserService = new OidcUserService();
        oidcUserService.setAccessibleScopes(Collections.emptySet());
        return oidcUserService;
    }

}

You can apply this workaround if it is acceptable to query the User Info endpoint on every login. If that's not acceptable in your case, let me know and I'll see about a different workaround.

@tobiaskrauss
Copy link

Thanks @sjohnr for your fast and helpful response. I was working with @DamianFekete on this issue. The workaround works fine for our application.
As we do not have too many users on this application, it should be fine for us that the user info endpoint is queried on every login.

@sjohnr sjohnr added this to the 5.6.10 milestone Nov 8, 2022
@sjohnr sjohnr removed the status: waiting-for-triage An issue we've not yet triaged label Nov 8, 2022
sjohnr added a commit to sjohnr/spring-security that referenced this issue Nov 8, 2022
@shresthaujjwal
Copy link

FYI, seeing same issue with 5.7.5 version too. Workaround works for me

@Clemens-E
Copy link

I'm seeing the same behaviour on 5.7.8 while integrating a login with Azure B2C IDM.
Spring was supposed to call the UserInfo endpoint to get the users' email/name after login, but
UserInfo is always null, and I can't see any call to the endpoint in the debug logs.
I can't exclude with certainty that it's not caused by some (miss-) configuration on either spring or azure b2c.

So, either way, I just wanted to put my fix here after hours of debugging in case anyone has a similar issue:
add the above-mentioned workaround (I had to remove the security filter chain as it interfered with my WebSecurityConfigurerAdapter and you can't have both)

@Configuration
@EnableWebSecurity
public class SecurityConfiguration {
    // see https://github.com/spring-projects/spring-security/issues/12144
    @Bean
    public OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService() {
        OidcUserService oidcUserService = new OidcUserService();
        oidcUserService.setAccessibleScopes(Collections.emptySet());
        return oidcUserService;
    }
}

However, spring now validates the UserInfo and will complain if you do not have a "sub" property, so make sure your UserInfo endpoint includes a sub property (mine didn't)
If you are using the Azure B2C Identity Experience Framework, you have to configure this:
https://github.com/azure-ad-b2c/samples/blob/master/policies/user-info-endpoint/policy/UserInfo_TrustFrameworkExtensions.xml#L34
and additionally add the mentioned sub claim with: <InputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="sub"/>
This way the sub property will be included in the UserInfo Response and spring won't complain.

I apologize if this seems off-topic, but I thought it would be valuable to share my solution here for others experiencing the same problem, even if it's a niche topic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) type: bug A general bug
Projects
None yet
Development

No branches or pull requests

6 participants