Skip to main content
Home
Drupal life hacks

Main navigation

  • Drupal
  • React
  • WP
  • Contact
  • About
User account menu
  • Log in

Breadcrumb

  1. Home

Why Using current_route_match in Access Checks is Problematic

By admin, 22 February, 2025

If you inject the current route match service (current_route_match) and use it inside an access() method, your access check will only work when the user is actually visiting that route in the browser.

However, if access is checked programmatically from another page (e.g., via an access API or a block), the current route match will be from that other page, not the one you actually want to check access for.


Example of a Problematic Approach with current_route_match

Let’s say we want to check access to a user profile page (/user/{user}/profile). If we use current_route_match, the access check might work only when visiting that route directly.

use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Session\AccountInterface;

class ProfileAccessCheck {

  protected $routeMatch;

  public function __construct(RouteMatchInterface $route_match) {
    $this->routeMatch = $route_match;
  }

  public function access(AccountInterface $account) {
    // Get the user ID from the route
    $user = $this->routeMatch->getParameter('user');

    if ($user && $account->id() === $user->id()) {
      return AccessResult::allowed();
    }

    return AccessResult::forbidden();
  }
}

The Problem

  • If the user visits /user/5/profile, current_route_match will return the correct route, and everything will work fine.
  • But if access is checked from another context (e.g., a block on the homepage /), current_route_match->getParameter('user') will be NULL because the homepage doesn’t have a user parameter.
  • This can cause access checks to fail or always return forbidden when checked programmatically.

The Correct Approach

Instead of using current_route_match, pass the required object explicitly in the access() method. This is how Drupal handles access checks properly:

use Drupal\Core\Access\AccessResult;
use Drupal\Core\Session\AccountInterface;
use Drupal\user\UserInterface;

class ProfileAccessCheck {

  public function access(UserInterface $user, AccountInterface $account) {
    return $account->id() === $user->id()
      ? AccessResult::allowed()
      : AccessResult::forbidden();
  }
}

Now, when checking access programmatically:

$access = \Drupal::service('access_check.profile')->access($some_user, $current_user);

it will work in any context because the required data is passed explicitly.


Key Takeaways

❌ Bad practice: Using current_route_match inside access()
✅ Best practice: Pass required objects (e.g., UserInterface $user) as parameters in the access() method.

This ensures reliable access checks in all contexts! 🚀

Tags

  • #Drupal Planet
  • Access Check

Comments

About text formats

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.
Powered by Drupal