|
For the latest stable version, please use Spring Security 6.5.3! |
What’s New in Spring Security 6.4
Spring Security 6.4 provides a number of new features. Below are the highlights of the release, or you can view the release notes for a detailed listing of each feature and bug fix.
Deprecation Notices
As we get closer to Spring Security 7, it’s important to stay up to date on deprecations. As such, this section points out deprecations in the 6.4 release.
-
Method Security -
AuthorizationManager#checkis deprecated in favor ofAuthorizationManager#authorize. This is primarily to allow the return type to be an interface instead of a concrete class. If you are invokingAuthorizationManager#check, please invokeAuthorizationManager#authorizeinstead.Relatedly,
AuthorizationEventPublisher#publishEventthat takes anAuthorizationDecisionis deprecated in favor of a method of the same name that takes anAuthorizationResultinterface instead. -
Method Security -
PrePostTemplateDefaultsis deprecated in favor of the more genericAnnotationTemplateExpressionDefaultsas there is now meta-annotation property support for@AuthenticationPrincipaland@CurrentSecurityContextas well. If you are constructing aPrePostTemplateDefaults, change this out for anAnnotationTemplateExpressionDefaults. -
OAuth 2.0 -
NimbusOpaqueTokenIntrospectorhas been deprecated in favor ofSpringOpaqueTokenIntrospectorin order to remove Spring Security OAuth 2.0 Resource Server’s reliance on theoidc-oauth2-sdkpackage. If you are constructing aNimbusOpaqueTokenIntrospector, replace it withSpringOpaqueTokenIntrospector's constructor -
OAuth 2.0 -
DefaultAuthorizationCodeTokenResponseClient,DefaultClientCredentialsTokenResponseClient,DefaultJwtBearerTokenResponseClient,DefaultPasswordTokenResponseClient,DefaultRefreshTokenTokenResponseClient, andDefaultTokenExchangeTokenResponseClientare deprecated in favor of theirRestClientequivalents.Relatedly,
JwtBearerGrantRequestEntityConverter,OAuth2AuthorizationCodeGrantRequestEntityConverter,OAuth2ClientCredentialsGrantRequestEntityConverter,OAuth2PasswordGrantRequestEntityConverter,OAuth2RefreshTokenGrantRequestEntityConverterare deprecated in favor of providing an instance ofDefaultOAuth2TokenRequestParametersConverterto one of the above token response clientsFor example, if you have the following arrangement:
private static class MyCustomConverter extends AbstractOAuth2AuthorizationGrantRequestEntityConverter<OAuth2AuthorizationCodeGrantRequest> { @Override protected MultiValueMap<String, String> createParameters (OAuth2AuthorizationCodeGrantRequest request) { MultiValueMap<String, String> parameters = super.createParameters(request); parameters.add("custom", "value"); return parameters; } } @Bean OAuth2AccessTokenResponseClient authorizationCode() { DefaultAuthorizationCodeTokenResponseClient client = new DefaultAuthorizationCodeTokenResponseClient(); Converter<AuthorizationCodeGrantRequest, RequestEntity<?>> entityConverter = new OAuth2AuthorizationCodeGrantRequestEntityConverter(); entityConverter.setParametersConverter(new MyCustomConverter()); client.setRequestEntityConverter(entityConverter); return client; }This configuration is deprecated since it uses
DefaultAuthorizationCodeTokenResponseClientandOAuth2AuthorizationCodeGrantRequestEntityConverter. The recommended configuration is now:private static class MyCustomConverter implements Converter<OAuth2AuthorizationCodeGrantRequest, Map<String, String>> { @Override public MultiValueMap<String, String> convert(OAuth2AuthorizeCodeGrantRequest request) { MultiValueMap<String, String> parameters = OAuth2AuthorizationCodeGrantRequest.defaultParameters(request); parameters.add("custom", "value"); return parameters; } } @Bean OAuth2AccessTokenResponseClient authorizationCode() { RestClientAuthorizationCodeTokenResponseClient client = new RestClientAuthorizationCodeTokenResponseClient(); client.setParametersConverter(new MyCustomConverter()); return client; } -
SAML 2.0 - Unversioned OpenSAML implementations of Spring Security SAML 2.0 Service Provider’s interfaces have been deprecated in favor of versioned ones. For example,
OpenSamlAuthenticationTokenConverteris now replaced byOpenSaml4AuthenticationTokenConverterandOpenSaml5AuthenticationTokenConverter. If you are constructing one of these deprecated versions, please replace it with the one that corresponds to the OpenSAML version you are using. -
SAML 2.0 - Methods surrounding
AssertingPartyDetailsare deprecated in favor of equivalent methods that use theAssertingPartyMetadatainterface. -
LDAP - Usages of
DistinguishedNameare now deprecated in order to align with Spring LDAP’s deprecations
One-Time Token Login
-
Spring Security now supports One-Time Token Login via the
oneTimeTokenLogin()DSL, including JDBC support.
Passkeys
Spring Security now has Passkeys support.
Method Security
-
All method security annotations now support Framework’s
@AliasFor -
@AuthenticationPrincipaland@CurrentSecurityContextnow support annotation templates.This means that you can now use Spring’s meta-annotation support like so:
-
Java
-
Kotlin
@Target(TargetType.TYPE) @Retention(RetentionPolicy.RUNTIME) @AuthenticationPrincipal("claims['{claim}']") @interface CurrentUsername { String claim() default "sub"; } // ... @GetMapping public String method(@CurrentUsername("username") String username) { // ... }annotation CurrentUsername(val claim: String = "sub") // ... @GetMapping fun method(@CurrentUsername("username") val username: String): String { // ... } -
-
Several improvements were made to align Security’s annotation search with
AbstractFallbackMethodSecurityMetadataSource's algorithm. This aids in migration from earlier versions of Spring Security. -
Native applications can now use
@AuthorizeReturnObject -
Native applications can now reference beans in
@PreAuthorizeand@PostAuthorize -
SecurityAnnotationScannersoffers a convenient API for scanning for Security annotations and for adding Security’s selection and templating features to custom annotations
OAuth 2.0
-
oauth2Login()now acceptsOAuth2AuthorizationRequestResolveras a@Bean -
ClientRegistrationsnow supports externally obtained configuration -
Added
loginPage()to DSL in reactiveoauth2Login() -
OIDC Back-Channel support now accepts logout tokens of type
logout+jwt -
RestClientcan now be configured withOAuth2ClientHttpRequestInterceptorto make protected resources requests -
Added
RestClient-based implementations ofOAuth2AccessTokenResponseClientfor more consistent configuration of access token requests.To opt-in to using
RestClientsupport, simply publish a bean for each grant type as in the following example:-
Java
-
Kotlin
@Configuration public class SecurityConfig { @Bean public OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> authorizationCodeAccessTokenResponseClient() { return new RestClientAuthorizationCodeTokenResponseClient(); } @Bean public OAuth2AccessTokenResponseClient<OAuth2RefreshTokenGrantRequest> refreshTokenAccessTokenResponseClient() { return new RestClientRefreshTokenTokenResponseClient(); } @Bean public OAuth2AccessTokenResponseClient<OAuth2ClientCredentialsGrantRequest> clientCredentialsAccessTokenResponseClient() { return new RestClientClientCredentialsTokenResponseClient(); } @Bean public OAuth2AccessTokenResponseClient<JwtBearerGrantRequest> jwtBearerAccessTokenResponseClient() { return new RestClientJwtBearerTokenResponseClient(); } @Bean public OAuth2AccessTokenResponseClient<TokenExchangeGrantRequest> tokenExchangeAccessTokenResponseClient() { return new RestClientTokenExchangeTokenResponseClient(); } }@Configuration class SecurityConfig { @Bean fun authorizationCodeAccessTokenResponseClient(): OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> { return RestClientAuthorizationCodeTokenResponseClient() } @Bean fun refreshTokenAccessTokenResponseClient(): OAuth2AccessTokenResponseClient<OAuth2RefreshTokenGrantRequest> { return RestClientRefreshTokenTokenResponseClient() } @Bean fun clientCredentialsAccessTokenResponseClient(): OAuth2AccessTokenResponseClient<OAuth2ClientCredentialsGrantRequest> { return RestClientClientCredentialsTokenResponseClient() } @Bean fun jwtBearerAccessTokenResponseClient(): OAuth2AccessTokenResponseClient<JwtBearerGrantRequest> { return RestClientJwtBearerTokenResponseClient() } @Bean fun tokenExchangeAccessTokenResponseClient(): OAuth2AccessTokenResponseClient<TokenExchangeGrantRequest> { return RestClientTokenExchangeTokenResponseClient() } } -
-
Token Exchange now supports refresh tokens
SAML 2.0
-
Added OpenSAML 5 Support. Now you can use either OpenSAML 4 or OpenSAML 5; by default, Spring Security will select the right implementations based on what’s on your classpath.
-
Using EntityIDs for the
registrationIdis simplified.A common pattern is to identify asserting parties by their
entityID. In previous versions, this required directly configuringOpenSamlAuthenticationRequestResolver. Now, the request resolver looks by default for theregistrationIdas a request parameter in addition to looking for it in the path. This allows you to useRelyingPartyRegistrationsorOpenSaml4/5AssertingPartyMetadataRepositorywithout also needing to modify theregistrationIdvalues or customize the request resolver.Relatedly, you can now configure your
authenticationRequestUrito contain a query parameter -
Asserting Parties can now be refreshed in the background according to the metadata’s expiry.
For example, you can now use
OpenSaml5AssertingPartyMetadataRepositoryto do:-
Java
-
Kotlin
@Component public class RefreshableRelyingPartyRegistrationRepository implements IterableRelyingPartyRegistrationRepository { private final AssertingPartyMetadataRepository assertingParties = OpenSaml5AssertingPartyMetadataRepository .fromTrustedMetadataLocation("https://idp.example.org").build(); @Override public RelyingPartyRegistration findByRegistrationId(String registrationId) { AssertingPartyMetadata assertingParty = this.assertingParties.findByEntityId(registrationId); return RelyingPartyRegistration.withAssertingPartyMetadata(assertingParty) // relying party configurations .build(); } // ... }@Component open class RefreshableRelyingPartyRegistrationRepository: IterableRelyingPartyRegistrationRepository { private val assertingParties: AssertingPartyMetadataRepository = OpenSaml5AssertingPartyMetadataRepository .fromTrustedMetadataLocation("https://idp.example.org").build() override fun findByRegistrationId(String registrationId): RelyingPartyRegistration { val assertingParty = this.assertingParties.findByEntityId(registrationId) return RelyingPartyRegistration.withAssertingPartyMetadata(assertingParty) // relying party configurations .build() } // ... }This implementation also supports the validation of a metadata’s signature.
-
-
You can now sign relying party metadata
-
RelyingPartyRegistrationRepositoryresults can now be cached. This is helpful if you want to defer the loading of the registration values til after application startup. It is also helpful if you want to control when metadata gets refreshed via Spring Cache. -
To align with the SAML 2.0 standard, the metadata endpoint now uses the
application/samlmetadata+xmlMIME type
Web
-
CSRF BREACH tokens are now more consistent
-
The Remember Me cookie now is more customizable
-
Security Filter Chain finds more invalid configurations. For example, a filter chain declared after an any-request filter chain is invalid since it will never be invoked:
-
Java
-
Kotlin
@Bean @Order(0) SecurityFilterChain api(HttpSecurity http) throws Exception { http // implicit securityMatcher("/**") .authorizeHttpRequests(...) .httpBasic(...) return http.build(); } @Bean @Order(1) SecurityFilterChain app(HttpSecurity http) throws Exception { http .securityMatcher("/app/**") .authorizeHttpRequests(...) .formLogin(...) return http.build(); }@Bean @Order(0) fun api(val http: HttpSecurity): SecurityFilterChain { http { authorizeHttpRequests { // ... } } return http.build() } @Bean @Order(1) fun app(val http: HttpSecurity): SecurityFilterChain { http { securityMatcher("/app/**") authorizeHttpRequests { // ... } } return http.build() }You can read more in the related ticket.
-
-
ServerHttpSecuritynow picks upServerWebExchangeFirewallas a@Bean
Observability
Observability now supports toggling authorization, authentication, and request observations separately
For example, to turn off filter chain observations, you can publish a @Bean like this one:
-
Java
-
Kotlin
@Bean
SecurityObservationSettings allSpringSecurityObservations() {
return SecurityObservationSettings.withDefaults()
.shouldObserveFilterChains(false).build();
}
@Bean
fun allSpringSecurityObservations(): SecurityObservationSettings {
return SecurityObservationSettings.builder()
.shouldObserveFilterChains(false).build()
}
Kotlin
-
The Kotlin DSL now supports SAML 2.0 and
GrantedAuthorityDefaultsandRoleHierarchy@Beans -
@PreFilterand@PostFilterare now supported in Kotlin -
The Kotlin Reactive DSL now supports
SecurityContextRepository
Acl
-
AclAuthorizationStrategyImplnow supportsRoleHierarchy