| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 | 
							- [[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.
 
- == 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.
 
- == OAuth 2.0
 
- * `oauth2Login()` now accepts https://github.com/spring-projects/spring-security/pull/15237[`OAuth2AuthorizationRequestResolver` as a `@Bean`]
 
- * 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()
 
- 	}
 
- }
 
- ----
 
- ======
 
- * Deprecated `Default*` implementations of `OAuth2AccessTokenResponseClient`
 
- == 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.
 
- * 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 is now improved.
 
- Specifically, the following arrangement is invalid since an any request filter chain comes before all other filter chains:
 
- +
 
- [tabs]
 
- ======
 
- Java::
 
- +
 
- [source,java,role="primary"]
 
- ----
 
- @Bean 
 
- @Order(0)
 
- SecurityFilterChain api(HttpSecurity http) throws Exception {
 
-     http
 
-         .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].
 
- == One-Time Token Login
 
- Spring Security now xref:servlet/authentication/onetimetoken.adoc[supports One-Time Token Login] via the `oneTimeTokenLogin()` DSL.
 
- == 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`]
 
 
  |