I have a Drupal 7 site on a server wich can be accessed by 2 differents Network (A and B). On both Network I use SAML to authentificate the users and affect them their roles (including back office roles) with SAML attributes. When an user logs in from network A to my site he must have his back office options but when he logs in from network B he must not have them.

I want to block any administration feature, not just back office access so blocking urls will not be enough. I don't want to see the edit/view tabs on content in the front office. I don't want them to have access to content that is not published (even if they have access to it on network A). Like the users had no back office role at all when they are on network B.

I am able to detect wich network the user is using on each visit and I have some code that allows me to affect the back office roles only if he comes from network A.

But if the user logs in first on network A then on his mobile access the site from network B and logs in he will lose his back office role on A unless he logout/login again.

Is there a way to disable all back office (admin) features on each visit if coming from network B? And not on each login? Aka a solution not involving removing his back office roles so he keep them when on network A.

  • At the Drupal level, you'd need to change the access callback of a reasonable number of menu callbacks to do that. Also you need to consider what you define as "back office". For example, is editing a node a back office operation in your setup? What about other entity types? You could reliably set something up in hook_menu_alter() for anything under /admin, it'd even be quite easy, it's just the rest of the paths you need to consider. The other option of course would be to handle it at web server level, so Drupal never gets involved. Might be harder to execute code in that context though
    – Clive
    Commented Jul 26, 2016 at 8:41
  • Thanks Clive, I updated my question to answer you. But blocking urls will not be enough even on a web server level (we allready do that for security reasons, network B is more open to public). What I want is to simulate the users had no back office role at all, to temporary disable them if on network B. And editing the access callback of that many menus seems a long and complex process. Commented Jul 26, 2016 at 9:09
  • Indeed, it is a long and complex process. But Drupal doesn't have the concept of an "administration feature", just paths and operations that are controlled by static permissions assigned to roles. Plus the ability for modules to provide dynamic access decisions of their own, based on any criteria they like. I'm racking my brains but I don't see this having a happy ending, the surface area for what might be considered an admin feature, and the entry points to actually controlling the access decision for each, are just too great. And that's just considering core, not even contrib modules
    – Clive
    Commented Jul 26, 2016 at 9:14
  • 1
    Hope I'm wrong though, there might be a simpler way by patching a core function or something. In fact you'd get quite a lot of the way there by patching user_access to first check the network
    – Clive
    Commented Jul 26, 2016 at 9:15
  • Yep user_access seems to be the way to go, It seems if I alter the $account->roles to remove the back office roles on network B before user_role_permissions() is called might do the job. I wonder if I could alter the global $user directly to remove the roles, and avoid altering the core, with a hook_init() (no cache engine on this site). Commented Jul 26, 2016 at 10:44

1 Answer 1


Ok so the best solution I found wich might even work with a cache engine and without altering core was to remove the roles from the global $user in a hook_boot() :

function myModule_boot() {
  global $user;

  // if the user is connected and I am on network B
  if ($user->uid != 0 && variable_get('networkB', FALSE)) {
    // then we remove the role BO from the global $user
    // wich are stocked in a variable (roles_back_office) as a string (rid separated by pipes).
    foreach(explode('|', variable_get('roles_back_office')) as $rid) {
      if (isset($user->roles[$rid])) unset($user->roles[$rid]);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.