You are here

function shib_auth_init in Shibboleth Authentication 6.3

Same name and namespace in other branches
  1. 5.3 shib_auth.module \shib_auth_init()
  2. 5.2 shib_auth.module \shib_auth_init()
  3. 6.4 shib_auth.module \shib_auth_init()
  4. 6 shib_auth.module \shib_auth_init()
  5. 6.2 shib_auth.module \shib_auth_init()
  6. 7.4 shib_auth.module \shib_auth_init()

Create a new user based on informations from the Shibboleth handler if it's necessary or log in.

If already authenticated - do nothing If Shibboleth doesn't provide User information - error message Else if user exists, and mail override (shib_auth_req_shib_only) enabled, override existing user info If not exists, and Shibboleth provides mail address, create an account for this user If there's no mail attribute, ask for the mail address on a generated form if mail override (shib_auth_req_shib_only) is disabled In this case, the account will be created with this e-mail address.

This function also gives roles to the user, if certain server fields were provided by the Shibboleth server

File

./shib_auth.module, line 50
This is a Shibboleth authentication module.

Code

function shib_auth_init() {
  global $user;
  $shib_headers_exist = $_SERVER['HTTP_SHIB_IDENTITY_PROVIDER'] || $_SERVER['Shib-Identity-Provider'] || $_SERVER['Shib_Identity_Provider'];
  if (shib_auth_isDebug()) {
    $debug_message = print_r($_SERVER, TRUE);
    drupal_set_message('<pre>' . $debug_message . '</pre>');
  }

  // if the user IS logged in as non-admin, but we're missing Shibboleth identity
  if (!$shib_headers_exist && $_SESSION['authentication'] == 'shib_auth' && variable_get('shib_auth_auto_destroy_session', FALSE) && $user->uid && $user->uid != 1) {
    drupal_set_message(t('Your session is expired. Please log in again!'), "error");
    unset($_SESSION['authentication']);
    session_destroy();
    $user = drupal_anonymous_user();
  }
  elseif (isset($_SESSION['uname'])) {
    if ($_SESSION['uname'] != $uname) {
      unset($_SESSION['authentication']);
      unset($_SESSION['uname']);
      session_destroy();
      $user = drupal_anonymous_user();
    }
  }
  else {
    $_SESSION['uname'] = $uname;
  }
  $uname = $_SERVER[variable_get('shib_auth_username_variable', 'REMOTE_USER')];
  $umail = $_SERVER[variable_get('shib_auth_username_email', 'HTTP_SHIB_MAIL')];
  $umail_single = preg_replace('/;.*/', '', $umail);

  // 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 set up
  // - The settings are fine and there has been a valid user email address set up
  if (!$user->uid && $shib_headers_exist) {

    //If custom mail form will be generated, generate it only once
    if (isset($_SESSION['redirected_to_custom_mail_form']) && $_SESSION['redirected_to_custom_mail_form']) {
      unset($_SESSION['redirected_to_custom_mail_form']);
    }
    else {

      //Shib didn't provide username, or the admin gave wrong server variable on the shib config form
      if (!$uname) {
        $message = t('Username is missing. Please contact your Shibboleth administrator!');
        drupal_set_message($message, "error");
        watchdog('shib_auth', $message, WATCHDOG_CRITICAL);
      }
      else {
        $username_query = db_query("SELECT * FROM {users} WHERE name='%s'", $uname);
        $new_user = !db_fetch_object($username_query);

        //The user exists in the drupal user database, login her
        if (!$new_user) {
          user_external_login_register($uname, "shib_auth");
          $_SESSION['authentication'] = 'shib_auth';

          //if we have an e-mail address from the shib server
          if ($umail_single) {

            //and the Shibboleth mail address override was enabled in the admin config
            if (variable_get('shib_auth_mail_shib_only', 0) == 0) {

              //check if there isn't any user with this e-mail (whose name is different)
              $email_for_other_user_query = db_query("SELECT * FROM {users} WHERE mail='%s' AND name <> '%s'", $umail_single, $uname);
              $email_for_other_user = db_fetch_object($username_and_email_query);
              if ($email_for_other_user) {
                drupal_set_message(t("Error saving user account. E-mail address is already used."), 'error');
              }
              else {
                $user = user_save($user, array(
                  'mail' => $umail_single,
                ));
              }
            }
          }
        }
        else {

          //If we have an e-mail address from the shib server, and there isn't any user with this address, create an account with these infos
          if ($umail_single) {
            $email_already_used_query = db_query("SELECT * FROM {users} WHERE mail='%s'", $umail_single);
            $email_already_used = db_fetch_object($email_already_used_query);

            // If the mail address is used, give an error
            if ($email_already_used) {
              drupal_set_message(t("Error saving user account. E-mail address is already used."), 'error');
            }
            else {
              user_external_login_register($uname, "shib_auth");
              $_SESSION['authentication'] = 'shib_auth';
              $user = user_save($user, array(
                'mail' => $umail_single,
              ));
            }
          }
          else {
            if (variable_get('shib_auth_mail_shib_only', 0) == 0) {
              $message = t('E-mail address is missing. Please contact your Shibboleth administrator!');
              drupal_set_message($message, "error");
              watchdog('shib_auth', $message, WATCHDOG_CRITICAL);
            }
            else {

              // if the custom mail was enabled on the admin form
              if ($_POST['form_id'] == 'shib_auth_custom_email' && $_POST['custom_mail']) {
                $custom_mail = $_POST['custom_mail'];
              }

              //if the user provided the custom mail string, and it is not empty
              if (isset($custom_mail) && $custom_mail) {

                // and it isn't used by another registered drupal user
                $email_already_used_query = db_query("SELECT * FROM {users} WHERE mail='%s'", $custom_mail);
                $email_already_used = db_fetch_object($email_already_used_query);
                if ($email_already_used) {
                  drupal_set_message(t("Error saving user account. E-mail address is already used."), 'error');
                }
                else {
                  user_external_login_register($uname, "shib_auth");
                  $_SESSION['authentication'] = 'shib_auth';
                  $user = user_save($user, array(
                    'mail' => $custom_mail,
                  ));
                }

                //then the user is redirected to the page, which she wanted to open before the auth process had been initiated
                if (isset($_SESSION['redirected_to_custom_mail_form_url'])) {
                  $redirect_url = $_SESSION['redirected_to_custom_mail_form_url'];
                  unset($_SESSION['redirected_to_custom_mail_form_url']);
                  drupal_goto($redirect_url);
                }
              }
              else {
                $_SESSION['redirected_to_custom_mail_form'] = TRUE;
                $_SESSION['redirected_to_custom_mail_form_url'] = $_GET['q'];
                drupal_goto('shib_auth/get_custom_mail');
              }
            }
          }
        }
      }
    }
  }

  //The admin can define authorization rules based on the server variables - which are provided by Shibboleth -

  //to give roles to users, if the IdP provide certain authorization or authentication string

  //the rules can be defined as a server field - Regexp - role(s) trio

  // Store rules for further examination
  $former_rules = serialize($user->roles);

  // Examine all previously saved rule
  $rules = db_query("SELECT * FROM {shib_auth}");
  while ($rule = db_fetch_array($rules)) {
    $fieldname = $rule['field'];
    $expression = '/' . urldecode($rule['regexpression']) . '/';

    //check out, if the given server field exists
    if (isset($_SERVER[$fieldname])) {
      foreach (explode(';', $_SERVER[$fieldname]) as $value) {

        //check if the RegEx can be fit to one of the value of the server field
        if (preg_match($expression, trim($value))) {
          $roles = unserialize(urldecode($rule['role']));

          //if there is a match, give this user the specified role(s)
          if (!empty($roles)) {
            foreach ($roles as $key => $value) {
              $user->roles[$key] = $value;
            }
          }
        }
      }
    }
  }
  $user->roles = array_filter($user->roles);

  // If the user roles array has been changed then reset the permission cache
  if (serialize($user->roles) != $former_rules) {

    // Hack to reset the permissions
    user_access('access content', $account, TRUE);
  }
}