I built CSRF protection in my application, by simply generating a random token on every page load, putting it into session, and then binding the token to the <body>
tag attribute like:
<body data-csrf-token="csrf_GeJf53caJD6Q5WzwAzfy">
Then on every form action or ajax request, I simply grab the token from the body tag and send it along.
This works great, except for a huge issue. Users are opening multiple tabs of the application, and I am seeing token collisions. For example, a user loads the first page and it generates a token, then they switch tabs, load another page, which generates a new token. Finally they switch back to the first page and submit a format action. This results in an invalid CSRF token error.
What is the best way to re-architect this to prevent collisions with multiple tabs, while keeping it as secure as possible.
Is simply generating a single token upon login the correct solution, instead of generating a new token on every page load?
login
page, or in thelogin
form action page? Right now I pass a CSRF token even on the login page to the login action. – Ebneter