Search code examples
drupalshibbolethdrupal-rules

Rules module not picking up the (external) "User Login" event?


In my installation the users login with Shibboleth [1], but the rule [2] I've set up to be executed on "User has logged in" event, isn't executed.

On the other hand, when I login as administrator through the normal Drupal way, the rule is executed.

Does this mean that the external login event isn't handled at all?

Is there a way to overcome this?

[1] http://drupal.org/project/shib_auth

[2] http://drupal.org/project/rules


Solution

  • This seems to be a bug of the Shibboleth module, so the login 'event' is indeed not raised by it (in Drupal terms, it does not invoke hook_user() with $op = 'login').

    Looking at the Shibboleth code, the login seems to happen in its hook_init() implementation:

    /**
    * Create a new user based on informations from the Shibboleth handler if it's necessary or log in.
    */
    function shib_auth_init() {
      global $user;
    
      $unameVar = variable_get('shib_auth_username_variable', 'REMOTE_USER');
      $umailVar = variable_get('shib_auth_username_email', 'HTTP_SHIB_MAIL');
    
      // If
      // - The user isn't logged in
      // - There is Shibboleth authentication in the background
      // - The settings are fine and there has been a valid username setted up
      // - The settings are fine and there has been a valid user email address setted up
      if (!$user->uid && $_SERVER['HTTP_SHIB_IDENTITY_PROVIDER']) {
        if ($_SERVER[$unameVar] && $_SERVER[$umailVar]) {
          user_external_login_register($_SERVER[$unameVar], "shib_auth");
        }
        else {
          drupal_set_message(t("Username or e-mail address is missing. Maybe the Shibboleth configuration is not perfect."),"error");
        }
      }
      if ($user->uid && $_SERVER['HTTP_SHIB_IDENTITY_PROVIDER']) {
        $account = user_save($user,array('mail' => $_SERVER[$umailVar]));
        // Terminate if an error occured during user_save().
        if (!$account) {
          drupal_set_message(t("Error saving user account."), 'error');
          return;
        }
        $user = $account;
      }
    } // function shib_auth_init()
    

    So you'd need to patch this and and ensure that user_module_invoke() is called. The standard way to do this would be to call user_authenticate_finalize() after a successful login (which will in turn call user_module_invoke()), so you'd add that after the user_external_login_register() call:

        [...]
        if ($_SERVER[$unameVar] && $_SERVER[$umailVar]) {
          user_external_login_register($_SERVER[$unameVar], "shib_auth");
          // Do we have a logged in user now?
          if ($user->uid) {
            // Yes, ensure watchdog logging and proper invocation of hook_user
            // NOTE: We pass an empty array, as no form submit was involved here,
            // but we could also pass an array with 'unameVar' and 'umailVar',
            // as they would be the closest substitute.
            user_authenticate_finalize(array());
          }
        }
        [...]
    

    NOTE: Untested code, beware of typos and other stupid oversights ;)

    Should you end up doing this, you might want to submit it as a patch to the bug report linked above. (only if it works, obviously ;)