I am looking into protecting a website from CSRF attacks. Although sensitive cookies already are tagged with same-site=lax
, I would still like to implement CSRF tokens. More specifically the double submission pattern. I read that these tokens could also be generated client-side. Is this correct? I was thinking of taking the following approach:
- User is on the website and sends out a request
- The client generates a random token which is added to the cookies which will be send to the server
- The client adds this token to a request header called "x-csrf-token".
- The server compares the token in the cookie with the token in the request header.
Should these tokens be generated for each request? Or can I just generate one token and refresh that token every time the user visits again?
Would this be a good protective measure against CSRF attacks? Is the assumption correct that the attacker can not set cookies for my specific domain and can thus not generate the token themselves?
2
Answers
This is all about correct, yes.
If you generate a new token for each request, you will run into a race condition as setting a cookie takes some time for the browser, and one cookie can have one value at any given time. Too fast requests will send the wrong cookie value.
It is usually enough to generate one token per user session (login).
Also SameSite nowadays is increasingly accepted as the only protection against CSRF. It may or may not be enough in your usecase, depending mostly on what potential clients (which browsers) you may want to serve, ie. what will your legitimate users use, as it’s their session that attackers want to exploit in case of CSRF. If you want additional protection, double submit is a reasonable solution.
It’s safer to do this server-side, especially if you want to protect against subdomain hijacking.
You can then cryptographically sign the double-submit token to bind it to the session cookie.
I recommend reading API Security in Action, section 4.4.2.
The relevant code can be found here: