zend-framework2zfcuser

zfcuser - whitelist routes and all childroutes


I'am using ZfcUser module in my application to protect access to /admin route. As I want to block all childroutes of /admin, except for /login, /register etc.

In order to do so, I've added a code from accepted answer here - Zend Framework 2 - Global check for authentication with ZFCUser

protected $whitelist = array('zfcuser/login', 'default');

  public function onBootstrap($e)
  {
      $app = $e->getApplication();
      $em  = $app->getEventManager();
      $sm  = $app->getServiceManager();

      $list = $this->whitelist;
      $auth = $sm->get('zfcuser_auth_service');

      $em->attach(MvcEvent::EVENT_ROUTE, function($e) use ($list, $auth) {
          $match = $e->getRouteMatch();

          // No route match, this is a 404
          if (!$match instanceof RouteMatch) {
              return;
          }

          // Route is whitelisted
          $name = $match->getMatchedRouteName();
          if (in_array($name, $list)) {
              return;
          }

          // User is authenticated
          if ($auth->hasIdentity()) {
              return;
          }

          // Redirect to the user login page, as an example
          $router   = $e->getRouter();
          $url      = $router->assemble(array(), array(
              'name' => 'zfcuser/login'
          ));

          $response = $e->getResponse();
          $response->getHeaders()->addHeaderLine('Location', $url);
          $response->setStatusCode(302);

          return $response;
      }, -100);
  }

It works, however it also block access to root routes - and as there is plenty of them, I do not really want to add every single route to whitelist. Is there any way to restrict access only to /admin routes?


Solution

  • You may protect access to admin area by checking each controller name instead of checking route names. Thus you may control user's accessibility with less effort and it is more portable than checking route names.

    List your controllers where you want to limit accesses. So everything related to a controller should be restricted. Wherever you need to restrict access just list them here. You do not need to make your hands dirty with onBootstrap() method anymore.

    protected $whitelist = array(
        'ZfcUser\Controller\User', // or use 'zfcuser'
    ); 
    

    Put right controller name in the $whitelist. You can get that by echoing $controller in the onBootstrap() method. Please check out the commented area below.

    Next catch up the controller name and then check whether that is listed in your list or not.

    public function onBootstrap(MvcEvent $e)
    {
        $app = $e->getApplication();
        $em  = $app->getEventManager();
        $sm  = $app->getServiceManager();
    
        $list = $this->whitelist;
        $auth = $sm->get('zfcuser_auth_service');
    
        $em->attach(MvcEvent::EVENT_ROUTE, function($e) use ($list, $auth) {
    
            // get the current route
            $route = $e->getRouteMatch()->getMatchedRouteName();
    
            // check for 'zfcuser/login' and 'zfcuser/register' routes
            if (in_array($route, array('zfcuser/login', 'zfcuser/register'))) {
                return;
            }   
    
            // get the current controller name
            $controller = $e->getRouteMatch()->getParam('controller');
    
            // Check the right controller name by echoing 
            // echo $controller;         
    
            // check if a user has access on the current controller 
            if (in_array($controller, $list)) {
    
                if(! $auth->hasIdentity()) {
    
                    $router = $e->getRouter();
                    $url = $router->assemble(array(), array(
                        'name' => 'zfcuser/login'
                    ));
    
                    $response = $e->getResponse();
                    $response->getHeaders()->addHeaderLine('Location', $url);
                    $response->setStatusCode(302);
    
                    return $response;
                }
            }
    
        }, -100);
    }    
    

    Let us know if it helps you!