CSRF token expires during login
Recommended solution
I would say that you should not disable csrf tokens on a production site. You may make session (and thus the csrf token) last longer (but it usually should not last longer than a day, especially for not-logged-in users as it is a DOS vector), but the real solution may be to automatically refresh the login page when the csrf token expires. You may use a
<META HTTP-EQUIV="REFRESH" CONTENT="csrf_timeout_in_seconds">
in your login page header. If the user lets the login page sit for hours, it should not bother him that the page got refreshed.
Second solution
A possible solution which does not require you to actually store sessions but allows for infinite timeout is that you can generate your csrf tokens with hashing from the session id and a server-side secret:
csrf = hash(sessionid+secret)
Note however that you need to really dig and override spring-security internal mechanisms, namely:
- re-creating anonymous sessions on the fly if a request arrives and no such session exists
- re-creating the csrf token on the fly from the session id
And choose a very secure hashing algorithm, preferably sha-512.
Third solution
You could have a small javascript that calls a no-op page on your server regularly (just before the session timeout), thus extending your session. This results in infinite session timeout only if the browser is on all the time, so the DOS aspect is mitigated.
Ok, one last solution
You can alter the CSRF token checking code, and disable it for the login page. This is actually synonymous with the second solution, but is specific for the login page, not generally for all anonymous sessions.
You can do this e.g. by setting a custom RequestMatcher in HttpSecurity:
http.csrf().requireCsrfProtectionMatcher(new MyCsrfRequestMatcher());
...
class MyCsrfRequestMatcher implements RequestMatcher {
@Override
public boolean matches(HttpServletRequest request) {
return !request.getServletPath().equals("/login");
}
}
Vartlok
Updated on June 17, 2022Comments
-
Vartlok about 2 years
I'm working on Spring web application and I need to avoid problem with expire csrf token on login page, because if user is waiting too long and try to login only one way to resolve problem with csrf is to reload page and try to login again. But it's not user friendly and I want to avoid this situation.
First question: Is it possible in general(by spring security 3.2.4)? Without disable csrf.
I tried to use security="none" for login page and spring seciruty "login_check", but it's not working, i got infinity redirect or I got error that no mapping for url "myhost/login_check".
Second question: How can i do it?
-
Vartlok over 9 yearsIt's same solution as reload page, will work but not user friendly.
-
P.Péter over 9 yearsBut the user does not have to manually reload the page. Most probably the user will not even notice that the page was reloaded, if he didn't touch the page for hours, so I consider this a non-issue.
-
P.Péter over 9 yearsAnd if your sessions last forever, than that will be a DOS attack vector (as you need memory/disk to store those sessions and csrf tokens). But you can do that, if a small chance of downtime is less inconvenient for your users than a reload in the background...
-
Vartlok over 9 yearsI guess infinite timeout(or very-very long) for session is the worst solution. But reload page is not perfect.
-
P.Péter over 9 yearsBut if you do not have infinite timeout, do not renew the session, and do not disable csrf, then how do you achieve to have a valid CSRF token after the session is timed out?
-
Vartlok over 9 yearsI don't want to have valid CSRF token after session timed out, i just want that user can stay on login page as long as it want, but after user login, CSRF should work as expected(timeout and other)
-
P.Péter over 9 yearsYou are currently contradicting yourself: if you do not want to have valid CSRF token after session timed out, then it is impossible for the login to work as it needs an anonymous session and a CSRF token!
-
P.Péter over 9 yearsLet us continue this discussion in chat.
-
Rolch2015 over 6 yearsOne should add that the spring documentation refers to csrf tokens stored in cookies as potentially insecure, and therefore stores the token by default in a session. See docs.spring.io/spring-security/site/docs/current/reference/html/….