genedys/csrf-route-bundle
A Laravel/PHP package for adding CSRF protection to routes, helping secure state-changing requests with token validation and straightforward route integration. Lightweight and simple to configure for safer forms and endpoints.
Still calibrate expectations: genedys/csrf-route-bundle is a Symfony 3 bundle, not a Laravel package — and 3.0.0 does not change that. There is still no service provider, no facade, no config/csrf-route.php. What 3.0.0 does change is that the bundle has been modernized enough to be viable on Symfony 3.3/3.4 (the LTS) with PSR-4 autoloading and a fixed router performance problem. If you were previously told to avoid it because it was slow on large route sets, that specific objection is now resolved.
Minimal steps in a Symfony 3.3+ app:
composer require genedys/csrf-route-bundle:^3.0
// app/AppKernel.php
$bundles = [
// ...
new Genedys\CsrfRouteBundle\GenedysCsrfRouteBundle(),
];
Then look first at these places in vendor/genedys/csrf-route-bundle/src/ (note the PSR-4 src/ layout — 2.x used PSR-0, so paths moved):
DependencyInjection/ — which services are registered. CsrfTokenManager no longer exists; token generation/storage logic was redistributed into other classes. Find the replacement service before you write any custom code.Routing/ — CsrfRouter no longer extends Symfony's Router. It is now a composition/decorator around the router, which is what killed the getRouteCollection performance hit. Verify how it is wired and whether it replaces or wraps router.EventListener/ or EventSubscriber/) — the kernel event and priority where tokens are validated.@CsrfToken) — how a route opts in. (3.0.0 stripped many class/method descriptions, so expect less inline documentation than 2.x.)First use case: tag a single POST route as CSRF-protected, submit without a token, and confirm a 403 arrives before the controller runs. Then submit twice with the same token to confirm single-use/replay behavior. That tells you both the listener priority and the token lifecycle.
Laravel mental model is unchanged: roughly VerifyCsrfToken, but opt-in per route via annotation/route default instead of a global middleware group.
Route-scoped protection (the core idea). Unchanged from 2.x at the API surface — annotate individual routes:
/**
* @Route("/account/email", name="account_email", methods={"POST"})
* @CsrfToken
*/
public function updateEmailAction(Request $request) { /* ... */ }
Laravel equivalent is still opt-in middleware:
Route::post('/account/email', ...)->middleware('csrf');
Router decoration, not inheritance (new in 3.0). Because CsrfRouter no longer extends Symfony\Component\Routing\Router, anything that type-hinted Router and expected the CSRF router to satisfy it will fail. Inject the CSRF-aware router where you need token-aware URL/route resolution, and the base router elsewhere. In Laravel terms: this is the difference between subclassing Illuminate\Routing\Router and wrapping it in a decorator — cleaner, faster, but a BC break for type hints.
Token identity per form/route. The genuinely useful pattern to steal: namespace tokens by route name or a configurable token id so a token minted for /checkout cannot be replayed against /admin/delete. Laravel's default token is session-global; for per-form tokens, implement a TokenManager salting with the route name plus a TTL and validate in custom middleware.
Listener and token services as the extension points. Everything interesting still happens on a kernel event (kernel.request for validation, possibly kernel.response for injection). To change where the token is read — X-CSRF-Token header for AJAX, body field for forms — override the token-extraction service in services.yml. Do not reach for CsrfTokenManager any more; that service was removed in 3.0.0 and any service definition referencing it will break container compilation.
Performance-sensitive setups get a second look. If your app has hundreds of routes and you dismissed this bundle in 2.x due to getRouteCollection overhead on every request, 3.0.0 is the release that makes it tolerable. Still benchmark before adopting — the fix removes one known cost, it does not make the bundle free.
Hybrid-stack tip (unchanged). If a Laravel API gateway fronts a Symfony 3 legacy app, do not share this bundle's session tokens across the boundary. Keep CSRF enforcement in the app that owns the session; the gateway uses stateless auth.
laravel/framework constraint, no auto-discovery. composer require in Laravel succeeds and the code sits inert.CsrfTokenManager removed; logic moved to other classes. Any custom service definition, compiler pass, or direct $container->get('...csrf_token_manager') call breaks.CsrfRouter no longer extends Symfony's Router. Type hints against Router/RouterInterface that assumed this class breaks.src/ layout), so any hardcoded vendor/... requires, classmap hack, or custom autoloader breaks. Run composer dump-autoload after upgrading.CsrfTokenManager.getRouteCollection performance fix is the headline. On route-heavy apps, 2.x rebuilt/iterated the route collection wastefully per request. If you previously profiled this bundle and rejected it, re-benchmark 3.0.0 rather than reusing the old objection.Configuration.php and the DI extension rather than relying on docblocks or README — 2017-era bundle docs drifted from code, and this release made the source quieter still.CsrfTokenManager already handle tokens. Check whether routes are already protected before adopting — double validation produces confusing 403s.stateless: true firewalls and API endpoints will fail validation or silently mint new tokens. This is the most common source of "invalid CSRF token" in mixed apps._csrf default/annotation to verify opt-in; (4) check the token field name — a mismatch between Twig rendering and listener extraction looks exactly like a routing bug; (5) after upgrading, confirm the container compiled cleanly, since a stale CsrfTokenManager reference fails only at runtime on some setups.CsrfTokenManager), the token-extraction service, the annotation reader, and the (now non-inheriting) CsrfRouter. Override via service definition rather than forking.Cache/session-backed TokenManager: same opt-in semantics, current PHP support, something you can debug.How can I help you explore Laravel packages today?