You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
328 lines
9.7 KiB
328 lines
9.7 KiB
= 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`. |
|
|
|
|