Skip to content

Commit a50085b

Browse files
feature #54443 [Security] Add support for dynamic CSRF id with Expression in #[IsCsrfTokenValid] (yguedidi)
This PR was merged into the 7.1 branch. Discussion ---------- [Security] Add support for dynamic CSRF id with Expression in `#[IsCsrfTokenValid]` | Q | A | ------------- | --- | Branch? | 7.1 | Bug fix? | no | New feature? | yes | Deprecations? | no | Issues | continuation of #52961 from Hackday | License | MIT Use case is for example on a list page with delete action per item, and you want a CSRF token per item, so in the template you have something like the following: ```twig {# in a loop over multiple posts #} <form action="{{ path('post_delete', {post: post.id}) }}" method="POST"> <input type="hidden" name="_token" value="{{ csrf_token('delete-post-' ~ post.id) }}"> ... </form> ``` The new feature will allow: ```php #[IsCsrfTokenValid(new Expression('"delete-post-" ~ args["post"].id'))] public function delete(Request $request, Post $post): Response { // ... delete the post } ``` Maybe this need more tests but need help identify which test cases are useful. Hope this can pass before the feature freeze Commits ------- 8f99ca58a8 Add support for dynamic CSRF id in IsCsrfTokenValid
2 parents acbda0e + 10da723 commit a50085b

File tree

3 files changed

+14
-0
lines changed

3 files changed

+14
-0
lines changed

DependencyInjection/Compiler/RegisterCsrfFeaturesPass.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
1515
use Symfony\Component\DependencyInjection\ContainerBuilder;
16+
use Symfony\Component\DependencyInjection\ContainerInterface;
1617
use Symfony\Component\DependencyInjection\Reference;
1718
use Symfony\Component\Security\Csrf\TokenStorage\ClearableTokenStorageInterface;
1819
use Symfony\Component\Security\Http\EventListener\CsrfProtectionListener;
@@ -35,6 +36,10 @@ public function process(ContainerBuilder $container): void
3536

3637
private function registerCsrfProtectionListener(ContainerBuilder $container): void
3738
{
39+
if (!$container->hasDefinition('cache.system')) {
40+
$container->removeDefinition('cache.security_is_csrf_token_valid_attribute_expression_language');
41+
}
42+
3843
if (!$container->has('security.authenticator.manager') || !$container->has('security.csrf.token_manager')) {
3944
return;
4045
}
@@ -45,6 +50,7 @@ private function registerCsrfProtectionListener(ContainerBuilder $container): vo
4550

4651
$container->register('controller.is_csrf_token_valid_attribute_listener', IsCsrfTokenValidAttributeListener::class)
4752
->addArgument(new Reference('security.csrf.token_manager'))
53+
->addArgument(new Reference('security.is_csrf_token_valid_attribute_expression_language', ContainerInterface::NULL_ON_INVALID_REFERENCE))
4854
->addTag('kernel.event_subscriber');
4955
}
5056

DependencyInjection/SecurityExtension.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ public function load(array $configs, ContainerBuilder $container): void
123123
$container->removeDefinition('security.expression_language');
124124
$container->removeDefinition('security.access.expression_voter');
125125
$container->removeDefinition('security.is_granted_attribute_expression_language');
126+
$container->removeDefinition('security.is_csrf_token_valid_attribute_expression_language');
126127
}
127128

128129
if (!class_exists(PasswordHasherExtension::class)) {

Resources/config/security.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,5 +303,12 @@
303303
->set('cache.security_is_granted_attribute_expression_language')
304304
->parent('cache.system')
305305
->tag('cache.pool')
306+
307+
->set('security.is_csrf_token_valid_attribute_expression_language', BaseExpressionLanguage::class)
308+
->args([service('cache.security_is_csrf_token_valid_attribute_expression_language')->nullOnInvalid()])
309+
310+
->set('cache.security_is_csrf_token_valid_attribute_expression_language')
311+
->parent('cache.system')
312+
->tag('cache.pool')
306313
;
307314
};

0 commit comments

Comments
 (0)