From f51f1a1e43f730a22bc319c21c1a55f7d128daf6 Mon Sep 17 00:00:00 2001 From: Fernando Herrero Date: Sat, 29 Aug 2026 02:38:39 +0200 Subject: [PATCH 01/10] New method skipAuthorizationActions --- .../Component/AuthorizationComponent.php | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/Controller/Component/AuthorizationComponent.php b/src/Controller/Component/AuthorizationComponent.php index c87a5e8..9df372a 100644 --- a/src/Controller/Component/AuthorizationComponent.php +++ b/src/Controller/Component/AuthorizationComponent.php @@ -49,6 +49,21 @@ class AuthorizationComponent extends Component 'actionMap' => [], ]; + protected array $skipAuthorization = []; + + /** + * Allow specific actions to bypass authorization checks + * + * @param string ...$actions + * @return $this + */ + public function skipAuthorizationActions(string ...$actions) + { + $this->skipAuthorization = $actions; + + return $this; + } + /** * Check the policy for $resource, raising an exception on error. * @@ -130,6 +145,12 @@ protected function performCheck( $action = $this->getDefaultAction($request); } + if (in_array($action, $this->skipAuthorization)) { + $this->skipAuthorization(); + + return true; + } + $identity = $this->getIdentity($request); if (!$identity instanceof IdentityInterface) { return $this->getService($request)->{$method}(null, $action, $resource); From 958b010d9ca82e99e61573a824a74ece3c0ac09c Mon Sep 17 00:00:00 2001 From: Fernando Herrero Date: Sat, 29 Aug 2026 02:57:54 +0200 Subject: [PATCH 02/10] PHPDoc for $skipAuthorization property --- src/Controller/Component/AuthorizationComponent.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Controller/Component/AuthorizationComponent.php b/src/Controller/Component/AuthorizationComponent.php index 9df372a..8661ff7 100644 --- a/src/Controller/Component/AuthorizationComponent.php +++ b/src/Controller/Component/AuthorizationComponent.php @@ -49,6 +49,11 @@ class AuthorizationComponent extends Component 'actionMap' => [], ]; + /** + * Methods to skip authorization + * + * @var array + */ protected array $skipAuthorization = []; /** From 3a0f27c882e2f147b4350d9010ce6647867ddb3b Mon Sep 17 00:00:00 2001 From: Fernando Herrero Date: Sat, 29 Aug 2026 03:47:43 +0200 Subject: [PATCH 03/10] Use skipAuthorization config var instead of $skipAuthorization property --- src/Controller/Component/AuthorizationComponent.php | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/Controller/Component/AuthorizationComponent.php b/src/Controller/Component/AuthorizationComponent.php index 8661ff7..0aabd98 100644 --- a/src/Controller/Component/AuthorizationComponent.php +++ b/src/Controller/Component/AuthorizationComponent.php @@ -49,13 +49,6 @@ class AuthorizationComponent extends Component 'actionMap' => [], ]; - /** - * Methods to skip authorization - * - * @var array - */ - protected array $skipAuthorization = []; - /** * Allow specific actions to bypass authorization checks * @@ -64,7 +57,7 @@ class AuthorizationComponent extends Component */ public function skipAuthorizationActions(string ...$actions) { - $this->skipAuthorization = $actions; + $this->_config['skipAuthorization'] = array_merge($this->_config['skipAuthorization'], $actions); return $this; } @@ -151,7 +144,7 @@ protected function performCheck( } if (in_array($action, $this->skipAuthorization)) { - $this->skipAuthorization(); + $this->getService($request)->skipAuthorization(); return true; } From d7661533c468cc6b27d73b79a7041a6285329e8a Mon Sep 17 00:00:00 2001 From: Fernando Herrero Date: Sat, 29 Aug 2026 03:49:19 +0200 Subject: [PATCH 04/10] Fix reference to $skipAuthorization property --- src/Controller/Component/AuthorizationComponent.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Controller/Component/AuthorizationComponent.php b/src/Controller/Component/AuthorizationComponent.php index 0aabd98..75eb125 100644 --- a/src/Controller/Component/AuthorizationComponent.php +++ b/src/Controller/Component/AuthorizationComponent.php @@ -143,7 +143,7 @@ protected function performCheck( $action = $this->getDefaultAction($request); } - if (in_array($action, $this->skipAuthorization)) { + if (in_array($action, $this->_config['skipAuthorization'])) { $this->getService($request)->skipAuthorization(); return true; From 63adab055dea0849b814558260f5dd0410ede6d9 Mon Sep 17 00:00:00 2001 From: Fernando Herrero Date: Sat, 29 Aug 2026 04:00:17 +0200 Subject: [PATCH 05/10] Update documentation and test --- docs/en/component.md | 6 ++++++ .../Component/AuthorizationComponentTest.php | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/docs/en/component.md b/docs/en/component.md index 30d456b..278e85c 100644 --- a/docs/en/component.md +++ b/docs/en/component.md @@ -34,6 +34,12 @@ $this->loadComponent('Authorization.Authorization', [ ]); ``` +The same can be done at runtime, for example in `beforeFilter()`: + +```php +$this->Authorization->skipAuthorizationActions('login', 'logout'); +``` + By default, every action requires authorization when authorization checking is enabled. diff --git a/tests/TestCase/Controller/Component/AuthorizationComponentTest.php b/tests/TestCase/Controller/Component/AuthorizationComponentTest.php index b1d17e6..5b8aefd 100644 --- a/tests/TestCase/Controller/Component/AuthorizationComponentTest.php +++ b/tests/TestCase/Controller/Component/AuthorizationComponentTest.php @@ -550,6 +550,24 @@ public function testAuthorizeModel(): void $this->assertEquals(['foo', 'bar', 'baz'], $this->Auth->getConfig('authorizeModel')); } + public function testSkipAuthorizationActions(): void + { + $this->Auth->skipAuthorizationActions('foo', 'bar'); + $this->assertEquals(['foo', 'bar'], $this->Auth->getConfig('skipAuthorization')); + + $this->Auth->skipAuthorizationActions('baz'); + $this->assertEquals(['foo', 'bar', 'baz'], $this->Auth->getConfig('skipAuthorization')); + } + + public function testSkipAuthorizationActionsAppliedOnAuthorizeAction(): void + { + $service = $this->Controller->getRequest()->getAttribute('authorization'); + + $this->Auth->skipAuthorizationActions('edit'); + $this->Auth->authorizeAction(); + $this->assertTrue($service->authorizationChecked()); + } + public function testMapAction(): void { $this->Auth->mapAction('foo', 'bar'); From 0eedf37e501df736d212addcfd0e459f68b3e93d Mon Sep 17 00:00:00 2001 From: Fernando Herrero Date: Sat, 29 Aug 2026 04:04:46 +0200 Subject: [PATCH 06/10] test fix rector setup --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 8dce7d7..32e6433 100644 --- a/composer.json +++ b/composer.json @@ -73,7 +73,7 @@ "stan": "@phpstan", "stan-baseline": "tools/phpstan --generate-baseline", "stan-setup": "phive install", - "rector-setup": "cp composer.json composer.backup && composer require --dev rector/rector:\"~2.3.1\" && mv composer.backup composer.json", + "rector-setup": "cp composer.json composer.backup && composer require --dev rector/rector --with-dependencies && mv composer.backup composer.json", "rector-check": "vendor/bin/rector process --dry-run", "rector-fix": "vendor/bin/rector process", "test": "phpunit", From 0632e4974ca69d5f4500b2733780745276ff435e Mon Sep 17 00:00:00 2001 From: Fernando Herrero Date: Sat, 29 Aug 2026 04:51:42 +0200 Subject: [PATCH 07/10] Use authorizeAction and authorizationChecked for skip actions --- src/Controller/Component/AuthorizationComponent.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Controller/Component/AuthorizationComponent.php b/src/Controller/Component/AuthorizationComponent.php index 75eb125..18b299b 100644 --- a/src/Controller/Component/AuthorizationComponent.php +++ b/src/Controller/Component/AuthorizationComponent.php @@ -143,9 +143,8 @@ protected function performCheck( $action = $this->getDefaultAction($request); } - if (in_array($action, $this->_config['skipAuthorization'])) { - $this->getService($request)->skipAuthorization(); - + $this->authorizeAction(); + if ($this->getService($request)->authorizationChecked()) { return true; } From fae0e9562365952d86d0924df7bfc64f50933026 Mon Sep 17 00:00:00 2001 From: Fernando Herrero Date: Sat, 29 Aug 2026 05:09:57 +0200 Subject: [PATCH 08/10] phpunit out of memory --- src/Controller/Component/AuthorizationComponent.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Controller/Component/AuthorizationComponent.php b/src/Controller/Component/AuthorizationComponent.php index 18b299b..d75fff2 100644 --- a/src/Controller/Component/AuthorizationComponent.php +++ b/src/Controller/Component/AuthorizationComponent.php @@ -143,8 +143,10 @@ protected function performCheck( $action = $this->getDefaultAction($request); } - $this->authorizeAction(); - if ($this->getService($request)->authorizationChecked()) { + $skipAuthorization = $this->checkAction($action, 'skipAuthorization'); + if ($skipAuthorization) { + $this->skipAuthorization(); + return true; } From 8487d1e4a2af4592728c5acf99bded28612a61ca Mon Sep 17 00:00:00 2001 From: Fernando Herrero Date: Sat, 29 Aug 2026 05:26:14 +0200 Subject: [PATCH 09/10] Update PHPDoc for skipAuthorizationActions method --- .../Component/AuthorizationComponent.php | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/Controller/Component/AuthorizationComponent.php b/src/Controller/Component/AuthorizationComponent.php index d75fff2..79bfa4b 100644 --- a/src/Controller/Component/AuthorizationComponent.php +++ b/src/Controller/Component/AuthorizationComponent.php @@ -49,19 +49,6 @@ class AuthorizationComponent extends Component 'actionMap' => [], ]; - /** - * Allow specific actions to bypass authorization checks - * - * @param string ...$actions - * @return $this - */ - public function skipAuthorizationActions(string ...$actions) - { - $this->_config['skipAuthorization'] = array_merge($this->_config['skipAuthorization'], $actions); - - return $this; - } - /** * Check the policy for $resource, raising an exception on error. * @@ -198,6 +185,22 @@ public function skipAuthorization() return $this; } + /** + * Adds actions that should skip the automatic authorization check. + * + * Actions registered here are marked as authorized in `authorizeAction()`, + * which runs on the configured `authorizationEvent`. + * + * @param string ...$actions Controller actions to skip authorization for. + * @return $this + */ + public function skipAuthorizationActions(string ...$actions) + { + $this->_config['skipAuthorization'] = array_merge($this->_config['skipAuthorization'], $actions); + + return $this; + } + /** * Allows to map controller action to another authorization policy action. * From 25c201a012513605e81f89d9ead2b10544e00886 Mon Sep 17 00:00:00 2001 From: Fernando Herrero Date: Sat, 29 Aug 2026 13:07:48 +0200 Subject: [PATCH 10/10] return Result on canResult --- src/Controller/Component/AuthorizationComponent.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Controller/Component/AuthorizationComponent.php b/src/Controller/Component/AuthorizationComponent.php index 79bfa4b..24c1d46 100644 --- a/src/Controller/Component/AuthorizationComponent.php +++ b/src/Controller/Component/AuthorizationComponent.php @@ -19,6 +19,7 @@ use Authorization\AuthorizationServiceInterface; use Authorization\Exception\ForbiddenException; use Authorization\IdentityInterface; +use Authorization\Policy\Result; use Authorization\Policy\ResultInterface; use Cake\Controller\Component; use Cake\Http\ServerRequest; @@ -134,7 +135,10 @@ protected function performCheck( if ($skipAuthorization) { $this->skipAuthorization(); - return true; + return match ($method) { + 'can' => true, + 'canResult' => new Result(true), + }; } $identity = $this->getIdentity($request);