reactive.adoc 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. = Reactive Migrations
  2. If you have already performed the xref:migration/index.adoc[initial migration steps] for your Reactive application, you're now ready to perform steps specific to Reactive applications.
  3. == Exploit Protection Migrations
  4. The following steps relate to changes around how to configure CSRF.
  5. === Configure `tokenFromMultipartDataEnabled`
  6. In Spring Security 5.8, the method `tokenFromMultipartDataEnabled` was deprecated in favor of `ServerCsrfTokenRequestAttributeHandler#setTokenFromMultipartDataEnabled`.
  7. To address the deprecation, the following code:
  8. .Configure `tokenFromMultipartDataEnabled` with DSL
  9. ====
  10. .Java
  11. [source,java,role="primary"]
  12. ----
  13. @Bean
  14. SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
  15. http
  16. // ...
  17. .csrf((csrf) -> csrf
  18. .tokenFromMultipartDataEnabled(true)
  19. );
  20. return http.build();
  21. }
  22. ----
  23. .Kotlin
  24. [source,kotlin,role="secondary"]
  25. ----
  26. @Bean
  27. open fun securityWebFilterChain(http: HttpSecurity): SecurityWebFilterChain {
  28. return http {
  29. // ...
  30. csrf {
  31. tokenFromMultipartDataEnabled = true
  32. }
  33. }
  34. }
  35. ----
  36. ====
  37. can be replaced with:
  38. .Configure `tokenFromMultipartDataEnabled` with `ServerCsrfTokenRequestAttributeHandler`
  39. ====
  40. .Java
  41. [source,java,role="primary"]
  42. ----
  43. @Bean
  44. SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
  45. ServerCsrfTokenRequestAttributeHandler requestHandler = new ServerCsrfTokenRequestAttributeHandler();
  46. requestHandler.setTokenFromMultipartDataEnabled(true);
  47. http
  48. // ...
  49. .csrf((csrf) -> csrf
  50. .csrfTokenRequestHandler(requestHandler)
  51. );
  52. return http.build();
  53. }
  54. ----
  55. .Kotlin
  56. [source,kotlin,role="secondary"]
  57. ----
  58. @Bean
  59. open fun securityWebFilterChain(http: HttpSecurity): SecurityWebFilterChain {
  60. val requestHandler = ServerCsrfTokenRequestAttributeHandler()
  61. requestHandler.tokenFromMultipartDataEnabled = true
  62. return http {
  63. // ...
  64. csrf {
  65. csrfTokenRequestHandler = requestHandler
  66. }
  67. }
  68. }
  69. ----
  70. ====
  71. == Use `AuthorizationManager` for Method Security
  72. xref:reactive/authorization/method.adoc[Method Security] has been xref:reactive/authorization/method.adoc#jc-enable-reactive-method-security-authorization-manager[improved] through {security-api-url}org/springframework/security/authorization/AuthorizationManager.html[the `AuthorizationManager` API] and direct use of Spring AOP.
  73. Should you run into trouble with making these changes, you can follow the
  74. <<reactive-authorizationmanager-methods-opt-out,opt out steps>> at the end of this section.
  75. In Spring Security 5.8, `useAuthorizationManager` was added to {security-api-url}org/springframework/security/config/annotation/method/configuration/EnableReactiveMethodSecurity.html[`@EnableReactiveMethodSecurity`] to allow applications to opt in to ``AuthorizationManager``'s features.
  76. [[reactive-change-to-useauthorizationmanager]]
  77. === Change `useAuthorizationManager` to `true`
  78. To opt in, change `useAuthorizationManager` to `true` like so:
  79. ====
  80. .Java
  81. [source,java,role="primary"]
  82. ----
  83. @EnableReactiveMethodSecurity
  84. ----
  85. .Kotlin
  86. [source,kotlin,role="secondary"]
  87. ----
  88. @EnableReactiveMethodSecurity
  89. ----
  90. ====
  91. changes to:
  92. ====
  93. .Java
  94. [source,java,role="primary"]
  95. ----
  96. @EnableReactiveMethodSecurity(useAuthorizationManager = true)
  97. ----
  98. .Kotlin
  99. [source,kotlin,role="secondary"]
  100. ----
  101. @EnableReactiveMethodSecurity(useAuthorizationManager = true)
  102. ----
  103. ====
  104. [[reactive-check-for-annotationconfigurationexceptions]]
  105. === Check for ``AnnotationConfigurationException``s
  106. `useAuthorizationManager` activates stricter enforcement of Spring Security's non-repeatable or otherwise incompatible annotations.
  107. If after turning on `useAuthorizationManager` you see ``AnnotationConfigurationException``s in your logs, follow the instructions in the exception message to clean up your application's method security annotation usage.
  108. [[reactive-authorizationmanager-methods-opt-out]]
  109. === Opt-out Steps
  110. If you ran into trouble with `AuthorizationManager` for reactive method security, you can opt out by changing:
  111. ====
  112. .Java
  113. [source,java,role="primary"]
  114. ----
  115. @EnableReactiveMethodSecurity
  116. ----
  117. .Kotlin
  118. [source,kotlin,role="secondary"]
  119. ----
  120. @EnableReactiveMethodSecurity
  121. ----
  122. ====
  123. to:
  124. ====
  125. .Java
  126. [source,java,role="primary"]
  127. ----
  128. @EnableReactiveMethodSecurity(useAuthorizationManager = false)
  129. ----
  130. .Kotlin
  131. [source,kotlin,role="secondary"]
  132. ----
  133. @EnableReactiveMethodSecurity(useAuthorizationManager = false)
  134. ----
  135. ====
  136. == Propagate ``AuthenticationServiceException``s
  137. {security-api-url}org/springframework/security/web/server/Webauthentication/AuthenticationWebFilter.html[`AuthenticationFilter`] propagates {security-api-url}org/springframework/security/authentication/AuthenticationServiceException.html[``AuthenticationServiceException``]s to the {security-api-url}org/springframework/security/web/server/ServerAuthenticationEntryPoint.html[`ServerAuthenticationEntryPoint`].
  138. Because ``AuthenticationServiceException``s represent a server-side error instead of a client-side error, in 6.0, this changes to propagate them to the container.
  139. === Configure `ServerAuthenticationFailureHandler` to rethrow ``AuthenticationServiceException``s
  140. To prepare for the 6.0 default, `httpBasic` and `oauth2ResourceServer` should be configured to rethrow ``AuthenticationServiceException``s.
  141. For each, construct the appropriate authentication entry point for `httpBasic` and for `oauth2ResourceServer`:
  142. ====
  143. .Java
  144. [source,java,role="primary"]
  145. ----
  146. ServerAuthenticationEntryPoint bearerEntryPoint = new BearerTokenServerAuthenticationEntryPoint();
  147. ServerAuthenticationEntryPoint basicEntryPoint = new HttpStatusServerEntryPoint(HttpStatus.UNAUTHORIZED);
  148. ----
  149. .Kotlin
  150. [source,kotlin,role="secondary"]
  151. ----
  152. val bearerEntryPoint: ServerAuthenticationEntryPoint = BearerTokenServerAuthenticationEntryPoint()
  153. val basicEntryPoint: ServerAuthenticationEntryPoint = HttpStatusServerEntryPoint(HttpStatus.UNAUTHORIZED)
  154. ----
  155. ====
  156. [NOTE]
  157. ====
  158. If you use a custom `AuthenticationEntryPoint` for either or both mechanisms, use that one instead for the remaining steps.
  159. ====
  160. Then, construct and configure a `ServerAuthenticationEntryPointFailureHandler` for each one:
  161. ====
  162. .Java
  163. [source,java,role="primary"]
  164. ----
  165. AuthenticationFailureHandler bearerFailureHandler = new ServerAuthenticationEntryPointFailureHandler(bearerEntryPoint);
  166. bearerFailureHandler.setRethrowAuthenticationServiceException(true);
  167. AuthenticationFailureHandler basicFailureHandler = new ServerAuthenticationEntryPointFailureHandler(basicEntryPoint);
  168. basicFailureHandler.setRethrowAuthenticationServiceException(true)
  169. ----
  170. .Kotlin
  171. [source,kotlin,role="secondary"]
  172. ----
  173. val bearerFailureHandler: AuthenticationFailureHandler = ServerAuthenticationEntryPointFailureHandler(bearerEntryPoint)
  174. bearerFailureHandler.setRethrowAuthenticationServiceException(true)
  175. val basicFailureHandler: AuthenticationFailureHandler = ServerAuthenticationEntryPointFailureHandler(basicEntryPoint)
  176. basicFailureHandler.setRethrowAuthenticationServiceException(true)
  177. ----
  178. ====
  179. Finally, wire each authentication failure handler into the DSL, like so:
  180. ====
  181. .Java
  182. [source,java,role="primary"]
  183. ----
  184. http
  185. .httpBasic((basic) -> basic.authenticationFailureHandler(basicFailureHandler))
  186. .oauth2ResourceServer((oauth2) -> oauth2.authenticationFailureHandler(bearerFailureHandler))
  187. ----
  188. .Kotlin
  189. [source,kotlin,role="secondary"]
  190. ----
  191. http {
  192. httpBasic {
  193. authenticationFailureHandler = basicFailureHandler
  194. }
  195. oauth2ResourceServer {
  196. authenticationFailureHandler = bearerFailureHandler
  197. }
  198. }
  199. ----
  200. ====
  201. [[reactive-authenticationfailurehandler-opt-out]]
  202. === Opt-out Steps
  203. To opt-out of the 6.0 defaults and instead continue to pass `AuthenticationServiceException` on to ``ServerAuthenticationEntryPoint``s, you can follow the same steps as above, except set `rethrowAuthenticationServiceException` to false.
  204. == Address OAuth2 Client Deprecations
  205. === `ServerOAuth2AuthorizedClientExchangeFilterFunction`
  206. The method `setAccessTokenExpiresSkew(...)` can be replaced with one of:
  207. * `ClientCredentialsReactiveOAuth2AuthorizedClientProvider#setClockSkew(...)`
  208. * `RefreshTokenReactiveOAuth2AuthorizedClientProvider#setClockSkew(...)`
  209. * `JwtBearerReactiveOAuth2AuthorizedClientProvider#setClockSkew(...)`
  210. The method `setClientCredentialsTokenResponseClient(...)` can be replaced with the constructor `ServerOAuth2AuthorizedClientExchangeFilterFunction(ReactiveOAuth2AuthorizedClientManager)`.
  211. [NOTE]
  212. ====
  213. See xref:reactive/oauth2/client/authorization-grants.adoc#oauth2Client-client-creds-grant[Client Credentials] for more information.
  214. ====
  215. === `WebSessionOAuth2ServerAuthorizationRequestRepository`
  216. The method `setAllowMultipleAuthorizationRequests(...)` has no direct replacement.
  217. === `UnAuthenticatedServerOAuth2AuthorizedClientRepository`
  218. The class `UnAuthenticatedServerOAuth2AuthorizedClientRepository` has no direct replacement. Usage of the class can be replaced with `AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager`.