What's the advantage of still having the cookie with some value in it when we use a random token as a hidden form value plus this token being stored on the server? Your suggestion seems overly complex to me, so maybe I'm missing an attack vector that can be mitigated by throwing salts, hashing and a cookie at the issue.
There are a TON of different CSRF schemes and once you have billions of requests per day, storing and distributing each CSRF token for each user can be a large burden.
Most advanced CSRF schemes use some crypto primitives in a manner like client-side sessions work (Enc+Mac on the server, give token to user, Validate Integrity+Dec on the server when you get it back), or HMAC some user meta-data. This allows you to distribute the key and then any server with the key can validate the token without needing to know the token in advance.
I've written a blog post about a bunch of types of CSRF schemes and their pros and cons, but never published it. Is this interesting enough for me to publish?
> I've written a blog post about a bunch of types of CSRF schemes and their pros and cons, but never published it. Is this interesting enough for me to publish?
Definitely. Having looked myself, I can tell you there aren't many resources online that get this right.
How we do it is a little wonky. Our web app calls GET /login which returns a CSRF cookie and an anonymous session cookie and an object that says there's no active session. The app then uses that CSRF token to POST to /login. Once the auth is successful, the anonymous session is destroyed and a new CSRF secret is generated on the authenticated session.
We serve static HTML and site is driven entirely by JavaScript with all communication with the server being solely through a REST API. There's no mechanism to add a value to a form field, thus we use a cookie.
Really the difference is that you compare the user's response to a known value on the server rather than two values in the same request body which cannot be independently verified.
How do you bind the value stored on the server to the logged-in user? If it's a global value (same for all users), you aren't correctly protecting against CSRF. If it's tied to the logged-in user, storing a value is essentially the same as deriving a value using HMAC (or some other one way function).
The CSRF token is generated on login and then stored in the user's session. We accept the risk of not having a per-form token for pure developer/user convenience reasons.
Keep in mind that if you don't change the client's view of the token on every page load (using some kind of salt), you are potentially vulnerable to CRIME/BEAST.