Skip to content

CSRF Protection

Cross-Site Request Forgery (CSRF) protection prevents attackers from executing unauthorized actions on behalf of authenticated users.

Protection Strategy

  1. Generate a unique token per session
  2. Include token in forms as hidden field
  3. Validate token on form submission
  4. Reject requests with missing or invalid tokens

Implementation

Token Generation

final class CsrfService
{
    public function generateToken(): string
    {
        $token = bin2hex(random_bytes(32));
        $this->session->set('csrf_token', $token);
        return $token;
    }

    public function validateToken(string $token): bool
    {
        $storedToken = $this->session->get('csrf_token');
        return $storedToken !== null && hash_equals($storedToken, $token);
    }
}

Form Integration

<form method="post" action="/books/create">
    <input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
    <input type="text" name="title">
    <button type="submit">Create</button>
</form>

Middleware Validation

if ($this->isWriteRequest($request)) {
    $token = $this->extractToken($request);
    if (!$this->csrfService->validateToken($token)) {
        return $this->responseFactory->createResponse(403);
    }
}
return $handler->handle($request);

Modern browsers provide additional CSRF protection via the SameSite attribute:

  • Strict: Cookie only sent for same-site requests
  • Lax: Cookie sent for same-site requests and top-level navigation

Best Practices

  • Always use CSRF tokens for state-changing operations
  • Use hash_equals() for constant-time comparison
  • Regenerate tokens after successful submission
  • Don't expose tokens in URLs

See Also