Cross Site Request Forgery (CSRF) is typically prevent with one of the following methods:
- Check referer - RESTful but unreliable
- insert token into form and store the token in the server session - not really RESTful
- cryptic one time URIs - not RESTful for the same reason as tokens
- send password manually for this request (not the cached password used with HTTP auth) - RESTful but not convenient
My idea is to use a user secret, a cryptic but static form id and JavaScript to generate tokens.
<form method="POST" action="/someresource" id="7099879082361234103">
<input type="hidden" name="token" value="generateToken(...)">
...
</form>
GET /usersecret/john_doe
fetched by the JavaScript from the authenticated user.- Response:
OK 89070135420357234586534346
This secret is conceptionally static, but can be changed every day/hour ... to improve security. This is the only confidential thing. - Read the cryptic (but static for all users!) form id with JavaScript, process it together with the user secret:
generateToken(7099879082361234103, 89070135420357234586534346)
- Send the form along with the generated token to the server.
- Since the server knows the user secret and the form id, it is possible to run the same generateToken function as the client did before sending and compare both results. Only when both values are equal the action will be authorized.
Is something wrong with this approach, despite the fact that it doesn't work without JavaScript?
Addendum: