whats-new.adoc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. [[new]]
  2. = What's New in Spring Security 6.4
  3. Spring Security 6.4 provides a number of new features.
  4. 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.
  5. == Method Security
  6. * 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`]
  7. * `@AuthenticationPrincipal` and `@CurrentSecurityContext` now support xref:servlet/authorization/method-security.adoc#_templating_meta_annotation_expressions[annotation templates].
  8. +
  9. This means that you can now use Spring's meta-annotation support like so:
  10. +
  11. [tabs]
  12. ======
  13. Java::
  14. +
  15. [source,java,role="primary"]
  16. ----
  17. @Target(TargetType.TYPE)
  18. @Retention(RetentionPolicy.RUNTIME)
  19. @AuthenticationPrincipal("claims['{claim}']")
  20. @interface CurrentUsername {
  21. String claim() default "sub";
  22. }
  23. // ...
  24. @GetMapping
  25. public String method(@CurrentUsername("username") String username) {
  26. // ...
  27. }
  28. ----
  29. Kotlin::
  30. +
  31. [source,kotlin,role="secondary"]
  32. ----
  33. annotation CurrentUsername(val claim: String = "sub")
  34. // ...
  35. @GetMapping
  36. fun method(@CurrentUsername("username") val username: String): String {
  37. // ...
  38. }
  39. ----
  40. ======
  41. * 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.
  42. This aids in migration from earlier versions of Spring Security.
  43. == OAuth 2.0
  44. * `oauth2Login()` now accepts https://github.com/spring-projects/spring-security/pull/15237[`OAuth2AuthorizationRequestResolver` as a `@Bean`]
  45. * Added `loginPage()` to DSL in reactive `oauth2Login()`
  46. * OIDC Back-Channel support now accepts https://github.com/spring-projects/spring-security/issues/15003[logout tokens of type `logout+jwt`]
  47. * `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]
  48. * Added `RestClient`-based implementations of `OAuth2AccessTokenResponseClient` for more consistent configuration of access token requests.
  49. +
  50. To opt-in to using `RestClient` support, simply publish a bean for each grant type as in the following example:
  51. +
  52. [tabs]
  53. ======
  54. Java::
  55. +
  56. [source,java,role="primary"]
  57. ----
  58. @Configuration
  59. public class SecurityConfig {
  60. @Bean
  61. public OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> authorizationCodeAccessTokenResponseClient() {
  62. return new RestClientAuthorizationCodeTokenResponseClient();
  63. }
  64. @Bean
  65. public OAuth2AccessTokenResponseClient<OAuth2RefreshTokenGrantRequest> refreshTokenAccessTokenResponseClient() {
  66. return new RestClientRefreshTokenTokenResponseClient();
  67. }
  68. @Bean
  69. public OAuth2AccessTokenResponseClient<OAuth2ClientCredentialsGrantRequest> clientCredentialsAccessTokenResponseClient() {
  70. return new RestClientClientCredentialsTokenResponseClient();
  71. }
  72. @Bean
  73. public OAuth2AccessTokenResponseClient<JwtBearerGrantRequest> jwtBearerAccessTokenResponseClient() {
  74. return new RestClientJwtBearerTokenResponseClient();
  75. }
  76. @Bean
  77. public OAuth2AccessTokenResponseClient<TokenExchangeGrantRequest> tokenExchangeAccessTokenResponseClient() {
  78. return new RestClientTokenExchangeTokenResponseClient();
  79. }
  80. }
  81. ----
  82. Kotlin::
  83. +
  84. [source,kotlin,role="secondary"]
  85. ----
  86. @Configuration
  87. class SecurityConfig {
  88. @Bean
  89. fun authorizationCodeAccessTokenResponseClient(): OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> {
  90. return RestClientAuthorizationCodeTokenResponseClient()
  91. }
  92. @Bean
  93. fun refreshTokenAccessTokenResponseClient(): OAuth2AccessTokenResponseClient<OAuth2RefreshTokenGrantRequest> {
  94. return RestClientRefreshTokenTokenResponseClient()
  95. }
  96. @Bean
  97. fun clientCredentialsAccessTokenResponseClient(): OAuth2AccessTokenResponseClient<OAuth2ClientCredentialsGrantRequest> {
  98. return RestClientClientCredentialsTokenResponseClient()
  99. }
  100. @Bean
  101. fun jwtBearerAccessTokenResponseClient(): OAuth2AccessTokenResponseClient<JwtBearerGrantRequest> {
  102. return RestClientJwtBearerTokenResponseClient()
  103. }
  104. @Bean
  105. fun tokenExchangeAccessTokenResponseClient(): OAuth2AccessTokenResponseClient<TokenExchangeGrantRequest> {
  106. return RestClientTokenExchangeTokenResponseClient()
  107. }
  108. }
  109. ----
  110. ======
  111. * Deprecated `Default*` implementations of `OAuth2AccessTokenResponseClient`
  112. == SAML 2.0
  113. * Added xref:servlet/saml2/opensaml.adoc[OpenSAML 5 Support].
  114. 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.
  115. * Using EntityIDs for the `registrationId` is simplified.
  116. +
  117. A common pattern is to identify asserting parties by their `entityID`.
  118. In previous versions, this required directly configuring `OpenSamlAuthenticationRequestResolver`.
  119. 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.
  120. This allows you to use `RelyingPartyRegistrations` or `OpenSaml4/5AssertingPartyMetadataRepository` without also needing to modify the `registrationId` values or customize the request resolver.
  121. +
  122. Relatedly, you can now configure your `authenticationRequestUri` to xref:servlet/saml2/login/authentication-requests.adoc#configuring-authentication-request-uri[contain a query parameter]
  123. * Asserting Parties can now be refreshed in the background according to the metadata's expiry.
  124. +
  125. For example, you can now use xref:servlet/saml2/metadata.adoc#using-assertingpartymetadatarepository[`OpenSaml5AssertingPartyMetadataRepository`] to do:
  126. +
  127. [tabs]
  128. ======
  129. Java::
  130. +
  131. [source,java,role="primary"]
  132. ----
  133. @Component
  134. public class RefreshableRelyingPartyRegistrationRepository implements IterableRelyingPartyRegistrationRepository {
  135. private final AssertingPartyMetadataRepository assertingParties = OpenSaml5AssertingPartyMetadataRepository
  136. .fromTrustedMetadataLocation("https://idp.example.org").build();
  137. @Override
  138. public RelyingPartyRegistration findByRegistrationId(String registrationId) {
  139. AssertingPartyMetadata assertingParty = this.assertingParties.findByEntityId(registrationId);
  140. return RelyingPartyRegistration.withAssertingPartyMetadata(assertingParty)
  141. // relying party configurations
  142. .build();
  143. }
  144. // ...
  145. }
  146. ----
  147. Kotlin::
  148. +
  149. [source,kotlin,role="secondary"]
  150. ----
  151. @Component
  152. open class RefreshableRelyingPartyRegistrationRepository: IterableRelyingPartyRegistrationRepository {
  153. private val assertingParties: AssertingPartyMetadataRepository = OpenSaml5AssertingPartyMetadataRepository
  154. .fromTrustedMetadataLocation("https://idp.example.org").build()
  155. override fun findByRegistrationId(String registrationId): RelyingPartyRegistration {
  156. val assertingParty = this.assertingParties.findByEntityId(registrationId)
  157. return RelyingPartyRegistration.withAssertingPartyMetadata(assertingParty)
  158. // relying party configurations
  159. .build()
  160. }
  161. // ...
  162. }
  163. ----
  164. ======
  165. +
  166. This implementation also supports the validation of a metadata's signature.
  167. * You can now sign https://github.com/spring-projects/spring-security/pull/14916[relying party metadata]
  168. * `RelyingPartyRegistrationRepository` results can now be javadoc:org.springframework.security.saml2.provider.service.registration.CachingRelyingPartyRegistrationRepository[cached].
  169. This is helpful if you want to defer the loading of the registration values til after application startup.
  170. It is also helpful if you want to control when metadata gets refreshed.
  171. * 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]
  172. == Web
  173. * CSRF BREACH tokens are now https://github.com/spring-projects/spring-security/issues/15187[more consistent]
  174. * The Remember Me cookie now is https://github.com/spring-projects/spring-security/pull/15203[more customizable]
  175. * Security Filter Chain is now improved.
  176. Specifically, the following arrangement is invalid since an any request filter chain comes before all other filter chains:
  177. +
  178. [tabs]
  179. ======
  180. Java::
  181. +
  182. [source,java,role="primary"]
  183. ----
  184. @Bean
  185. @Order(0)
  186. SecurityFilterChain api(HttpSecurity http) throws Exception {
  187. http
  188. .authorizeHttpRequests(...)
  189. .httpBasic(...)
  190. return http.build();
  191. }
  192. @Bean
  193. @Order(1)
  194. SecurityFilterChain app(HttpSecurity http) throws Exception {
  195. http
  196. .securityMatcher("/app/**")
  197. .authorizeHttpRequests(...)
  198. .formLogin(...)
  199. return http.build();
  200. }
  201. ----
  202. Kotlin::
  203. +
  204. [source,kotlin,role="secondary"]
  205. ----
  206. @Bean
  207. @Order(0)
  208. fun api(val http: HttpSecurity): SecurityFilterChain {
  209. http {
  210. authorizeHttpRequests {
  211. // ...
  212. }
  213. }
  214. return http.build()
  215. }
  216. @Bean
  217. @Order(1)
  218. fun app(val http: HttpSecurity): SecurityFilterChain {
  219. http {
  220. securityMatcher("/app/**")
  221. authorizeHttpRequests {
  222. // ...
  223. }
  224. }
  225. return http.build()
  226. }
  227. ----
  228. ======
  229. You can read more https://github.com/spring-projects/spring-security/issues/15220[in the related ticket].
  230. == One-Time Token Login
  231. Spring Security now xref:servlet/authentication/onetimetoken.adoc[supports One-Time Token Login] via the `oneTimeTokenLogin()` DSL.
  232. == Passkeys
  233. Spring Security now has xref:servlet/authentication/passkeys.adoc[Passkeys] support.
  234. == Kotlin
  235. * 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
  236. * `@PreFilter` and `@PostFilter` are https://github.com/spring-projects/spring-security/pull/15095[now supported] in Kotlin
  237. * The Kotlin Reactive DSL now supports https://github.com/spring-projects/spring-security/pull/15013[`SecurityContextRepository`]
  238. == Acl
  239. * `AclAuthorizationStrategyImpl` now https://github.com/spring-projects/spring-security/issues/4186[supports `RoleHierarchy`]