Skip to content

Commit 7cbb9e8

Browse files
Document how to opt-in for SHA256 in RememberMe
Closes gh-12097
1 parent 6a4b279 commit 7cbb9e8

File tree

1 file changed

+161
-0
lines changed

1 file changed

+161
-0
lines changed

docs/modules/ROOT/pages/migration.adoc

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1703,6 +1703,167 @@ authenticationFilter.setAuthenticationFailureHandler(handler)
17031703
----
17041704
====
17051705

1706+
[[servlet-opt-in-sha256-rememberme]]
1707+
=== Use SHA-256 in Remember Me
1708+
1709+
The `TokenBasedRememberMeServices` implementation now supports SHA-256 for the Remember Me token and this is the default in Spring Security 6.
1710+
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.
1711+
1712+
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.
1713+
If the algorithm name is not present, then the `matchingAlgorithm` property is used to check the token.
1714+
This allows for a smooth transition from MD5 to SHA-256.
1715+
1716+
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.
1717+
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.
1718+
1719+
[[servlet-opt-in-sha256-sha256-encoding]]
1720+
.Use Spring Security 6 defaults for encoding, SHA-256 for encoding and MD5 for matching
1721+
====
1722+
.Java
1723+
[source,java,role="primary"]
1724+
----
1725+
@Configuration
1726+
@EnableWebSecurity
1727+
public class SecurityConfig {
1728+
1729+
@Bean
1730+
SecurityFilterChain securityFilterChain(HttpSecurity http, RememberMeServices rememberMeServices) throws Exception {
1731+
http
1732+
// ...
1733+
.rememberMe((remember) -> remember
1734+
.rememberMeServices(rememberMeServices)
1735+
);
1736+
return http.build();
1737+
}
1738+
1739+
@Bean
1740+
RememberMeServices rememberMeServices(UserDetailsService userDetailsService) {
1741+
RememberMeTokenAlgorithm encodingAlgorithm = RememberMeTokenAlgorithm.SHA256;
1742+
TokenBasedRememberMeServices rememberMe = new TokenBasedRememberMeServices(myKey, userDetailsService, encodingAlgorithm);
1743+
rememberMe.setMatchingAlgorithm(RememberMeTokenAlgorithm.MD5);
1744+
return rememberMe;
1745+
}
1746+
1747+
}
1748+
----
1749+
1750+
.XML
1751+
[source,xml,role="secondary"]
1752+
----
1753+
<http>
1754+
<remember-me services-ref="rememberMeServices"/>
1755+
</http>
1756+
1757+
<bean id="rememberMeServices" class=
1758+
"org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
1759+
<property name="userDetailsService" ref="myUserDetailsService"/>
1760+
<property name="key" value="springRocks"/>
1761+
<property name="matchingAlgorithm" value="MD5"/>
1762+
<property name="encodingAlgorithm" value="SHA256"/>
1763+
</bean>
1764+
----
1765+
====
1766+
1767+
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?
1768+
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).
1769+
By that time, all the tokens generated with MD5 will have expired.
1770+
1771+
.Use Spring Security 6 defaults, SHA-256 for both encoding and matching
1772+
====
1773+
.Java
1774+
[source,java,role="primary"]
1775+
----
1776+
@Configuration
1777+
@EnableWebSecurity
1778+
public class SecurityConfig {
1779+
1780+
@Bean
1781+
SecurityFilterChain securityFilterChain(HttpSecurity http, RememberMeServices rememberMeServices) throws Exception {
1782+
http
1783+
// ...
1784+
.rememberMe((remember) -> remember
1785+
.rememberMeServices(rememberMeServices)
1786+
);
1787+
return http.build();
1788+
}
1789+
1790+
@Bean
1791+
RememberMeServices rememberMeServices(UserDetailsService userDetailsService) {
1792+
RememberMeTokenAlgorithm encodingAlgorithm = RememberMeTokenAlgorithm.SHA256;
1793+
TokenBasedRememberMeServices rememberMe = new TokenBasedRememberMeServices(myKey, userDetailsService, encodingAlgorithm);
1794+
rememberMe.setMatchingAlgorithm(RememberMeTokenAlgorithm.SHA256);
1795+
return rememberMe;
1796+
}
1797+
1798+
}
1799+
----
1800+
1801+
.XML
1802+
[source,xml,role="secondary"]
1803+
----
1804+
<http>
1805+
<remember-me services-ref="rememberMeServices"/>
1806+
</http>
1807+
1808+
<bean id="rememberMeServices" class=
1809+
"org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
1810+
<property name="userDetailsService" ref="myUserDetailsService"/>
1811+
<property name="key" value="springRocks"/>
1812+
<property name="matchingAlgorithm" value="SHA256"/>
1813+
<property name="encodingAlgorithm" value="SHA256"/>
1814+
</bean>
1815+
----
1816+
====
1817+
1818+
If you are having problems with the Spring Security 6 defaults, you can explicitly opt into 5.8 defaults using the following configuration:
1819+
1820+
.Use MD5 for both encoding and matching algorithms
1821+
====
1822+
.Java
1823+
[source,java,role="primary"]
1824+
----
1825+
@Configuration
1826+
@EnableWebSecurity
1827+
public class SecurityConfig {
1828+
1829+
@Bean
1830+
SecurityFilterChain securityFilterChain(HttpSecurity http, RememberMeServices rememberMeServices) throws Exception {
1831+
http
1832+
// ...
1833+
.rememberMe((remember) -> remember
1834+
.rememberMeServices(rememberMeServices)
1835+
);
1836+
return http.build();
1837+
}
1838+
1839+
@Bean
1840+
RememberMeServices rememberMeServices(UserDetailsService userDetailsService) {
1841+
RememberMeTokenAlgorithm encodingAlgorithm = RememberMeTokenAlgorithm.MD5;
1842+
TokenBasedRememberMeServices rememberMe = new TokenBasedRememberMeServices(myKey, userDetailsService, encodingAlgorithm);
1843+
rememberMe.setMatchingAlgorithm(RememberMeTokenAlgorithm.MD5);
1844+
return rememberMe;
1845+
}
1846+
1847+
}
1848+
----
1849+
1850+
.XML
1851+
[source,xml,role="secondary"]
1852+
----
1853+
<http>
1854+
<remember-me services-ref="rememberMeServices"/>
1855+
</http>
1856+
1857+
<bean id="rememberMeServices" class=
1858+
"org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
1859+
<property name="userDetailsService" ref="myUserDetailsService"/>
1860+
<property name="key" value="springRocks"/>
1861+
<property name="matchingAlgorithm" value="MD5"/>
1862+
<property name="encodingAlgorithm" value="MD5"/>
1863+
</bean>
1864+
----
1865+
====
1866+
17061867
== Reactive
17071868

17081869
=== Use `AuthorizationManager` for Method Security

0 commit comments

Comments
 (0)