123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394 |
- [[new]]
- = 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 https://github.com/spring-projects/spring-security/releases[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#check` is deprecated in favor of `AuthorizationManager#authorize`.
- This is primarily to allow the return type to be an interface instead of a concrete class.
- If you are invoking `AuthorizationManager#check`, please invoke `AuthorizationManager#authorize` instead.
- +
- Relatedly, `AuthorizationEventPublisher#publishEvent` that takes an `AuthorizationDecision` is deprecated in favor of a method of the same name that takes an `AuthorizationResult` interface instead.
- * *Method Security* - `PrePostTemplateDefaults` is deprecated in favor of the more generic `AnnotationTemplateExpressionDefaults` as there is now meta-annotation property support for `@AuthenticationPrincipal` and `@CurrentSecurityContext` as well.
- If you are constructing a `PrePostTemplateDefaults`, change this out for an `AnnotationTemplateExpressionDefaults`.
- * *OAuth 2.0* - `NimbusOpaqueTokenIntrospector` has been deprecated in favor of `SpringOpaqueTokenIntrospector` in order to remove Spring Security OAuth 2.0 Resource Server's reliance on the `oidc-oauth2-sdk` package.
- If you are constructing a `NimbusOpaqueTokenIntrospector`, replace it with ``SpringOpaqueTokenIntrospector``'s constructor
- * *OAuth 2.0* - `DefaultAuthorizationCodeTokenResponseClient`, `DefaultClientCredentialsTokenResponseClient`, `DefaultJwtBearerTokenResponseClient`, `DefaultPasswordTokenResponseClient`, `DefaultRefreshTokenTokenResponseClient`, and `DefaultTokenExchangeTokenResponseClient` are deprecated in favor of their `RestClient` equivalents.
- +
- Relatedly,`JwtBearerGrantRequestEntityConverter`, `OAuth2AuthorizationCodeGrantRequestEntityConverter`, `OAuth2ClientCredentialsGrantRequestEntityConverter`, `OAuth2PasswordGrantRequestEntityConverter`, `OAuth2RefreshTokenGrantRequestEntityConverter` are deprecated in favor of providing an instance of `DefaultOAuth2TokenRequestParametersConverter` to one of the above token response clients
- +
- For example, if you have the following arrangement:
- +
- [source,java]
- ----
- 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 `DefaultAuthorizationCodeTokenResponseClient` and `OAuth2AuthorizationCodeGrantRequestEntityConverter`.
- The recommended configuration is now:
- +
- [source,java]
- ----
- 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, `OpenSamlAuthenticationTokenConverter` is now replaced by `OpenSaml4AuthenticationTokenConverter` and `OpenSaml5AuthenticationTokenConverter`.
- 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 `AssertingPartyDetails` are deprecated in favor of equivalent methods that use the `AssertingPartyMetadata` interface.
- * *LDAP* - Usages of `DistinguishedName` are now deprecated in order to align with Spring LDAP's deprecations
- == One-Time Token Login
- * Spring Security now xref:servlet/authentication/onetimetoken.adoc[supports One-Time Token Login] via the `oneTimeTokenLogin()` DSL, including xref:servlet/authentication/onetimetoken.adoc#customize-generate-consume-token[JDBC support].
- == Passkeys
- Spring Security now has xref:servlet/authentication/passkeys.adoc[Passkeys] support.
- == Method Security
- * All xref:servlet/authorization/method-security.adoc#meta-annotations[method security annotations] now support {spring-framework-api-url}org/springframework/core/annotation/AliasFor.html[Framework's `@AliasFor`]
- * `@AuthenticationPrincipal` and `@CurrentSecurityContext` now support xref:servlet/authorization/method-security.adoc#_templating_meta_annotation_expressions[annotation templates].
- +
- This means that you can now use Spring's meta-annotation support like so:
- +
- [tabs]
- ======
- Java::
- +
- [source,java,role="primary"]
- ----
- @Target(TargetType.TYPE)
- @Retention(RetentionPolicy.RUNTIME)
- @AuthenticationPrincipal("claims['{claim}']")
- @interface CurrentUsername {
- String claim() default "sub";
- }
- // ...
- @GetMapping
- public String method(@CurrentUsername("username") String username) {
- // ...
- }
- ----
- Kotlin::
- +
- [source,kotlin,role="secondary"]
- ----
- annotation CurrentUsername(val claim: String = "sub")
- // ...
- @GetMapping
- fun method(@CurrentUsername("username") val username: String): String {
- // ...
- }
- ----
- ======
- * https://github.com/spring-projects/spring-security/issues/13490[Several] https://github.com/spring-projects/spring-security/issues/13234[improvements] https://github.com/spring-projects/spring-security/issues/15097[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 xref:servlet/authorization/method-security.adoc#authorize-return-object-aot[use `@AuthorizeReturnObject`]
- * Native applications can now xref:servlet/authorization/method-security.adoc#pre-post-authorize-aot[reference beans in `@PreAuthorize` and `@PostAuthorize`]
- * `SecurityAnnotationScanners` offers https://github.com/spring-projects/spring-security/issues/15700[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 accepts https://github.com/spring-projects/spring-security/pull/15237[`OAuth2AuthorizationRequestResolver` as a `@Bean`]
- * `ClientRegistrations` now supports externally obtained configuration
- * Added `loginPage()` to DSL in reactive `oauth2Login()`
- * OIDC Back-Channel support now accepts https://github.com/spring-projects/spring-security/issues/15003[logout tokens of type `logout+jwt`]
- * `RestClient` can now be xref:servlet/oauth2/index.adoc#oauth2-client-access-protected-resources[configured] with `OAuth2ClientHttpRequestInterceptor` to xref:servlet/oauth2/index.adoc#oauth2-client-accessing-protected-resources-example[make protected resources requests]
- * Added `RestClient`-based implementations of `OAuth2AccessTokenResponseClient` for more consistent configuration of access token requests.
- +
- To opt-in to using `RestClient` support, simply publish a bean for each grant type as in the following example:
- +
- [tabs]
- ======
- Java::
- +
- [source,java,role="primary"]
- ----
- @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();
- }
- }
- ----
- Kotlin::
- +
- [source,kotlin,role="secondary"]
- ----
- @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 https://github.com/spring-projects/spring-security/issues/15534[supports refresh tokens]
- == SAML 2.0
- * Added xref:servlet/saml2/opensaml.adoc[OpenSAML 5 Support].
- Now you can use either OpenSAML 4 or OpenSAML 5; by default, Spring Security will select the write implementations based on what's on your classpath.
- * Using EntityIDs for the `registrationId` is simplified.
- +
- A common pattern is to identify asserting parties by their `entityID`.
- In previous versions, this required directly configuring `OpenSamlAuthenticationRequestResolver`.
- Now, the request resolver looks by default for the `registrationId` https://github.com/spring-projects/spring-security/issues/15017[as a request parameter] in addition to looking for it in the path.
- This allows you to use `RelyingPartyRegistrations` or `OpenSaml4/5AssertingPartyMetadataRepository` without also needing to modify the `registrationId` values or customize the request resolver.
- +
- Relatedly, you can now configure your `authenticationRequestUri` to xref:servlet/saml2/login/authentication-requests.adoc#configuring-authentication-request-uri[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 xref:servlet/saml2/metadata.adoc#using-assertingpartymetadatarepository[`OpenSaml5AssertingPartyMetadataRepository`] to do:
- +
- [tabs]
- ======
- Java::
- +
- [source,java,role="primary"]
- ----
- @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();
- }
- // ...
- }
- ----
- Kotlin::
- +
- [source,kotlin,role="secondary"]
- ----
- @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 https://github.com/spring-projects/spring-security/pull/14916[relying party metadata]
- * `RelyingPartyRegistrationRepository` results can now be javadoc:org.springframework.security.saml2.provider.service.registration.CachingRelyingPartyRegistrationRepository[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 https://github.com/spring-projects/spring-security/issues/15147[uses the `application/samlmetadata+xml` MIME type]
- == Web
- * CSRF BREACH tokens are now https://github.com/spring-projects/spring-security/issues/15187[more consistent]
- * The Remember Me cookie now is https://github.com/spring-projects/spring-security/pull/15203[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:
- +
- [tabs]
- ======
- Java::
- +
- [source,java,role="primary"]
- ----
- @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();
- }
- ----
- Kotlin::
- +
- [source,kotlin,role="secondary"]
- ----
- @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 https://github.com/spring-projects/spring-security/issues/15220[in the related ticket].
- * `ServerHttpSecurity` now https://github.com/spring-projects/spring-security/issues/15974[picks up `ServerWebExchangeFirewall` as a `@Bean`]
- == Observability
- Observability now supports xref:servlet/integrations/observability.adoc#observability-tracing-disable[toggling authorization, authentication, and request observations separately]
- For example, to turn off filter chain observations, you can publish a `@Bean` like this one:
- [tabs]
- ======
- Java::
- +
- [source,java,role="primary"]
- ----
- @Bean
- SecurityObservationSettings allSpringSecurityObservations() {
- return SecurityObservationSettings.withDefaults()
- .shouldObserveFilterChains(false).build();
- }
- ----
- Kotlin::
- +
- [source,kotlin,role="secondary"]
- ----
- @Bean
- fun allSpringSecurityObservations(): SecurityObservationSettings {
- return SecurityObservationSettings.builder()
- .shouldObserveFilterChains(false).build()
- }
- ----
- ======
- == Kotlin
- * The Kotlin DSL now supports https://github.com/spring-projects/spring-security/issues/14935[SAML 2.0] and https://github.com/spring-projects/spring-security/issues/15171[`GrantedAuthorityDefaults`] and https://github.com/spring-projects/spring-security/issues/15136[`RoleHierarchy`] ``@Bean``s
- * `@PreFilter` and `@PostFilter` are https://github.com/spring-projects/spring-security/pull/15095[now supported] in Kotlin
- * The Kotlin Reactive DSL now supports https://github.com/spring-projects/spring-security/pull/15013[`SecurityContextRepository`]
- == Acl
- * `AclAuthorizationStrategyImpl` now https://github.com/spring-projects/spring-security/issues/4186[supports `RoleHierarchy`]
|