I have 2 forms on the same page. I want to use the csrf token in both forms. when I try to use it, it regenerates the csrf token on form submission.
How can I solve this?
<?php function csrf_token() { return bin2hex(random_bytes(35)); } function create_csrf_token() { $token = csrf_token(); $_SESSION['csrf_token'] = $token; $_SESSION['csrf_token_time'] = time(); return $token; } function csrf_token_tag() { $token = create_csrf_token(); return '<input type="hidden" name="csrf_token" value="' . $token . '">'; } $csrf_token = csrf_token_tag(); ?> <form action="" method="post"> ... <?= $csrf_token; ?> </form> <form action="" method="post"> ... <?= $csrf_token; ?> </form>
Advertisement
Answer
When you refresh the page, the function created_csrf_token
gets fired again, changing the CSRF token.
As Lawrence has commented, you can scope it. E.g.
<?php function csrf_token() { return bin2hex(random_bytes(35)); } function create_csrf_token() { if (isset($_SESSION['csrf_token'])) { return $_SESSION['csrf_token']; } $token = csrf_token(); $_SESSION['csrf_token'] = $token; $_SESSION['csrf_token_time'] = time(); return $token; } function csrf_token_tag() { $token = create_csrf_token(); return '<input type="hidden" name="csrf_token" value="' . $token . '">'; } $csrf_token = csrf_token_tag(); ?> <form action="" method="post"> ... <?= $csrf_token; ?> </form> <form action="" method="post"> ... <?= $csrf_token; ?> </form>
Adding an isset into the create_csrf_token
will check if the CSRF token is set, and return the existing, rather than create a new one.
You probably want to add some logic though, to create a new CSRF token after around 5 minutes.