You are here

function _bakery_handle_sso in Bakery Single Sign-On System 7.3

Authenticate from valid SSO cookie.

Parameters

array $cookie:

1 call to _bakery_handle_sso()
bakery_boot in ./bakery.module
Implements hook_boot().

File

./bakery.module, line 692

Code

function _bakery_handle_sso($cookie) {
  global $user;

  // Detect SSO cookie mismatch if there is already a valid session for user.
  if ($user->uid && $cookie['name'] !== $user->name) {

    // The SSO cookie doesn't match the existing session so force a logout.
    drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
    _bakery_user_logout();
  }
  elseif ($user->uid > 0) {

    // User is already authenticated as SSO user.
    return;
  }

  // Since this might happen in hook_boot we need to bootstrap first.
  // Note that this only runs if they have a valid session on the master
  // and do not have one on the slave so it only creates the extra load of
  // a bootstrap on one pageview per session on the site which is not much.
  drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

  // User is anonymous. If they do not have an account we'll create one by
  // requesting their information from the master site. If they do have an
  // account we may need to correct some disparant information.
  $account = user_load_multiple(array(), array(
    'name' => $cookie['name'],
    'mail' => $cookie['mail'],
  ));
  $account = reset($account);

  // Fix out of sync users with valid init.
  if (!$account && !variable_get('bakery_is_master', 0) && $cookie['master']) {
    $count = db_select('users', 'u')
      ->fields('u', array(
      'uid',
    ))
      ->condition('init', $cookie['init'])
      ->countQuery()
      ->execute()
      ->fetchField();
    if ($count > 1) {

      // Uh oh.
      watchdog('bakery', 'Account uniqueness problem: Multiple users found with init %init.', array(
        '%init' => $cookie['init'],
      ), WATCHDOG_ERROR);
      drupal_set_message(t('Account uniqueness problem detected. <a href="@contact">Please contact the site administrator.</a>', array(
        '@contact' => variable_get('bakery_master', 'http://drupal.org/') . 'contact',
      )), 'error');
    }
    if ($count == 1) {
      $account = user_load_multiple(array(), array(
        'init' => $cookie['init'],
      ));
      if (is_array($account)) {
        $account = reset($account);
      }
      if ($account) {
        watchdog('bakery', 'Fixing out of sync uid %uid. Changed name %name_old to %name_new, mail %mail_old to %mail_new.', array(
          '%uid' => $account->uid,
          '%name_old' => $account->name,
          '%name_new' => $cookie['name'],
          '%mail_old' => $account->mail,
          '%mail_new' => $cookie['mail'],
        ));
        user_save($account, array(
          'name' => $cookie['name'],
          'mail' => $cookie['mail'],
        ));
        $account = user_load_multiple(array(), array(
          'name' => $cookie['name'],
          'mail' => $cookie['mail'],
        ));
        $account = reset($account);
      }
    }
  }

  // Create the account if it doesn't exist.
  if (!$account && !variable_get('bakery_is_master', 0) && $cookie['master']) {

    // Check if existing account with same name, mail or init.
    if (_bakery_check_account($user->uid, $cookie)) {
      $account = bakery_create_account($cookie);
    }
    else {
      drupal_set_message(t('Your user account on %site appears to have problems. Would you like to try to <a href="@url">repair it yourself</a>?', array(
        '%site' => variable_get('site_name', 'Drupal'),
        '@url' => url('bakery/repair'),
      )));
      drupal_set_message(filter_xss_admin(variable_get('bakery_help_text', 'Otherwise you can contact the site administrators.')));
      $_SESSION['BAKERY_CRUMBLED'] = TRUE;
    }
  }
  if ($account && $cookie['master'] && $account->uid && !variable_get('bakery_is_master', 0) && $account->init != $cookie['init']) {

    // User existed previously but init is wrong. Fix it to ensure account
    // remains in sync.
    // Make sure that there aren't any OTHER accounts with this init already.
    $count = db_select('users', 'u')
      ->fields('u', array(
      'uid',
    ))
      ->condition('init', $cookie['init'], '=')
      ->countQuery()
      ->execute()
      ->fetchField();
    if ($count == 0) {
      db_update('users')
        ->fields(array(
        'init' => $cookie['init'],
      ))
        ->condition('uid', $account->uid)
        ->execute();
      watchdog('bakery', 'uid %uid out of sync. Changed init field from %oldinit to %newinit', array(
        '%oldinit' => $account->init,
        '%newinit' => $cookie['init'],
        '%uid' => $account->uid,
      ));
    }
    else {

      // Username and email matched, but init belonged to a DIFFERENT account.
      // Something got seriously tangled up.
      watchdog('bakery', 'Accounts mixed up! Username %user and init %init disagree with each other!', array(
        '%user' => $account->name,
        '%init' => $cookie['init'],
      ), WATCHDOG_CRITICAL);
    }
  }
  if ($account && $user->uid == 0) {

    // If the login attempt fails destroy the cookie to prevent infinite
    // redirects (with infinite failed login messages).
    $login = bakery_user_external_login($account);
    if ($login) {

      // If an anonymous user has just been logged in, trigger a 'refresh'
      // of the current page, ensuring that drupal_goto() does not override
      // the current page with the destination query.
      $query = drupal_get_query_parameters();
      unset($_GET['destination']);
      drupal_goto(current_path(), array(
        'query' => $query,
      ));
    }
  }
}