|
@@ -2,41 +2,304 @@
|
|
= What's New in Spring Security 6.3
|
|
= What's New in Spring Security 6.3
|
|
|
|
|
|
Spring Security 6.3 provides a number of new features.
|
|
Spring Security 6.3 provides a number of new features.
|
|
-Below are the highlights of the release.
|
|
|
|
|
|
+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.
|
|
|
|
|
|
-== General
|
|
|
|
|
|
+== Passive JDK Serialization Support
|
|
|
|
|
|
-- https://spring.io/blog/2024/01/19/spring-security-6-3-adds-passive-jdk-serialization-deserialization-for[blog post] - Added Passive JDK Serialization/Deserialization for Seamless Upgrades
|
|
|
|
|
|
+When it comes to its support for JDK-serialized security components, Spring Security has historically been quite aggressive, supporting each serialization version for only one Spring Security minor version.
|
|
|
|
+This meant that if you had JDK-serialized security components, then they would need to be evacuated before upgrading to the next Spring Security version since they would no longer be deserializable.
|
|
|
|
|
|
-== Authentication
|
|
|
|
-
|
|
|
|
-- https://github.com/spring-projects/spring-security/issues/7395[gh-7395] - xref:features/authentication/password-storage.adoc#authentication-compromised-password-check[docs] - Add Compromised Password Checker
|
|
|
|
|
|
+Now that Spring Security performs a minor release every six months, this became a much larger pain point.
|
|
|
|
+To address that, Spring Security now will https://spring.io/blog/2024/01/19/spring-security-6-3-adds-passive-jdk-serialization-deserialization-for[maintain passivity with JDK serialization], like it does with JSON serialization, making for more seamless upgrades.
|
|
|
|
|
|
== Authorization
|
|
== Authorization
|
|
|
|
|
|
-- https://github.com/spring-projects/spring-security/issues/14596[gh-14596] - xref:servlet/authorization/method-security.adoc[docs] - Add Programmatic Proxy Support for Method Security
|
|
|
|
-- https://github.com/spring-projects/spring-security/issues/14597[gh-14597] - xref:servlet/authorization/method-security.adoc[docs] - Add Securing of Return Values
|
|
|
|
-- https://github.com/spring-projects/spring-security/issues/14601[gh-14601] - xref:servlet/authorization/method-security.adoc#fallback-values-authorization-denied[docs] - Add Authorization Denied Handlers for Method Security
|
|
|
|
|
|
+An ongoing theme for the last several releases has been to refactor and improve Spring Security's authorization subsystem.
|
|
|
|
+Starting with replacing the `AccessDecisionManager` API with `AuthorizationManager` it's now come to the point where we are able to add several exciting new features.
|
|
|
|
|
|
-== Configuration
|
|
|
|
|
|
+=== Annotation Parameters - https://github.com/spring-projects/spring-security/issues/14480[#14480]
|
|
|
|
|
|
-- https://github.com/spring-projects/spring-security/issues/6192[gh-6192] - xref:reactive/authentication/concurrent-sessions-control.adoc[(docs)] - Add Concurrent Sessions Control on WebFlux
|
|
|
|
|
|
+The first 6.3 feature is https://github.com/spring-projects/spring-security/issues/14480[support for annotation parameters].
|
|
|
|
+Consider Spring Security's support for xref:servlet/authorization/method-security.adoc#meta-annotations[meta-annotations] like this one:
|
|
|
|
|
|
-== CAS
|
|
|
|
|
|
+[tabs]
|
|
|
|
+======
|
|
|
|
+Java::
|
|
|
|
++
|
|
|
|
+[source,java,role="primary"]
|
|
|
|
+----
|
|
|
|
+@Retention(RetentionPolicy.RUNTIME)
|
|
|
|
+@Target(ElementType.METHOD)
|
|
|
|
+@PreAuthorize("hasAuthority('SCOPE_message:read')")
|
|
|
|
+public @interface HasMessageRead {}
|
|
|
|
+----
|
|
|
|
|
|
-- https://github.com/spring-projects/spring-security/pull/14193[gh-14193] - Added support for CAS Gateway Authentication
|
|
|
|
|
|
+Kotlin::
|
|
|
|
++
|
|
|
|
+.Kotlin
|
|
|
|
+[source,kotlin,role="secondary"]
|
|
|
|
+----
|
|
|
|
+@Retention(RetentionPolicy.RUNTIME)
|
|
|
|
+@Target(ElementType.METHOD)
|
|
|
|
+@PreAuthorize("hasAuthority('SCOPE_message:read')")
|
|
|
|
+annotation class HasMessageRead
|
|
|
|
+----
|
|
|
|
+======
|
|
|
|
+
|
|
|
|
+Before this release, something like this is only helpful when it is used widely across the codebase.
|
|
|
|
+But now, xref:servlet/authorization/method-security.adoc#_templating_meta_annotation_expressions[you can add parameters] like so:
|
|
|
|
+
|
|
|
|
+[tabs]
|
|
|
|
+======
|
|
|
|
+Java::
|
|
|
|
++
|
|
|
|
+[source,java,role="primary"]
|
|
|
|
+----
|
|
|
|
+@Retention(RetentionPolicy.RUNTIME)
|
|
|
|
+@Target(ElementType.METHOD)
|
|
|
|
+@PreAuthorize("hasAuthority('SCOPE_{scope}')")
|
|
|
|
+public @interface HasScope {
|
|
|
|
+ String scope();
|
|
|
|
+}
|
|
|
|
+----
|
|
|
|
+
|
|
|
|
+Kotlin::
|
|
|
|
++
|
|
|
|
+[source,kotlin,role="secondary"]
|
|
|
|
+----
|
|
|
|
+@Retention(RetentionPolicy.RUNTIME)
|
|
|
|
+@Target(ElementType.METHOD)
|
|
|
|
+@PreAuthorize("hasAuthority('SCOPE_{scope}')")
|
|
|
|
+annotation class HasScope (val scope:String)
|
|
|
|
+----
|
|
|
|
+======
|
|
|
|
+
|
|
|
|
+making it possible to do things like this:
|
|
|
|
+
|
|
|
|
+[tabs]
|
|
|
|
+======
|
|
|
|
+Java::
|
|
|
|
++
|
|
|
|
+[source,java,role="primary"]
|
|
|
|
+----
|
|
|
|
+@HasScope("message:read")
|
|
|
|
+public String method() { ... }
|
|
|
|
+----
|
|
|
|
+
|
|
|
|
+Kotlin::
|
|
|
|
++
|
|
|
|
+[source,kotlin,role="secondary"]
|
|
|
|
+----
|
|
|
|
+@HasScope("message:read")
|
|
|
|
+fun method(): String { ... }
|
|
|
|
+----
|
|
|
|
+======
|
|
|
|
+
|
|
|
|
+and apply your SpEL expression in several more places.
|
|
|
|
+
|
|
|
|
+=== Secure Return Values - https://github.com/spring-projects/spring-security/issues/14596[#14596], https://github.com/spring-projects/spring-security/issues/14597[#14597]
|
|
|
|
+
|
|
|
|
+Since the early days of Spring Security, you've been able to xref:servlet/authorization/method-security.adoc#use-preauthorize[annotate Spring beans with `@PreAuthorize` and `@PostAuthorize`].
|
|
|
|
+But controllers, services, and repositories are not the only things you care to secure.
|
|
|
|
+For example, what about a domain object `Order` where only admins should be able to call the `Order#getPayment` method?
|
|
|
|
+
|
|
|
|
+Now in 6.3, https://github.com/spring-projects/spring-security/issues/14597[you can annotate those methods], too.
|
|
|
|
+First, annotate the `getPayment` method like you would a Spring bean:
|
|
|
|
+
|
|
|
|
+[tabs]
|
|
|
|
+======
|
|
|
|
+Java::
|
|
|
|
++
|
|
|
|
+[source,java,role="primary"]
|
|
|
|
+----
|
|
|
|
+public class Order {
|
|
|
|
+
|
|
|
|
+ @HasScope("payment:read")
|
|
|
|
+ Payment getPayment() { ... }
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+----
|
|
|
|
+
|
|
|
|
+Kotlin::
|
|
|
|
++
|
|
|
|
+[source,kotlin,role="secondary"]
|
|
|
|
+----
|
|
|
|
+class Order {
|
|
|
|
+
|
|
|
|
+ @HasScope("payment:read")
|
|
|
|
+ fun getPayment(): Payment { ... }
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+----
|
|
|
|
+======
|
|
|
|
+
|
|
|
|
+And then xref:servlet/authorization/method-security.adoc#authorize-object[annotate your Spring Data repository with `@AuthorizeReturnObject`] like so:
|
|
|
|
+
|
|
|
|
+[tabs]
|
|
|
|
+======
|
|
|
|
+Java::
|
|
|
|
++
|
|
|
|
+[source,java,role="primary"]
|
|
|
|
+----
|
|
|
|
+public interface OrderRepository implements CrudRepository<Order, String> {
|
|
|
|
+
|
|
|
|
+ @AuthorizeReturnObject
|
|
|
|
+ Optional<Order> findOrderById(String id);
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+----
|
|
|
|
+
|
|
|
|
+Kotlin::
|
|
|
|
++
|
|
|
|
+[source,kotlin,role="secondary"]
|
|
|
|
+----
|
|
|
|
+
|
|
|
|
+interface OrderRepository : CrudRepository<Order, String> {
|
|
|
|
+ @AuthorizeReturnObject
|
|
|
|
+ fun findOrderById(id: String?): Optional<Order?>?
|
|
|
|
+}
|
|
|
|
+----
|
|
|
|
+======
|
|
|
|
+
|
|
|
|
+At that point, Spring Security will protect any `Order` returned from `findOrderById` by way of https://github.com/spring-projects/spring-security/issues/14596[proxying the `Order` instance].
|
|
|
|
|
|
-== Crypto
|
|
|
|
|
|
+=== Error Handling - https://github.com/spring-projects/spring-security/issues/14598[#14598], https://github.com/spring-projects/spring-security/issues/14600[#14600], https://github.com/spring-projects/spring-security/issues/14601[#14601]
|
|
|
|
|
|
-- https://github.com/spring-projects/spring-security/issues/14202[gh-14202] - Migrated spring-security-rsa into spring-security-crypto
|
|
|
|
|
|
+In this release, you can also https://github.com/spring-projects/spring-security/issues/14601[intercept and handle failure at the method level] with its last new method security annotation.
|
|
|
|
|
|
-== OAuth2
|
|
|
|
|
|
+When you xref:servlet/authorization/method-security.adoc#fallback-values-authorization-denied[annotate a method with `@HandleAuthorizationDenied`] like so:
|
|
|
|
|
|
|
|
+[tabs]
|
|
|
|
+======
|
|
|
|
+Java::
|
|
|
|
++
|
|
|
|
+[source,java,role="primary"]
|
|
|
|
+----
|
|
|
|
+public class Payment {
|
|
|
|
+ @HandleAuthorizationDenied(handlerClass=Mask.class)
|
|
|
|
+ @PreAuthorize("hasAuthority('card:read')")
|
|
|
|
+ public String getCreditCardNumber() { ... }
|
|
|
|
+}
|
|
|
|
+----
|
|
|
|
+
|
|
|
|
+Kotlin::
|
|
|
|
++
|
|
|
|
+[source,kotlin,role="secondary"]
|
|
|
|
+----
|
|
|
|
+class Payment {
|
|
|
|
+ @HandleAuthorizationDenied(handlerClass=Mask.class)
|
|
|
|
+ @PreAuthorize("hasAuthority('card:read')")
|
|
|
|
+ fun getCreditCardNumber(): String { ... }
|
|
|
|
+}
|
|
|
|
+----
|
|
|
|
+======
|
|
|
|
+
|
|
|
|
+and publish a `Mask` bean:
|
|
|
|
+
|
|
|
|
+[tabs]
|
|
|
|
+======
|
|
|
|
+Java::
|
|
|
|
++
|
|
|
|
+[source,java,role="primary"]
|
|
|
|
+----
|
|
|
|
+@Component
|
|
|
|
+public class Mask implements MethodAuthorizationDeniedHandler {
|
|
|
|
+ @Override
|
|
|
|
+ public Object handleDeniedInvocation(MethodInvocation invocation, AuthorizationResult result) {
|
|
|
|
+ return "***";
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+----
|
|
|
|
+
|
|
|
|
+Kotlin::
|
|
|
|
++
|
|
|
|
+[source,kotlin,role="secondary"]
|
|
|
|
+----
|
|
|
|
+@Component
|
|
|
|
+class Mask : MethodAuthorizationDeniedHandler {
|
|
|
|
+ fun handleDeniedInvocation(invocation: MethodInvocation?, result: AuthorizationResult?): Any = "***"
|
|
|
|
+}
|
|
|
|
+----
|
|
|
|
+======
|
|
|
|
+
|
|
|
|
+then any unauthorized call to `Payment#getCreditCardNumber` will return `\***` instead of the number.
|
|
|
|
+
|
|
|
|
+You can see all these features at work together in https://github.com/spring-projects/spring-security-samples/tree/main/servlet/spring-boot/java/data[the latest Spring Security Data sample].
|
|
|
|
+
|
|
|
|
+== Compromised Password Checking - https://github.com/spring-projects/spring-security/issues/7395[#7395]
|
|
|
|
+
|
|
|
|
+If you are going to let users pick passwords, it's critical to ensure that such a password isn't already compromised.
|
|
|
|
+Spring Security 6.3 makes this as simple as xref:features/authentication/password-storage.adoc#authentication-compromised-password-check[publishing a `CompromisedPasswordChecker` bean]:
|
|
|
|
+
|
|
|
|
+[tabs]
|
|
|
|
+======
|
|
|
|
+Java::
|
|
|
|
++
|
|
|
|
+[source,java,role="primary"]
|
|
|
|
+----
|
|
|
|
+@Bean
|
|
|
|
+public CompromisedPasswordChecker compromisedPasswordChecker() {
|
|
|
|
+ return new HaveIBeenPwnedRestApiPasswordChecker();
|
|
|
|
+}
|
|
|
|
+----
|
|
|
|
+
|
|
|
|
+Kotlin::
|
|
|
|
++
|
|
|
|
+[source,kotlin,role="secondary"]
|
|
|
|
+----
|
|
|
|
+@Bean
|
|
|
|
+fun compromisedPasswordChecker(): CompromisedPasswordChecker = HaveIBeenPwnedRestApiPasswordChecker()
|
|
|
|
+----
|
|
|
|
+======
|
|
|
|
+
|
|
|
|
+== `spring-security-rsa` is now part of Spring Security - https://github.com/spring-projects/spring-security/issues/14202[#14202]
|
|
|
|
+
|
|
|
|
+Since 2017, Spring Security has been undergoing a long-standing initiative to fold various Spring Security extensions into Spring Security proper.
|
|
|
|
+In 6.3, `spring-security-rsa` becomes the latest of these projects which will help the team maintain and add features to it, long-term.
|
|
|
|
+
|
|
|
|
+`spring-security-rsa` provides a number of https://github.com/spring-projects/spring-security/blob/main/crypto/src/main/java/org/springframework/security/crypto/encrypt/RsaSecretEncryptor.java[handy `BytesEncryptor`] https://github.com/spring-projects/spring-security/blob/main/crypto/src/main/java/org/springframework/security/crypto/encrypt/RsaRawEncryptor.java[implementations] as well as https://github.com/spring-projects/spring-security/blob/main/crypto/src/main/java/org/springframework/security/crypto/encrypt/KeyStoreKeyFactory.java[a simpler API for working with ``KeyStore``s].
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+== OAuth 2.0 Token Exchange Grant - https://github.com/spring-projects/spring-security/issues/5199[#5199]
|
|
|
|
+
|
|
|
|
+One of https://github.com/spring-projects/spring-security/issues/5199[the most highly-voted OAuth 2.0 features] in Spring Security is now in place in 6.3, which is the support for https://datatracker.ietf.org/doc/html/rfc8693#section-2[the OAuth 2.0 Token Exchange grant].
|
|
|
|
+
|
|
|
|
+For xref:servlet/oauth2/client/authorization-grants.adoc#token-exchange-grant-access-token[any client configured for token exchange], you can activate it in Spring Security by adding a `TokenExchangeAuthorizedClientProvider` instance to your `OAuth2AuthorizedClientManager` like so:
|
|
|
|
+
|
|
|
|
+[tabs]
|
|
|
|
+======
|
|
|
|
+Java::
|
|
|
|
++
|
|
|
|
+[source,java,role="primary"]
|
|
|
|
+----
|
|
|
|
+@Bean
|
|
|
|
+public OAuth2AuthorizedClientProvider tokenExchange() {
|
|
|
|
+ return new TokenExchangeOAuth2AuthorizedClientProvider();
|
|
|
|
+}
|
|
|
|
+----
|
|
|
|
+
|
|
|
|
+Kotlin::
|
|
|
|
++
|
|
|
|
+[source,kotlin,role="secondary"]
|
|
|
|
+----
|
|
|
|
+@Bean
|
|
|
|
+fun tokenExchange(): OAuth2AuthorizedClientProvider = TokenExchangeOAuth2AuthorizedClientProvider()
|
|
|
|
+----
|
|
|
|
+======
|
|
|
|
+
|
|
|
|
+and then xref:servlet/oauth2/client/authorized-clients.adoc#oauth2Client-registered-authorized-client[use the `@RegisteredOAuth2AuthorizedClient` annotation] as per usual to retrieve the appropriate token with the expanded privileges your resource server needs.
|
|
|
|
+
|
|
|
|
+== Additional Highlights
|
|
|
|
+
|
|
|
|
+- https://github.com/spring-projects/spring-security/pull/14655[gh-14655] - Add `DelegatingAuthenticationConverter
|
|
|
|
+- Add Concurrent Sessions Control on WebFlux - https://github.com/spring-projects/spring-security/issues/6192[gh-6192] - xref:reactive/authentication/concurrent-sessions-control.adoc[(docs)]
|
|
|
|
+- https://github.com/spring-projects/spring-security/pull/14193[gh-14193] - Added support for CAS Gateway Authentication
|
|
- https://github.com/spring-projects/spring-security/issues/13259[gh-13259] - Customize when UserInfo is called
|
|
- https://github.com/spring-projects/spring-security/issues/13259[gh-13259] - Customize when UserInfo is called
|
|
- https://github.com/spring-projects/spring-security/pull/14168[gh-14168] - Introduce Customizable AuthorizationFailureHandler in OAuth2AuthorizationRequestRedirectFilter
|
|
- https://github.com/spring-projects/spring-security/pull/14168[gh-14168] - Introduce Customizable AuthorizationFailureHandler in OAuth2AuthorizationRequestRedirectFilter
|
|
-- https://github.com/spring-projects/spring-security/issues/5199[gh-5199], https://github.com/spring-projects/spring-security/issues/14701[gh-14701] - Add support for OAuth 2.0 Token Exchange Grant
|
|
|
|
- https://github.com/spring-projects/spring-security/issues/14672[gh-14672] - Customize mapping the OidcUser from OidcUserRequest and OidcUserInfo
|
|
- https://github.com/spring-projects/spring-security/issues/14672[gh-14672] - Customize mapping the OidcUser from OidcUserRequest and OidcUserInfo
|
|
|
|
+- https://github.com/spring-projects/spring-security/issues/10538[gh-10538] - Support Certificate-Bound JWT Access Token Validation
|
|
|
|
+- https://github.com/spring-projects/spring-security/pull/14265[gh-14265] - Support Nexted username in UserInfo response
|
|
|
|
+- https://github.com/spring-projects/spring-security/pull/14265[gh-14449] - Add `SecurityContext` argument resolver
|
|
|
|
|
|
-== Documentation
|
|
|
|
-
|
|
|
|
-- https://github.com/spring-projects/spring-security/pull/14263[gh-14263] - xref:servlet/authentication/passwords/caching.adoc[(docs)] - Add documentation for CachingUserDetailsService
|
|
|
|
|
|
+And for an exhaustive list, please see the release notes for https://github.com/spring-projects/spring-security/releases/tag/6.3.0-RC1[6.3.0-RC1], https://github.com/spring-projects/spring-security/releases/tag/6.3.0-M3[6.3.0-M3], https://github.com/spring-projects/spring-security/releases/tag/6.3.0-M2[6.3.0-M2], and https://github.com/spring-projects/spring-security/releases/tag/6.3.0-M1[6.3.0-M1].
|
|
|
|
+`
|