Hi,
I have a project with a public site, the maintenance and API access are in separate prefixes in routes.
Oh… little detail, I’m upgrading this project from CakePHP 3.9.x to 4.3.x
In my attempt to find a solution I wanted to implement the middleware registration in the routes.php, but this fails I’ve added this for the maintenance part of the site:
$routes->prefix('maintenance', function ($builder) {
$authenticationService = new Authentication\AuthenticationService();
$fields = [
Authentication\Identifier\IdentifierInterface::CREDENTIAL_USERNAME => 'email',
Authentication\Identifier\IdentifierInterface::CREDENTIAL_PASSWORD => 'password',
];
$authenticationService->loadAuthenticator('Authentication.Session');
$authenticationService->loadAuthenticator('Authentication.Form', [
'fields' => $fields,
'loginUrl' => '/maintenance/login',
]);
$builder->registerMiddleware('authentication', new Authentication\Middleware\AuthenticationMiddleware($authenticationService));
$builder->applyMiddleware('authentication');
$builder->connect('/', ['controller' => 'Login', 'action' => 'index']);
$builder->connect('/logout', ['controller' => 'Login', 'action' => 'logout']);
$builder->fallbacks(DashedRoute::class);
});
Found this example, but the result is error:
Subject must be an instance of Authentication\AuthenticationServiceInterface or Authentication\AuthenticationServiceProviderInterface, App\Application given.
Also tried a setup like this:
$provider = new \App\Provider\AuthenticationProvider();
$middleware = new \Authentication\Middleware\AuthenticationMiddleware($provider);
$builder->registerMiddleware('auth', $middleware);
$builder->applyMiddleware('auth');
Found here:
The error is the same
I must admit that I liked the idea to split everything up, but that error doesn’t help
The only thing I can come up is to implement the activation of the authorization in the middleware (Application.php) by using something like:
if (strpos($_SERVER['REQUEST_URI'], '/api') !== 0) {
$middlewareQueue->add(new AuthenticationMiddleware($this));
$middlewareQueue->add(new AuthorizationMiddleware($this, [
'requireAuthorizationCheck' => false,
'unauthorizedHandler' => [
'className' => 'Authorization.CakeRedirect',
'url' => ['plugin' => false, 'controller' => 'Login', 'action' => 'index'],
'queryParam' => 'redirectUrl',
'exceptions' => $exceptions,
],
]));
}
So the authorization logic isn’t triggered when a normal user visits the portal…
When I go for the solution from the manual:
public function getAuthenticationService(ServerRequestInterface $request): AuthenticationServiceInterface
{
$path = $request->getPath();
$service = new AuthenticationService();
if (strpos($path, '/api') === 0) {
// Accept API tokens only
$service->loadAuthenticator('Authentication.Token');
$service->loadIdentifier('Authentication.Token');
return $service;
}
// Web authentication
// Support sessions and form login.
$service->loadAuthenticator('Authentication.Session');
$service->loadAuthenticator('Authentication.Form');
$service->loadIdentifier('Authentication.Password');
return $service;
}
The result is that when I remove the “web authentication” part I get errors that no “service” is configured…
Is this really the only way? It looks more or less ugly in my eyes to solve the problem in this way…
Thank you for your input/reaction!