|  | @@ -4,6 +4,194 @@
 | 
	
		
			
				|  |  |  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.
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -- https://github.com/spring-projects/spring-security/issues/4186[gh-4186] - Support `RoleHierarchy` in `AclAuthorizationStrategyImpl`
 | 
	
		
			
				|  |  | -- https://github.com/spring-projects/spring-security/issues/15136[gh-15136] - Support `RoleHierarchy` Bean in `authorizeHttpRequests` Kotlin DSL
 | 
	
		
			
				|  |  | +== Method Security
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +* All xref:servlet/authorization/method-security.adoc#using_metannotation-method-interceptors[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`]
 | 
	
		
			
				|  |  | +* OIDC Back-Channel support now accepts https://github.com/spring-projects/spring-security/issues/15003[logout tokens of type `logout+jwt`]
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +== 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].
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +== 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`]
 |