From a2f3165e24428cf01caea90702d2fdb07e62f44f Mon Sep 17 00:00:00 2001 From: Abel Hoogeveen Date: Mon, 6 Mar 2023 21:23:27 +0100 Subject: [PATCH] Fixed bug where CSRF-tokens are not replaced in cached forms. - A bug was discovered where cached forms always would contain the same CSRF-token. This would prevent the hidden token from being replaced, resulting in CSRF-errors in WebComponent on every POST-request. --- src/FuzeWorks/Forms/Forms.php | 15 ++++++++++++++- test/base/LibraryTest.php | 31 +++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/FuzeWorks/Forms/Forms.php b/src/FuzeWorks/Forms/Forms.php index a705509..e912cc4 100755 --- a/src/FuzeWorks/Forms/Forms.php +++ b/src/FuzeWorks/Forms/Forms.php @@ -43,6 +43,7 @@ use FuzeWorks\Logger; use FuzeWorks\ObjectStorage\ObjectStorageCache; use FuzeWorks\ObjectStorage\ObjectStorageComponent; use FuzeWorks\Priority; +use FuzeWorks\Security; class Forms implements iLibrary { @@ -98,7 +99,19 @@ class Forms implements iLibrary if ($cache->has($key)) { Logger::log("Returning cached Form '".$name."'"); - return $cache->get($key); + + /** @var Form $form */ + $form = $cache->get($key); + $csrf = $form->getCsrfField(); + if (!is_null($csrf)) + { + /** @var Security $security */ + $security = Factory::getInstance("security"); + $hash = $security->get_csrf_hash(); + $csrf->setValue($hash); + } + + return $form; } // Otherwise, create the form diff --git a/test/base/LibraryTest.php b/test/base/LibraryTest.php index 4974e2d..2123020 100644 --- a/test/base/LibraryTest.php +++ b/test/base/LibraryTest.php @@ -34,6 +34,7 @@ * @version Version 1.3.0 */ +use FuzeWorks\Forms\Fields\HiddenField; use FuzeWorks\Forms\Form; use FuzeWorks\Forms\Forms; use PHPUnit\Framework\TestCase; @@ -84,4 +85,34 @@ class LibraryTest extends TestCase $this->assertSame($form, $form2); } + /** + * @depends testGetCachedForm + */ + public function testGetCachedFormCsrfChange() + { + /** @var \FuzeWorks\Security $security */ + $security = \FuzeWorks\Factory::getInstance("security"); + $hash = $security->get_csrf_hash(); + + $form = $this->forms->getCachedForm(function (Form $form) { + return $form; + }, 'testGetCachedFormCsrfChange', 'testLabel'); + + $csrfField = $form->getCsrfField(); + $this->assertInstanceOf(HiddenField::class, $csrfField); + $this->assertEquals($hash, $csrfField->getValue()); + + // Now change the hash + $security->csrf_regenerate(); + $newHash = $security->get_csrf_hash(); + $this->assertNotEquals($hash, $newHash); + + // Regenerate the form + $newForm = $this->forms->getCachedForm(function (Form $form) { + return $form; + }, 'testGetCachedFormCsrfChange', 'testLabel'); + $csrfField = $newForm->getCsrfField(); + $this->assertEquals($newHash, $csrfField->getValue()); + } + } \ No newline at end of file