mirror of
				https://github.com/spring-projects/spring-security.git
				synced 2025-10-28 13:18:45 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			329 lines
		
	
	
		
			9.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			329 lines
		
	
	
		
			9.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| = OAuth Migrations
 | |
| 
 | |
| The following steps relate to changes around how to configure OAuth 2.0.
 | |
| 
 | |
| == Change Default `oauth2Login()` Authorities
 | |
| 
 | |
| In Spring Security 5, the default `GrantedAuthority` given to a user that authenticates with an OAuth2 or OpenID Connect 1.0 provider (via `oauth2Login()`) is `ROLE_USER`.
 | |
| 
 | |
| [NOTE]
 | |
| ====
 | |
| See xref:servlet/oauth2/login/advanced.adoc#oauth2login-advanced-map-authorities[Mapping User Authorities] for more information.
 | |
| ====
 | |
| 
 | |
| In Spring Security 6, the default authority given to a user authenticating with an OAuth2 provider is `OAUTH2_USER`.
 | |
| The default authority given to a user authenticating with an OpenID Connect 1.0 provider is `OIDC_USER`.
 | |
| These defaults allow clearer distinction of users that have authenticated with an OAuth2 or OpenID Connect 1.0 provider.
 | |
| 
 | |
| If you are using authorization rules or expressions such as `hasRole("USER")` or `hasAuthority("ROLE_USER")` to authorize users with this specific authority, the new defaults in Spring Security 6 will impact your application.
 | |
| 
 | |
| To opt into the new Spring Security 6 defaults, the following configuration can be used.
 | |
| 
 | |
| .Configure oauth2Login() with 6.0 defaults
 | |
| [tabs]
 | |
| ======
 | |
| Java::
 | |
| +
 | |
| [source,java,role="primary"]
 | |
| ----
 | |
| @Bean
 | |
| public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
 | |
| 	http
 | |
| 		// ...
 | |
| 		.oauth2Login((oauth2Login) -> oauth2Login
 | |
| 			.userInfoEndpoint((userInfo) -> userInfo
 | |
| 				.userAuthoritiesMapper(grantedAuthoritiesMapper())
 | |
| 			)
 | |
| 		);
 | |
| 	return http.build();
 | |
| }
 | |
| 
 | |
| private GrantedAuthoritiesMapper grantedAuthoritiesMapper() {
 | |
| 	return (authorities) -> {
 | |
| 		Set<GrantedAuthority> mappedAuthorities = new HashSet<>();
 | |
| 
 | |
| 		authorities.forEach((authority) -> {
 | |
| 			GrantedAuthority mappedAuthority;
 | |
| 
 | |
| 			if (authority instanceof OidcUserAuthority) {
 | |
| 				OidcUserAuthority userAuthority = (OidcUserAuthority) authority;
 | |
| 				mappedAuthority = new OidcUserAuthority(
 | |
| 					"OIDC_USER", userAuthority.getIdToken(), userAuthority.getUserInfo());
 | |
| 			} else if (authority instanceof OAuth2UserAuthority) {
 | |
| 				OAuth2UserAuthority userAuthority = (OAuth2UserAuthority) authority;
 | |
| 				mappedAuthority = new OAuth2UserAuthority(
 | |
| 					"OAUTH2_USER", userAuthority.getAttributes());
 | |
| 			} else {
 | |
| 				mappedAuthority = authority;
 | |
| 			}
 | |
| 
 | |
| 			mappedAuthorities.add(mappedAuthority);
 | |
| 		});
 | |
| 
 | |
| 		return mappedAuthorities;
 | |
| 	};
 | |
| }
 | |
| ----
 | |
| 
 | |
| Kotlin::
 | |
| +
 | |
| [source,kotlin,role="secondary"]
 | |
| ----
 | |
| @Bean
 | |
| fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
 | |
| 	http {
 | |
| 		// ...
 | |
| 		oauth2Login {
 | |
| 			userInfoEndpoint {
 | |
| 				userAuthoritiesMapper = grantedAuthoritiesMapper()
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	return http.build()
 | |
| }
 | |
| 
 | |
| private fun grantedAuthoritiesMapper(): GrantedAuthoritiesMapper {
 | |
| 	return GrantedAuthoritiesMapper { authorities ->
 | |
| 		authorities.map { authority ->
 | |
| 			when (authority) {
 | |
| 				is OidcUserAuthority ->
 | |
| 					OidcUserAuthority("OIDC_USER", authority.idToken, authority.userInfo)
 | |
| 				is OAuth2UserAuthority ->
 | |
| 					OAuth2UserAuthority("OAUTH2_USER", authority.attributes)
 | |
| 				else -> authority
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| ----
 | |
| 
 | |
| XML::
 | |
| +
 | |
| [source,xml,role="secondary"]
 | |
| ----
 | |
| <http>
 | |
| 	<oauth2-login user-authorities-mapper-ref="userAuthoritiesMapper" ... />
 | |
| </http>
 | |
| ----
 | |
| ======
 | |
| 
 | |
| [[servlet-oauth2-login-authorities-opt-out]]
 | |
| === Opt-out Steps
 | |
| 
 | |
| If configuring the new authorities gives you trouble, you can opt out and explicitly use the 5.8 authority of `ROLE_USER` with the following configuration.
 | |
| 
 | |
| .Configure oauth2Login() with 5.8 defaults
 | |
| [tabs]
 | |
| ======
 | |
| Java::
 | |
| +
 | |
| [source,java,role="primary"]
 | |
| ----
 | |
| @Bean
 | |
| public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
 | |
| 	http
 | |
| 		// ...
 | |
| 		.oauth2Login((oauth2Login) -> oauth2Login
 | |
| 			.userInfoEndpoint((userInfo) -> userInfo
 | |
| 				.userAuthoritiesMapper(grantedAuthoritiesMapper())
 | |
| 			)
 | |
| 		);
 | |
| 	return http.build();
 | |
| }
 | |
| 
 | |
| private GrantedAuthoritiesMapper grantedAuthoritiesMapper() {
 | |
| 	return (authorities) -> {
 | |
| 		Set<GrantedAuthority> mappedAuthorities = new HashSet<>();
 | |
| 
 | |
| 		authorities.forEach((authority) -> {
 | |
| 			GrantedAuthority mappedAuthority;
 | |
| 
 | |
| 			if (authority instanceof OidcUserAuthority) {
 | |
| 				OidcUserAuthority userAuthority = (OidcUserAuthority) authority;
 | |
| 				mappedAuthority = new OidcUserAuthority(
 | |
| 					"ROLE_USER", userAuthority.getIdToken(), userAuthority.getUserInfo());
 | |
| 			} else if (authority instanceof OAuth2UserAuthority) {
 | |
| 				OAuth2UserAuthority userAuthority = (OAuth2UserAuthority) authority;
 | |
| 				mappedAuthority = new OAuth2UserAuthority(
 | |
| 					"ROLE_USER", userAuthority.getAttributes());
 | |
| 			} else {
 | |
| 				mappedAuthority = authority;
 | |
| 			}
 | |
| 
 | |
| 			mappedAuthorities.add(mappedAuthority);
 | |
| 		});
 | |
| 
 | |
| 		return mappedAuthorities;
 | |
| 	};
 | |
| }
 | |
| ----
 | |
| 
 | |
| Kotlin::
 | |
| +
 | |
| [source,kotlin,role="secondary"]
 | |
| ----
 | |
| @Bean
 | |
| fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
 | |
| 	http {
 | |
| 		// ...
 | |
| 		oauth2Login {
 | |
| 			userInfoEndpoint {
 | |
| 				userAuthoritiesMapper = grantedAuthoritiesMapper()
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	return http.build()
 | |
| }
 | |
| 
 | |
| private fun grantedAuthoritiesMapper(): GrantedAuthoritiesMapper {
 | |
| 	return GrantedAuthoritiesMapper { authorities ->
 | |
| 		authorities.map { authority ->
 | |
| 			when (authority) {
 | |
| 				is OidcUserAuthority ->
 | |
| 					OidcUserAuthority("ROLE_USER", authority.idToken, authority.userInfo)
 | |
| 				is OAuth2UserAuthority ->
 | |
| 					OAuth2UserAuthority("ROLE_USER", authority.attributes)
 | |
| 				else -> authority
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| ----
 | |
| 
 | |
| XML::
 | |
| +
 | |
| [source,xml,role="secondary"]
 | |
| ----
 | |
| <http>
 | |
| 	<oauth2-login user-authorities-mapper-ref="userAuthoritiesMapper" ... />
 | |
| </http>
 | |
| ----
 | |
| ======
 | |
| 
 | |
| == Address OAuth2 Client Deprecations
 | |
| 
 | |
| In Spring Security 6, deprecated classes and methods were removed from xref:servlet/oauth2/client/index.adoc[OAuth2 Client].
 | |
| Each deprecation is listed below, along with a direct replacement.
 | |
| 
 | |
| === `ServletOAuth2AuthorizedClientExchangeFilterFunction`
 | |
| 
 | |
| The method `setAccessTokenExpiresSkew(...)` can be replaced with one of:
 | |
| 
 | |
| * `ClientCredentialsOAuth2AuthorizedClientProvider#setClockSkew(...)`
 | |
| * `RefreshTokenOAuth2AuthorizedClientProvider#setClockSkew(...)`
 | |
| * `JwtBearerOAuth2AuthorizedClientProvider#setClockSkew(...)`
 | |
| 
 | |
| The method `setClientCredentialsTokenResponseClient(...)` can be replaced with the constructor `ServletOAuth2AuthorizedClientExchangeFilterFunction(OAuth2AuthorizedClientManager)`.
 | |
| 
 | |
| [NOTE]
 | |
| ====
 | |
| See xref:servlet/oauth2/client/authorization-grants.adoc#oauth2Client-client-creds-grant[Client Credentials] for more information.
 | |
| ====
 | |
| 
 | |
| === `OidcUserInfo`
 | |
| 
 | |
| The method `phoneNumberVerified(String)` can be replaced with `phoneNumberVerified(Boolean)`.
 | |
| 
 | |
| === `OAuth2AuthorizedClientArgumentResolver`
 | |
| 
 | |
| The method `setClientCredentialsTokenResponseClient(...)` can be replaced with the constructor `OAuth2AuthorizedClientArgumentResolver(OAuth2AuthorizedClientManager)`.
 | |
| 
 | |
| [NOTE]
 | |
| ====
 | |
| See xref:servlet/oauth2/client/authorization-grants.adoc#oauth2Client-client-creds-grant[Client Credentials] for more information.
 | |
| ====
 | |
| 
 | |
| === `ClaimAccessor`
 | |
| 
 | |
| The method `containsClaim(...)` can be replaced with `hasClaim(...)`.
 | |
| 
 | |
| === `OidcClientInitiatedLogoutSuccessHandler`
 | |
| 
 | |
| The method `setPostLogoutRedirectUri(URI)` can be replaced with `setPostLogoutRedirectUri(String)`.
 | |
| 
 | |
| === `HttpSessionOAuth2AuthorizationRequestRepository`
 | |
| 
 | |
| The method `setAllowMultipleAuthorizationRequests(...)` has no direct replacement.
 | |
| 
 | |
| === `AuthorizationRequestRepository`
 | |
| 
 | |
| The method `removeAuthorizationRequest(HttpServletRequest)` can be replaced with `removeAuthorizationRequest(HttpServletRequest, HttpServletResponse)`.
 | |
| 
 | |
| === `ClientRegistration`
 | |
| 
 | |
| The method `getRedirectUriTemplate()` can be replaced with `getRedirectUri()`.
 | |
| 
 | |
| === `ClientRegistration.Builder`
 | |
| 
 | |
| The method `redirectUriTemplate(...)` can be replaced with `redirectUri(...)`.
 | |
| 
 | |
| === `AbstractOAuth2AuthorizationGrantRequest`
 | |
| 
 | |
| The constructor `AbstractOAuth2AuthorizationGrantRequest(AuthorizationGrantType)` can be replaced with `AbstractOAuth2AuthorizationGrantRequest(AuthorizationGrantType, ClientRegistration)`.
 | |
| 
 | |
| === `ClientAuthenticationMethod`
 | |
| 
 | |
| The static field `BASIC` can be replaced with `CLIENT_SECRET_BASIC`.
 | |
| 
 | |
| The static field `POST` can be replaced with `CLIENT_SECRET_POST`.
 | |
| 
 | |
| === `OAuth2AccessTokenResponseHttpMessageConverter`
 | |
| 
 | |
| The field `tokenResponseConverter` has no direct replacement.
 | |
| 
 | |
| The method `setTokenResponseConverter(...)` can be replaced with `setAccessTokenResponseConverter(...)`.
 | |
| 
 | |
| The field `tokenResponseParametersConverter` has no direct replacement.
 | |
| 
 | |
| The method `setTokenResponseParametersConverter(...)` can be replaced with `setAccessTokenResponseParametersConverter(...)`.
 | |
| 
 | |
| === `NimbusAuthorizationCodeTokenResponseClient`
 | |
| 
 | |
| The class `NimbusAuthorizationCodeTokenResponseClient` can be replaced with `DefaultAuthorizationCodeTokenResponseClient`.
 | |
| 
 | |
| === `NimbusJwtDecoderJwkSupport`
 | |
| 
 | |
| The class `NimbusJwtDecoderJwkSupport` can be replaced with `NimbusJwtDecoder` or `JwtDecoders`.
 | |
| 
 | |
| === `ImplicitGrantConfigurer`
 | |
| 
 | |
| The class `ImplicitGrantConfigurer` has no direct replacement.
 | |
| 
 | |
| [WARNING]
 | |
| ====
 | |
| Use of the `implicit` grant type is not recommended and all related support is removed in Spring Security 6.
 | |
| ====
 | |
| 
 | |
| === `AuthorizationGrantType`
 | |
| 
 | |
| The static field `IMPLICIT` has no direct replacement.
 | |
| 
 | |
| [WARNING]
 | |
| ====
 | |
| Use of the `implicit` grant type is not recommended and all related support is removed in Spring Security 6.
 | |
| ====
 | |
| 
 | |
| === `OAuth2AuthorizationResponseType`
 | |
| 
 | |
| The static field `TOKEN` has no direct replacement.
 | |
| 
 | |
| [WARNING]
 | |
| ====
 | |
| Use of the `implicit` grant type is not recommended and all related support is removed in Spring Security 6.
 | |
| ====
 | |
| 
 | |
| === `OAuth2AuthorizationRequest`
 | |
| 
 | |
| The static method `implicit()` has no direct replacement.
 | |
| 
 | |
| [WARNING]
 | |
| ====
 | |
| Use of the `implicit` grant type is not recommended and all related support is removed in Spring Security 6.
 | |
| ====
 | |
| 
 | |
| == Address `JwtAuthenticationConverter` Deprecation
 | |
| 
 | |
| The method `extractAuthorities` will be removed.
 | |
| Instead of extending `JwtAuthenticationConverter`, please supply a custom granted authorities converter with `JwtAuthenticationConverter#setJwtGrantedAuthoritiesConverter`.
 | |
| 
 |