diff --git a/composer.json b/composer.json index 3a9bae5b..30cf9490 100644 --- a/composer.json +++ b/composer.json @@ -18,6 +18,7 @@ "psr/http-server-middleware": "^1.0" }, "require-dev": { + "cakephp/cakephp": "^4.0", "cakephp/cakephp-codesniffer": "^4.0", "firebase/php-jwt": "^5.0", "phpunit/phpunit": "^8.5 || ^9.3" diff --git a/src/Controller/Component/AuthenticationComponent.php b/src/Controller/Component/AuthenticationComponent.php index 60d04c79..b835c668 100644 --- a/src/Controller/Component/AuthenticationComponent.php +++ b/src/Controller/Component/AuthenticationComponent.php @@ -45,6 +45,7 @@ class AuthenticationComponent extends Component implements EventDispatcherInterf * - `requireIdentity` - By default AuthenticationComponent will require an * identity to be present whenever it is active. You can set the option to * false to disable that behavior. See allowUnauthenticated() as well. + * - `unauthenticatedMessage` - Error message to use when `UnauthenticatedException` is thrown. * * @var array */ @@ -53,6 +54,7 @@ class AuthenticationComponent extends Component implements EventDispatcherInterf 'requireIdentity' => true, 'identityAttribute' => 'identity', 'identityCheckEvent' => 'Controller.startup', + 'unauthenticatedMessage' => null, ]; /** @@ -172,9 +174,7 @@ protected function doIdentityCheck(): void $identity = $request->getAttribute($this->getConfig('identityAttribute')); if (!$identity) { - throw new UnauthenticatedException( - 'No identity found. You can skip this check by configuring `requireIdentity` to be `false`.' - ); + throw new UnauthenticatedException($this->getConfig('unauthenticatedMessage', '')); } } diff --git a/tests/TestCase/Controller/Component/AuthenticationComponentTest.php b/tests/TestCase/Controller/Component/AuthenticationComponentTest.php index 6a4732b3..a8bfcd94 100644 --- a/tests/TestCase/Controller/Component/AuthenticationComponentTest.php +++ b/tests/TestCase/Controller/Component/AuthenticationComponentTest.php @@ -498,10 +498,31 @@ public function testIdentityCheckInBeforeFilter() $component = new AuthenticationComponent($registry); $this->expectException(UnauthenticatedException::class); + $this->expectExceptionMessage('Authentication is required to continue'); $this->expectExceptionCode(401); $component->setConfig('identityCheckEvent', 'Controller.initialize'); $component->allowUnauthenticated(['index', 'add']); $component->beforeFilter(); } + + public function testCustomUnauthenticatedMessage() + { + $request = $this->request + ->withAttribute('authentication', $this->service); + + $controller = new Controller($request, $this->response); + $registry = new ComponentRegistry($controller); + $component = new AuthenticationComponent($registry); + + $errorMessage = 'You shall not pass!'; + $this->expectException(UnauthenticatedException::class); + $this->expectExceptionMessage($errorMessage); + $this->expectExceptionCode(401); + + $component->setConfig('identityCheckEvent', 'Controller.initialize'); + $component->setConfig('unauthenticatedMessage', $errorMessage); + $component->allowUnauthenticated(['index', 'add']); + $component->beforeFilter(); + } }