| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328 | = OAuth MigrationsThe following steps relate to changes around how to configure OAuth 2.0.== Change Default `oauth2Login()` AuthoritiesIn 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"]----@Beanpublic 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"]----@Beanfun 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 StepsIf 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"]----@Beanpublic 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"]----@Beanfun 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 DeprecationsIn 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` DeprecationThe method `extractAuthorities` will be removed.Instead of extending `JwtAuthenticationConverter`, please supply a custom granted authorities converter with `JwtAuthenticationConverter#setJwtGrantedAuthoritiesConverter`.
 |