I'm using Codeigniter and I want to prevent CSRF attacks attempts that may happen. And to achieve this I add a hidden input tag with a random token to each form I want to protect, and in the same time I keep this token in a session to compare against when begin handling this form data.
// set a token to prevent CSRF attacks
$csrf_token = md5(uniqid(rand(), true));
$this->session->set_userdata("csrf_token", $csrf_token);
And the form will look like this:
<form action="path/to/handler/page" method="post">
<input type="text" name="title">
<input type="text" name="date">
<textarea name="content"></textarea>
<input type="hidden" name="csrf_token" value="<?php echo $this->session->userdata("csrf_token") ?>">
<input type="submit" name="submit" value="Save">
</form>
And in the page where I handle submitted data I check CSRF attacks something like this:
// make sure there is no CSRF attack attempt
$csrf_token = $this->session->userdata("csrf_token");
if (empty($csrf_token) || $csrf_token !== $this->input->post("csrf_token")) {
die("Some message here!!");
}
And that works pretty good. But as you see I generate a random token for each page containing a form and in some cases this causes a problem if for example I opened another tab in the browser to perform some another action. Consider this scenario:
- I opened
add.php
page to add a new item. - I filled in all required data, but I didn't submit the form.
- Now I decided to open
edit.php
page in another tab in the browser to edit an existing item. - Then I went back to the
add.php
page that was filled in and tried to submit the data.
At this point I will get an error because value of the token that has been stored in the session when I opened add.php
page has been changed and replaced with another token when I open the edit.php
page. So how can I fix this problem? Should I generate just one token for each user when he successfully login and then use this token in all pages that he may deal with? Does this approach has any risks or any cons?