views:

35

answers:

3

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

A: 

The order in which Drupal loads the modules is very important in these cases. You will need to set rules so that it is loaded after your authentication module. For instance, with ldap_integration

mysql> UPDATE system SET weight=20 WHERE name="rules";
mysql> UPDATE system SET weight=20 WHERE name="rules_forms";
mysql> UPDATE system SET weight=0 WHERE name="ldapauth";

"20" is an arbitrary number that is bigger than whatever your authentication module is.

Andrew Sledge
IMHO, execution (or load) order is not relevant here, as the hook is not invoked at all! (The order would only be relevant, if he wanted to react after another modules implementation of the same hook, but in this case there is nothing to react to in the first place)
Henrik Opel
A: 

This seems to be an unresolved 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 ;)

Henrik Opel
A: 

Drupal runs hooks, meaning modules get the chance to run a piece of code. E.g. on login a hook_user is called.

Too often, modules will call a drupal_goto() inside such hooks. This will break severely. Drupal_goto will kill everything, send a redirect-header, then die the application. No other hooks will be ran.

  1. Hooks should never call drupal_goto(), die() or other such destructive functions. But since nothing keeps people from breaking this rule, people (modules) will break it.
  2. form_alter should never invoke goto's, dies and so forth, for the same reason.

You can find any "illegal" goto's by installing devel module and toggling the setting "show redirects", you will see if e.g. sibbletooth invoked a redirect where it should not have.

berkes

related questions