authentication.adoc 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. = Authentication Migrations
  2. The following steps relate to changes around how authentication is performed.
  3. [[servlet-opt-in-sha256-rememberme]]
  4. == Use SHA-256 in Remember Me
  5. The `TokenBasedRememberMeServices` implementation now supports SHA-256 for the Remember Me token and this is the default in Spring Security 6.
  6. This change makes the implementation more secure by default since MD5 is already proven to be a weak hashing algorithm and vulnerable against collision attacks and modular differential attacks.
  7. The new generated tokens now have the information of which algorithm was used to generate the token and that information is used in order to match it.
  8. If the algorithm name is not present, then the `matchingAlgorithm` property is used to check the token.
  9. This allows for a smooth transition from MD5 to SHA-256.
  10. To opt into the new Spring Security 6 default to encode the tokens while still being able to decode tokens encoded with MD5, you can set the `encodingAlgorithm` property to SHA-256 and the `matchingAlgorithm` property to MD5.
  11. See the xref:servlet/authentication/rememberme.adoc#_tokenbasedremembermeservices[reference documentation] and the {security-api-url}org/springframework/security/web/authentication/rememberme/TokenBasedRememberMeServices.html[API docs] for more information.
  12. [[servlet-opt-in-sha256-sha256-encoding]]
  13. .Use Spring Security 6 defaults for encoding, SHA-256 for encoding and MD5 for matching
  14. ====
  15. .Java
  16. [source,java,role="primary"]
  17. ----
  18. @Configuration
  19. @EnableWebSecurity
  20. public class SecurityConfig {
  21. @Bean
  22. SecurityFilterChain securityFilterChain(HttpSecurity http, RememberMeServices rememberMeServices) throws Exception {
  23. http
  24. // ...
  25. .rememberMe((remember) -> remember
  26. .rememberMeServices(rememberMeServices)
  27. );
  28. return http.build();
  29. }
  30. @Bean
  31. RememberMeServices rememberMeServices(UserDetailsService userDetailsService) {
  32. RememberMeTokenAlgorithm encodingAlgorithm = RememberMeTokenAlgorithm.SHA256;
  33. TokenBasedRememberMeServices rememberMe = new TokenBasedRememberMeServices(myKey, userDetailsService, encodingAlgorithm);
  34. rememberMe.setMatchingAlgorithm(RememberMeTokenAlgorithm.MD5);
  35. return rememberMe;
  36. }
  37. }
  38. ----
  39. .XML
  40. [source,xml,role="secondary"]
  41. ----
  42. <http>
  43. <remember-me services-ref="rememberMeServices"/>
  44. </http>
  45. <bean id="rememberMeServices" class=
  46. "org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
  47. <property name="userDetailsService" ref="myUserDetailsService"/>
  48. <property name="key" value="springRocks"/>
  49. <property name="matchingAlgorithm" value="MD5"/>
  50. <property name="encodingAlgorithm" value="SHA256"/>
  51. </bean>
  52. ----
  53. ====
  54. At some point, you will want to fully migrate to Spring Security 6 defaults. But how do you know when it is safe to do so?
  55. Let's suppose that you deployed your application using SHA-256 as the encoding algorithm (as you have done <<servlet-opt-in-sha256-sha256-encoding,here>>) on November 1st, if you have the value for the `tokenValiditySeconds` property set to N days (14 is the default), you can migrate to SHA-256 N days after November 1st (which is November 15th in this example).
  56. By that time, all the tokens generated with MD5 will have expired.
  57. .Use Spring Security 6 defaults, SHA-256 for both encoding and matching
  58. ====
  59. .Java
  60. [source,java,role="primary"]
  61. ----
  62. @Configuration
  63. @EnableWebSecurity
  64. public class SecurityConfig {
  65. @Bean
  66. SecurityFilterChain securityFilterChain(HttpSecurity http, RememberMeServices rememberMeServices) throws Exception {
  67. http
  68. // ...
  69. .rememberMe((remember) -> remember
  70. .rememberMeServices(rememberMeServices)
  71. );
  72. return http.build();
  73. }
  74. @Bean
  75. RememberMeServices rememberMeServices(UserDetailsService userDetailsService) {
  76. RememberMeTokenAlgorithm encodingAlgorithm = RememberMeTokenAlgorithm.SHA256;
  77. TokenBasedRememberMeServices rememberMe = new TokenBasedRememberMeServices(myKey, userDetailsService, encodingAlgorithm);
  78. rememberMe.setMatchingAlgorithm(RememberMeTokenAlgorithm.SHA256);
  79. return rememberMe;
  80. }
  81. }
  82. ----
  83. .XML
  84. [source,xml,role="secondary"]
  85. ----
  86. <http>
  87. <remember-me services-ref="rememberMeServices"/>
  88. </http>
  89. <bean id="rememberMeServices" class=
  90. "org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
  91. <property name="userDetailsService" ref="myUserDetailsService"/>
  92. <property name="key" value="springRocks"/>
  93. <property name="matchingAlgorithm" value="SHA256"/>
  94. <property name="encodingAlgorithm" value="SHA256"/>
  95. </bean>
  96. ----
  97. ====
  98. If you are having problems with the Spring Security 6 defaults, you can explicitly opt into 5.8 defaults using the following configuration:
  99. .Use MD5 for both encoding and matching algorithms
  100. ====
  101. .Java
  102. [source,java,role="primary"]
  103. ----
  104. @Configuration
  105. @EnableWebSecurity
  106. public class SecurityConfig {
  107. @Bean
  108. SecurityFilterChain securityFilterChain(HttpSecurity http, RememberMeServices rememberMeServices) throws Exception {
  109. http
  110. // ...
  111. .rememberMe((remember) -> remember
  112. .rememberMeServices(rememberMeServices)
  113. );
  114. return http.build();
  115. }
  116. @Bean
  117. RememberMeServices rememberMeServices(UserDetailsService userDetailsService) {
  118. RememberMeTokenAlgorithm encodingAlgorithm = RememberMeTokenAlgorithm.MD5;
  119. TokenBasedRememberMeServices rememberMe = new TokenBasedRememberMeServices(myKey, userDetailsService, encodingAlgorithm);
  120. rememberMe.setMatchingAlgorithm(RememberMeTokenAlgorithm.MD5);
  121. return rememberMe;
  122. }
  123. }
  124. ----
  125. .XML
  126. [source,xml,role="secondary"]
  127. ----
  128. <http>
  129. <remember-me services-ref="rememberMeServices"/>
  130. </http>
  131. <bean id="rememberMeServices" class=
  132. "org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
  133. <property name="userDetailsService" ref="myUserDetailsService"/>
  134. <property name="key" value="springRocks"/>
  135. <property name="matchingAlgorithm" value="MD5"/>
  136. <property name="encodingAlgorithm" value="MD5"/>
  137. </bean>
  138. ----
  139. ====
  140. == Propagate ``AuthenticationServiceException``s
  141. {security-api-url}org/springframework/security/web/authentication/AuthenticationFilter.html[`AuthenticationFilter`] propagates {security-api-url}org/springframework/security/authentication/AuthenticationServiceException.html[``AuthenticationServiceException``]s to the {security-api-url}org/springframework/security/authentication/AuthenticationEntryPoint.html[`AuthenticationEntryPoint`].
  142. 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.
  143. === Configure `AuthenticationFailureHandler` to rethrow ``AuthenticationServiceException``s
  144. To prepare for the 6.0 default, wire `AuthenticationFilter` instances with a `AuthenticationFailureHandler` that rethrows ``AuthenticationServiceException``s, like so:
  145. ====
  146. .Java
  147. [source,java,role="primary"]
  148. ----
  149. AuthenticationFilter authenticationFilter = new AuthenticationFilter(...);
  150. AuthenticationEntryPointFailureHandler handler = new AuthenticationEntryPointFailureHandler(...);
  151. handler.setRethrowAuthenticationServiceException(true);
  152. authenticationFilter.setAuthenticationFailureHandler(handler);
  153. ----
  154. .Kotlin
  155. [source,kotlin,role="secondary"]
  156. ----
  157. val authenticationFilter: AuthenticationFilter = new AuthenticationFilter(...)
  158. val handler: AuthenticationEntryPointFailureHandler = new AuthenticationEntryPointFailureHandler(...)
  159. handler.setRethrowAuthenticationServiceException(true)
  160. authenticationFilter.setAuthenticationFailureHandler(handler)
  161. ----
  162. .Xml
  163. [source,xml,role="secondary"]
  164. ----
  165. <bean id="authenticationFilter" class="org.springframework.security.web.authentication.AuthenticationFilter">
  166. <!-- ... -->
  167. <property ref="authenticationFailureHandler"/>
  168. </bean>
  169. <bean id="authenticationFailureHandler" class="org.springframework.security.web.authentication.AuthenticationEntryPointFailureHandler">
  170. <property name="rethrowAuthenticationServiceException" value="true"/>
  171. </bean>
  172. ----
  173. ====
  174. [[servlet-authenticationfailurehandler-opt-out]]
  175. === Opt-out Steps
  176. If rethrowing ``AuthenticationServiceException``s gives you trouble, you can set the value to false instead of taking the 6.0 default, like so:
  177. ====
  178. .Java
  179. [source,java,role="primary"]
  180. ----
  181. AuthenticationFilter authenticationFilter = new AuthenticationFilter(...);
  182. AuthenticationEntryPointFailureHandler handler = new AuthenticationEntryPointFailureHandler(...);
  183. handler.setRethrowAuthenticationServiceException(false);
  184. authenticationFilter.setAuthenticationFailureHandler(handler);
  185. ----
  186. .Kotlin
  187. [source,kotlin,role="secondary"]
  188. ----
  189. val authenticationFilter: AuthenticationFilter = new AuthenticationFilter(...)
  190. val handler: AuthenticationEntryPointFailureHandler = new AuthenticationEntryPointFailureHandler(...)
  191. handler.setRethrowAuthenticationServiceException(false)
  192. authenticationFilter.setAuthenticationFailureHandler(handler)
  193. ----
  194. .Xml
  195. [source,xml,role="secondary"]
  196. ----
  197. <bean id="authenticationFilter" class="org.springframework.security.web.authentication.AuthenticationFilter">
  198. <!-- ... -->
  199. <property ref="authenticationFailureHandler"/>
  200. </bean>
  201. <bean id="authenticationFailureHandler" class="org.springframework.security.web.authentication.AuthenticationEntryPointFailureHandler">
  202. <property name="rethrowAuthenticationServiceException" value="false"/>
  203. </bean>
  204. ----
  205. ====