CSRF token expires during login

15,030

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");
    }
}
Share:
15,030
Vartlok
Author by

Vartlok

Updated on June 17, 2022

Comments

  • Vartlok
    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
    Vartlok over 9 years
    It's same solution as reload page, will work but not user friendly.
  • P.Péter
    P.Péter over 9 years
    But 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
    P.Péter over 9 years
    And 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
    Vartlok over 9 years
    I guess infinite timeout(or very-very long) for session is the worst solution. But reload page is not perfect.
  • P.Péter
    P.Péter over 9 years
    But 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
    Vartlok over 9 years
    I 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
    P.Péter over 9 years
    You 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
    P.Péter over 9 years
  • Rolch2015
    Rolch2015 over 6 years
    One 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/h‌​tml/….