CsrfMiddleware
The CsrfMiddleware class provides automatic CSRF (Cross-Site Request Forgery) protection for unsafe HTTP methods (POST, PUT, PATCH, DELETE). It validates CSRF tokens and optionally checks Origin/Referer headers.
Capabilities
Automatic CSRF validation on unsafe HTTP methods
Time-bucketed token validation with grace period
Origin/Referer header validation
Configurable session key and time buckets
Safe methods (GET, HEAD, OPTIONS) automatically pass validation
Constructor
public function __construct(
array $allowedOrigins = [],
string $csrfSessionKey = 'csrf_secret',
int $bucketSeconds = 3600,
bool $allowPreviousBucket = true
)Parameters
$allowedOrigins: Array of allowed origins (e.g.,['https://example.com']). If empty, origin validation is skipped.$csrfSessionKey: Session key where CSRF secret is stored (default:'csrf_secret')$bucketSeconds: Time bucket size in seconds for token rotation (default:3600= 1 hour)$allowPreviousBucket: Allow tokens from previous time bucket for grace period (default:true)
Public API
// Validate CSRF token and origin
handle(): boolReturns true if the request passes CSRF validation, false otherwise.
How It Works
Safe methods bypass validation: GET, HEAD, OPTIONS requests automatically pass
Origin validation (if configured): Checks
OriginorRefererheader against allowed originsToken validation: Validates CSRF token from
X-CSRF-TOKENheader or_tokenPOST parameterTime-bucketed tokens: Tokens are valid for current and previous time bucket (grace period)
Basic Example
use Stilmark\Base\CsrfMiddleware;
use Stilmark\Base\Render;
session_start();
// Create CSRF middleware with allowed origins
$csrfMiddleware = new CsrfMiddleware([
'https://example.com',
'https://www.example.com'
]);
// Validate CSRF on unsafe methods
if (!$csrfMiddleware->handle()) {
Render::json(['error' => 'CSRF validation failed'], 403);
exit;
}
// Continue with request handlingRouter Integration Example
use Stilmark\Base\Router;
use Stilmark\Base\CsrfMiddleware;
$router = new Router();
// Create CSRF middleware
$csrfMiddleware = new CsrfMiddleware([
'https://example.com'
]);
// Apply to specific routes
$router->post('/api/users', function($request) {
// Handle user creation
}, [$csrfMiddleware]);
$router->delete('/api/users/:id', function($request, $id) {
// Handle user deletion
}, [$csrfMiddleware]);Custom Configuration Example
use Stilmark\Base\CsrfMiddleware;
// Custom time bucket (30 minutes) without grace period
$csrfMiddleware = new CsrfMiddleware(
allowedOrigins: ['https://example.com'],
csrfSessionKey: 'my_csrf_secret',
bucketSeconds: 1800, // 30 minutes
allowPreviousBucket: false // No grace period
);
if (!$csrfMiddleware->handle()) {
http_response_code(403);
echo 'CSRF validation failed';
exit;
}Frontend Integration
Generating Tokens
use Stilmark\Base\Request;
session_start();
$request = new Request();
$csrfToken = $request->generateCsrfToken();
// Pass token to frontend
echo "<input type='hidden' name='_token' value='{$csrfToken}'>";Sending Tokens
HTML Form:
<form method="POST" action="/api/users">
<input type="hidden" name="_token" value="<?= $csrfToken ?>">
<input type="text" name="username">
<button type="submit">Create User</button>
</form>JavaScript (Fetch API):
fetch('/api/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': csrfToken
},
body: JSON.stringify({ username: 'john_doe' })
});Security Notes
Time-bucketed tokens: Tokens rotate automatically every hour (default), reducing exposure window
Grace period: Previous bucket tokens are accepted to prevent race conditions during rotation
Origin validation: Additional layer of protection against cross-origin attacks
Safe methods: GET requests don't require CSRF tokens (as per HTTP specification)
Session-based: CSRF secret is stored in session, not exposed to client
See Also
Request - For generating CSRF tokens
AuthMiddleware - For authentication
Session - For session management
Last updated