However, how is this safe? A malicious website can do the exact same thing, hit my log in, receive the token, add to token to header, and then do anything.
The malicious website could grab a csrf token, but as your server will have a different csrf token for each user session, it will be of no use to the malicious website.
To better understand csrf attacks, consider the following workflow:
- a user login successfully on your website, creating a session server-side, and getting a session cookie client side that identifies the server-side session
this user now visits another site (malicious) that has an onload event that trigger submitting a form on your website, that is accessible only to logged in user. The form would look like this :
<form method="POST" action="https://your.web.site/secured/transferFund">
<input type="hidden" name="amount" value="1000"/>
<input type="hidden" name="to" value="malicous_guy_account"/>
</form>
on submitting this form in an event, it :
- will be totally invisible to the end user
- work because the client is logged in on your website, and the session cookie will be used for this http request automatically
So how the CSRF token helps ?
It is not stored in a cookie, but either directly in a hidden form field, or in a header, both location cannot be scanned by the malicious website.
So now, when the malicious website tries to submit the previous form, the csrf token is missing or invalid, and will be rejected server-side as not authorized.
For that to work, you need :
- different token for each user session,
- to tie the token to the session lifecycle,
- to keep it away from cookies,
- that everything that changes state server side, is behind a POST action
- that every POST action has its CSRF token validated