I'm in need of a CSRF token, for a certain application that submits a form with
POST. Ideally, I'd like to not make a DB call for each submission, to avoid storage and DB traffic & latency. To this end OWASP's "CSRF Prevention Cheat Sheet" says,
The Encrypted Token Pattern leverages an encryption, rather than comparison, method of Token-validation. After successful authentication, the server generates a unique Token comprised of the user's ID, a timestamp value and a nonce, using a unique key available only on the server. This Token is returned to the client and embedded in a hidden field. […] Non-AJAX form-based requests will implicitly persist the Token in its hidden field. On receipt of this request, the server reads and decrypts the Token value with the same key used to create the Token. […]
On successful Token-decryption, the server has access to parsed values, ideally in the form of claims.
The first line of "Validation" reads, to me, like the very defintion of a JWT. I'm not seeing why the information in token needs to be encrypted, either: it would seem it merely needs to be authenticated that it came from the server (as opposed to an attacker attempting forging a CSRF token.)
Is there any particular reason to encrypt CSRF tokens? If not, does a JWT suffice?
Also, the above token pattern includes a nonce. What is the point of the nonce? (The whole point of this pattern is to not store any state server-side. If I'm not storing state, how can I use the nonce during validation in any material manner?)
My main reason for pursuing JWTs here is that there's decent library support, I'll probably want them for auth sooner or later, and it mostly keeps me away from implementing crypto stuff.
My understanding of JWTs is that if I had JWTs for full user authentication, I could store those in
localStorage, and simply add those to a field with JS prior to form submission. Unfortunately, the app uses cookie-based auth, and I'm not able to change that aspect right now.