Authorization versus Acl

If I use Acl I don’t need authorization plugin and the policies in src/Policy directory?

the ACL plugin and the Authorization plugin clashes. I wrote a middleware to leverage the ACL plugin in the same way authorization would.

<?php
declare(strict_types=1);

namespace App\Middleware;

use Acl\AclInterface;
use App\Model\Entity\User;
use Authentication\AuthenticationServiceInterface;
use Cake\Controller\Component;
use Cake\Controller\ComponentRegistry;
use Cake\Core\App;
use Cake\Core\Configure;
use Cake\Http\Exception\InternalErrorException;
use Cake\Http\Exception\UnauthorizedException;
use Cake\ORM\TableRegistry;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;

class AclMiddleware implements MiddlewareInterface
{
    /**
     * Instance of an ACL class
     *
     * @var \Acl\AclInterface
     */
    protected $_Instance = null;

    /**
     * Constructor. Will return an instance of the correct ACL class as defined in `Configure::read('Acl.classname')`
     *
     * @throws \Cake\Core\Exception\Exception when Acl.classname could not be loaded.
     */
    public function __construct()
    {
        $className = Configure::read('Acl.classname');
        if (!is_string($className) || !$className) {
            throw new \RuntimeException('Config `Acl.classname` not configured');
        }
        $name = $className;
        if (!class_exists($className)) {
            $className = App::className('Acl.' . $name, 'Adapter');
            if (!$className) {
                throw new \RuntimeException(sprintf('Could not find ACL Adapter: %s.', $name));
            }
        }
        $this->adapter($className);
    }

    /**
     * Sets or gets the Adapter object currently in the AclComponent.
     *
     * `$this->Acl->adapter();` will get the current adapter class while
     * `$this->Acl->adapter($obj);` will set the adapter class
     *
     * Will call the initialize method on the adapter if setting a new one.
     *
     * @param \Acl\AclInterface|string $adapter Instance of AclInterface or a string name of the class to use. (optional)
     * @return \Acl\AclInterface either null, or the adapter implementation.
     * @throws \Cake\Core\Exception\Exception when the given class is not an instance of AclInterface
     */
    public function adapter($adapter = null)
    {
        if ($adapter) {
            if (is_string($adapter)) {
                $adapter = new $adapter();
            }
            if (!$adapter instanceof AclInterface) {
                throw new \RuntimeException('AclComponent adapters must implement AclInterface');
            }
            $this->_Instance = $adapter;
            $registry = new ComponentRegistry();
            $component = new Component($registry);
            $this->_Instance->initialize($component);
        }

        return $this->_Instance;
    }

    /**
     * @param \Psr\Http\Message\ServerRequestInterface $request Requests
     * @param \Psr\Http\Server\RequestHandlerInterface $handler siguiente middleware
     * @return \Psr\Http\Message\ResponseInterface
     * @throws \Cake\Http\Exception\UnauthorizedException Cuando el usuario no tiene permisos
     */
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        $auth = $request->getAttribute('authentication');
        if (!($auth instanceof AuthenticationServiceInterface)) {
            throw new \RuntimeException('AuthenticationService not found in request');
        }

        /** @var \Authentication\Authenticator\Result|null $result */
        $result = $auth->getResult();
        if (!$result || !$result->isValid()) {
            return $handler->handle($request);
        }
        $user = $result->getData();
        if (!$user instanceof User) { // my User entity
            throw new \RuntimeException('No user found in session.');
        }

        $acoPath = $this->getPathFromRequest($request);
        /** @var \Acl\Model\Table\AcosTable $Acos */
        $Acos = TableRegistry::getTableLocator()->get('Acl.Acos');
        /** @var \Cake\ORM\Query|null $query */
        $query = $Acos->node($acoPath);
        if (!$query) {
            throw new InternalErrorException('Aco not found');
        }
        /** @var \Acl\Model\Entity\Aco|null $aco */
        $aco = $query->first();
        if (!$aco) {
            throw new InternalErrorException('Aco not found');
        }

        /** @var string $acoId */
        $acoId = $aco->get('id');
        $can = $this->_Instance->check($user->aclNode(), $acoId, 'read');
        if (!$can) {
            throw new UnauthorizedException('You are not authorized to perform this action.');
        }

        return $handler->handle($request);
    }

    /**
     * @param \Psr\Http\Message\ServerRequestInterface $request Request
     * @return string ACO path
     */
    protected function getPathFromRequest(ServerRequestInterface $request): string
    {
        /** @var array $params */
        $params = $request->getAttribute('params');
        $path = 'controllers/';
        if ($params['plugin']) {
            $path .= str_replace('/', '\\', $params['plugin']) . '/';
        }
        if (array_key_exists('prefix', $params) && $params['prefix']) {
            $path .= $params['prefix'] . '/';
        }
        $path .= $params['controller'] . '/' . $params['action'];

        return $path;
    }
}

and in the App middleware function i would just add

$middlewareQueue
    // ... some middlewares
    ->add(new AuthenticationMiddleware($this))
    ->add(new AclMiddleware()) // add this line after Authentication
    // ... more middlewares

This middleware leverages authorization from the ACL controllers tree. I modified it even more for example handling public routes and such, but have it in spanish and linked with other internal developments.
The aclNode of the user function, I took it from this example