Description
Currently, the Authentication plugin provides a very convenient $this->Authentication->allowUnauthenticated(['action']) method to skip authentication checks for specific controller actions.
However, the Authorization plugin lacks a direct equivalent, forcing developers to manually call $this->Authorization->skipAuthorization() inside every public action or build custom logic in beforeFilter.
I propose adding an allowUnauthorized() method to AuthorizationComponent to bring API parity between both core plugins and streamline the handling of public/unauthorized actions.
Proposed Solution
We can introduce an internal tracker for unauthorized actions within the component and intercept the authorization checks before they hit the policies.
Here is a working implementation I am currently using by extending the base component:
<?php
declare(strict_types=1);
namespace Authorization\Controller\Component;
use Authorization\Policy\ResultInterface;
use Cake\Controller\Component;
class AuthorizationComponent extends Component
{
protected array $unauthorizedActions = [];
/**
* Allow specific actions to bypass authorization checks.
*
* @param array<string> $actions List of controller actions.
* @return $this
*/
public function allowUnauthorized(array $actions): static
{
$this->unauthorizedActions = $actions;
return $this;
}
/**
* Overriding performCheck to automatically skip authorization for allowed actions
*/
protected function performCheck(mixed $resource, ?string $action = null, string $method = 'can'): ResultInterface|bool
{
$request = $this->getController()->getRequest();
if ($action === null) {
$action = $this->getDefaultAction($request);
}
if (in_array($action, ($this->unauthorizedActions)) {
$this->skipAuthorization();
return true;
}
return parent::performCheck($resource, $action, $method);
}
}
Example Usage
This allows a much cleaner and intuitive setup in any controller's beforeFilter:
public function beforeFilter(\Cake\Event\EventInterface $event)
{
parent::beforeFilter($event);
$this->Authorization->allowUnauthorized([
'login',
'logout',
'verify',
]);
// Global authorization check for the rest of the actions
if (!$this->Authorization->can($this)) {
return $this->redirect('/');
}
}
Why this should be added
- API Consistency: Alignment with how
AuthenticationComponent::allowUnauthenticated() works.
- Cleaner Controllers: Avoids cluttering public actions with repetitive
$this->Authorization->skipAuthorization() calls.
- Better DX: Centralizes access control rules in
beforeFilter right next to authentication rules.
Additional Notes
- Naming Conventions: I am completely open to suggestions regarding the names of the
allowUnauthorized() method and the $unauthorizedActions property if the core team prefers a different naming convention (e.g., allowBypass(), skipActions(), etc.).
- Pull Request: If the core team values this feature and approves the overall approach, I am more than happy to create and submit the Pull Request along with the necessary test cases.
Description
Currently, the
Authenticationplugin provides a very convenient$this->Authentication->allowUnauthenticated(['action'])method to skip authentication checks for specific controller actions.However, the
Authorizationplugin lacks a direct equivalent, forcing developers to manually call$this->Authorization->skipAuthorization()inside every public action or build custom logic inbeforeFilter.I propose adding an
allowUnauthorized()method toAuthorizationComponentto bring API parity between both core plugins and streamline the handling of public/unauthorized actions.Proposed Solution
We can introduce an internal tracker for unauthorized actions within the component and intercept the authorization checks before they hit the policies.
Here is a working implementation I am currently using by extending the base component:
Example Usage
This allows a much cleaner and intuitive setup in any controller's
beforeFilter:Why this should be added
AuthenticationComponent::allowUnauthenticated()works.$this->Authorization->skipAuthorization()calls.beforeFilterright next to authentication rules.Additional Notes
allowUnauthorized()method and the$unauthorizedActionsproperty if the core team prefers a different naming convention (e.g.,allowBypass(),skipActions(), etc.).