How to Use CSRF Token in PHP for Secure Forms
To use a
CSRF token in PHP, generate a unique token and store it in the user's session. Include this token as a hidden field in your HTML form, then verify it on form submission by comparing it with the session token to ensure the request is valid and secure.Syntax
Using a CSRF token in PHP involves three main steps:
- Generate Token: Create a unique token and save it in
$_SESSION. - Include Token: Add the token as a hidden input in your HTML form.
- Verify Token: On form submission, check if the submitted token matches the session token.
php
<?php // Start session session_start(); // Generate token if not set if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } // Include token in form $token = $_SESSION['csrf_token']; // On form submission, verify token if ($_SERVER['REQUEST_METHOD'] === 'POST') { if (!empty($_POST['csrf_token']) && hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) { // Token is valid } else { // Token is invalid } } ?>
Example
This example shows a simple form protected by a CSRF token. It generates the token, includes it in the form, and verifies it when the form is submitted.
php
<?php session_start(); // Generate CSRF token if not set if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } $message = ''; if ($_SERVER['REQUEST_METHOD'] === 'POST') { if (!empty($_POST['csrf_token']) && hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) { $message = 'Form submitted successfully with valid CSRF token.'; } else { $message = 'Error: Invalid CSRF token.'; } } $token = $_SESSION['csrf_token']; ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>CSRF Token Example</title> </head> <body> <h2>CSRF Token Protected Form</h2> <?php if ($message): ?> <p><strong><?php echo htmlspecialchars($message); ?></strong></p> <?php endif; ?> <form method="POST" action=""> <input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars($token); ?>"> <label for="name">Name:</label> <input type="text" id="name" name="name" required> <button type="submit">Submit</button> </form> </body> </html>
Output
Form submitted successfully with valid CSRF token.
Common Pitfalls
Common mistakes when using CSRF tokens include:
- Not starting the session with
session_start(), so tokens cannot be stored or accessed. - Forgetting to include the token as a hidden field in the form.
- Not verifying the token on form submission or using insecure comparison methods.
- Reusing the same token indefinitely without regeneration, which can reduce security.
php
<?php // Wrong: No session started, token not stored // $_SESSION['csrf_token'] is undefined // Wrong: Token not included in form // <form method="POST" action=""> // <!-- Missing hidden csrf_token input --> // </form> // Wrong: Insecure token check // if ($_POST['csrf_token'] === $_SESSION['csrf_token']) { ... } // Use hash_equals() instead // Right: Start session, generate token, include in form, verify with hash_equals() session_start(); if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } if ($_SERVER['REQUEST_METHOD'] === 'POST') { if (!empty($_POST['csrf_token']) && hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) { // Valid } else { // Invalid } } ?>
Quick Reference
CSRF Token Usage Summary:
- Start session with
session_start(). - Generate token with
bin2hex(random_bytes(32))and store in$_SESSION. - Include token in form as hidden input.
- On POST, verify token with
hash_equals(). - Reject requests with missing or invalid tokens.
Key Takeaways
Always generate a unique CSRF token and store it in the session before rendering the form.
Include the CSRF token as a hidden input field inside your HTML form.
Verify the submitted token against the session token using hash_equals() to prevent timing attacks.
Start the PHP session with session_start() before working with tokens.
Reject any form submissions with missing or invalid CSRF tokens to protect against forgery.