Hear from the Spring team this January at SpringOne. >

CVE-2022-31690: Privilege Escalation in spring-security-oauth2-client

Spring Security 5.6.9 and 5.7.5 released on October 31st, 2022 included a fix for CVE-2022-31690 affecting the mapping of authorized scopes in spring-security-oauth2-client. Users are encouraged to update as soon as possible.


Users who have applied the mitigation should take note of the following impact:

No authorized scopes are mapped to the principal (current user) when the Authorization Server (AS) responds to the OAuth2 Access Token Response with an empty or missing scope parameter.

If you are affected by this vulnerability, users will not be granted any authorities beginning with SCOPE_ when the AS does not return scopes. Only the special authority ROLE_USER is given to the principal.

Beginning with 6.0, the special authority is changed to OAUTH2_USER (or OIDC_USER). See Using a GrantedAuthoritiesMapper in the 6.0 reference documentation for more information.

If additional authorities are required for your application, you should register a GrantedAuthoritiesMapper @Bean to provide the needed authorities, as in the following example:

public class OAuth2LoginSecurityConfig {

	public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
			.authorizeHttpRequests((authorize) -> authorize
				.mvcMatchers(HttpMethod.GET, "/messages").hasAuthority("SCOPE_read")
				// ...
		return http.build();

	public GrantedAuthoritiesMapper userAuthoritiesMapper() {
		return (authorities) -> {
			if (!authorities.isEmpty() && authorities.stream()
					.anyMatch(authority -> authority.startsWith("SCOPE_"))) {
				// AS returned scopes that are mapped to SCOPE_ by Spring Security
				return authorities;

			// AS returned no scopes, either because none were granted or because requested == granted
			// See https://www.rfc-editor.org/rfc/rfc6749#section-5.1 and your AS documentation
			// You can access the ID Token or UserInfo attributes to map authorities based on the user:

			Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
			authorities.forEach(authority -> {
				if (OidcUserAuthority.class.isInstance(authority)) {
					OidcUserAuthority oidcUserAuthority = (OidcUserAuthority) authority;
					OidcIdToken idToken = oidcUserAuthority.getIdToken();
					// ...
				} else if (OAuth2UserAuthority.class.isInstance(authority)) {
					OAuth2UserAuthority oauth2UserAuthority = (OAuth2UserAuthority) authority;
					Map<String, Object> userAttributes = oauth2UserAuthority.getAttributes();
					// ...

			return grantedAuthorities;

			// Alternatively, provide a fallback set of authorities that make sense for your application
			// return AuthorityUtils.createAuthorityList("ROLE_USER", "SCOPE_read");

It is not recommended to simply map authorities from the ClientRegistration.
comments powered by Disqus