Why are csrf token's usually stored in hidden form fields?

Viewed 2451

I'm working on a React app and am thinking about implementing a CSRF mitigation technique. I decided to go with Same-Site cookies but before that, I was looking into using CSRF tokens and read numerous posts saying they should be stored in a hidden form field. What I'd like to know is if there is a difference between storing it in a hidden field and storing it in something like a class variable? If the point of it is to keep somewhere for when you a ready to send a request to the server, does it matter how it's stored on the client-side?

3 Answers

If you put it in a form field then everything typically just works, but if you put the value anywhere else then you have to write logic to extract that value and insert it back into the form data that is being sent to the server.

Using the form field also works for both ajax and standard form submission, so most tutorials are going to promote it over methods that only work for one or the other.

The reason a CSRF token is stored in a hidden input is so that it gets sent to the server automatically when the form is submitted. If you are manually sending a request to the server and grabbing the data yourself, you could store the CSRF anywhere. It would be best to be consistent and just store it in a hidden input.

The other answers are correct in that for a tutorial that you find somewhere (or a generic one on csrf) it's easier to demonstrate it with the token being written in form fields, also a traditional web application will just work that way.

What others did not mention is modern single-page applications like one with React do not work like that, often you don't even have forms, and writing the token to form fields makes no sense. So these applications typically do not do that.

There is also a practical aspect to this. You mentioned storing it in a class variable. That's fine, but how will it get there? The token is usually (not necessarily, but that's a sidetrack for now) generated by the server-side web app. How will the javascript SPA get it? You need to write it somewhere in the page, spending a separate request to get it would be a waste of resources. One thing that usually happens is writing it in a meta header (eg. <meta name="csrf" content="...">) at the top of the page so your SPA can read it from there and store it wherever it wants.

Another thing that often happens is csrf protection is not even needed, because api authentication is based on something like request headers (instead of something in a cookie), which would not be sent automatically by the browser, so classic csrf is not feasible.

Related