You are here

function saml_sp_drupal_login__saml_authenticate in SAML Service Provider 8.2

Same name and namespace in other branches
  1. 8.3 modules/saml_sp_drupal_login/saml_sp_drupal_login.module \saml_sp_drupal_login__saml_authenticate()
  2. 7.8 modules/saml_sp_drupal_login/saml_sp_drupal_login.module \saml_sp_drupal_login__saml_authenticate()
  3. 7 modules/saml_sp_drupal_login/saml_sp_drupal_login.module \saml_sp_drupal_login__saml_authenticate()
  4. 7.2 modules/saml_sp_drupal_login/saml_sp_drupal_login.module \saml_sp_drupal_login__saml_authenticate()
  5. 7.3 modules/saml_sp_drupal_login/saml_sp_drupal_login.module \saml_sp_drupal_login__saml_authenticate()
  6. 4.x modules/saml_sp_drupal_login/saml_sp_drupal_login.module \saml_sp_drupal_login__saml_authenticate()
  7. 3.x modules/saml_sp_drupal_login/saml_sp_drupal_login.module \saml_sp_drupal_login__saml_authenticate()

SAML authentication callback.

1 string reference to 'saml_sp_drupal_login__saml_authenticate'
SamlSPDrupalLoginController::initiate in modules/saml_sp_drupal_login/src/Controller/SamlSPDrupalLoginController.php
Initiate a SAML login for the given IdP

File

modules/saml_sp_drupal_login/saml_sp_drupal_login.module, line 149
SAML Drupal Login

Code

function saml_sp_drupal_login__saml_authenticate($is_valid, OneLogin_Saml2_Response $saml_response, Idp $idp) {
  if ($is_valid) {
    $attributes = $saml_response
      ->getAttributes();

    // Default language English
    $language = 'en';

    // If language attribute is set on IdP, then use that language
    if (isset($attributes['language'])) {
      $language = $attributes['language'][0];
    }

    // Get the NameID value from response
    $name_id = $saml_response
      ->getNameId();
    if (\Drupal::config('saml_sp.settings')
      ->get('debug')) {
      drupal_set_message(t('Response NameId: @nameid', [
        '@nameid' => $name_id,
      ]));
    }

    // If email address is not used to identify user,
    // it has to be in the attributes
    if ($idp->nameid_field != 'mail') {

      // Try to get email from SAML response attributes
      try {
        $email = $attributes['mail'][0];
      } catch (Exception $e) {
        \Drupal::logger('saml_sp')
          ->error('No mail attribute available, please check IdP configuration, %exception', array(
          '%exception' => $e->message,
        ));
      }
    }
    else {
      $email = $saml_response
        ->getNameId();
    }
    if ($account = saml_sp_drupal_login_get_uid($name_id, $idp->nameid_field, $email)) {
      user_login_finalize($account);
      return new RedirectResponse(\Drupal::url('<front>'));

      // TODO make the following work as expected and allow the code to be processed
      // Update email address if it has changed on IdP
      if (\Drupal::config('saml_sp_drupal_login.config')
        ->get('update_email') && $account->mail != $email) {
        \Drupal::logger('saml_sp')
          ->notice('Updating email address from %old_email to %new_email for UID %uid', array(
          '%old_email' => $account->mail,
          '%new_email' => $email,
          '%uid' => $account->uid,
        ));
        $wrapper = entity_metadata_wrapper('user', $account);
        $wrapper->mail
          ->set($email);
        $wrapper
          ->save();

        // Showing message for user about the update which happened on IdP
        $message = t('Your email address is now @new_email', array(
          '@new_email' => $email,
        ));
        drupal_set_message($message);
      }

      // Update language if it has changed on IdP
      if (\Drupal::config('saml_sp_drupal_login.config')
        ->get('update_language') && $account->language != $language) {
        \Drupal::logger('saml_sp')
          ->notice('Updating language from %old_lang to %new_lang for UID %uid', array(
          '%old_lang' => $account->language,
          '%new_lang' => $language,
          '%uid' => $account->uid,
        ));
        $wrapper = entity_metadata_wrapper('user', $account);
        $wrapper->language
          ->set($language);
        $wrapper
          ->save();
      }
    }
    else {
      if (\Drupal::config('user.settings')
        ->get('register') != \Drupal\user\UserInterface::REGISTER_ADMINISTRATORS_ONLY) {

        // New user, register.
        $language = \Drupal::languageManager()
          ->getCurrentLanguage()
          ->getId();
        $user = \Drupal\user\Entity\User::create();

        // Mandatory.
        $user
          ->setPassword('password');
        $user
          ->enforceIsNew();
        $user
          ->setEmail($email);
        $user
          ->setUsername($email);

        // Optional.
        $user
          ->set('init', $email);
        $user
          ->set('langcode', $language);
        $user
          ->set('preferred_langcode', $language);
        $user
          ->set('preferred_admin_langcode', $language);

        //$user->set('setting_name', 'setting_value');

        //$user->addRole('rid');
        $user
          ->activate();

        // Save user account.
        $result = $user
          ->save();
        \Drupal::logger('saml_sp')
          ->notice('New SSO user account for %mail with UID %uid', array(
          '%mail' => $email,
          '%uid' => $user->iddebt,
        ));
      }
      else {
        if (\Drupal::config('saml_sp_drupal_login.config')
          ->get('no_account_authenticated_user_role') && \Drupal::config('saml_sp_drupal_login.config')
          ->get('no_account_authenticated_user_account')) {

          // the user has no account but the setting allows for them to get an authenticated role
          $account = user_load_by_name(\Drupal::config('saml_sp_drupal_login.config')
            ->get('no_account_authenticated_user_account'));
        }
        else {

          // only Administrators can register new users
          $tokens = array(
            '%mail' => $email,
            '%idp_label' => $idp->label,
            '@account_request_url' => \Drupal\Core\Url::fromRoute('user.register', array(
              'query' => array(
                'email' => $email,
              ),
            ))
              ->toString(),
          );
          $no_account_message = t('No account matching %mail has been found. Please contact a site administrator.', $tokens);
          $user_may_request_account_message = t('No account matching %mail has been found. <a href="@account_request_url">Click here to apply for an account.</a>', $tokens);
          if (\Drupal::config('saml_sp_drupal_login.config')
            ->get('request_account')) {
            $no_account_message = $user_may_request_account_message;
          }
          drupal_set_message($no_account_message, 'warning');
          \Drupal::logger('saml_sp')
            ->warning('User attempting to login through %idp_label with %mail which doesn\'t match any accounts.', $tokens);
          return FALSE;
        }
      }
    }

    // @see user_login_name_validate().
    if (user_is_blocked($account
      ->getAccountName())) {
      drupal_set_message(t('The username %name has not been activated or is blocked.', array(
        '%name' => $account
          ->getAccountName(),
      )));
      if (\Drupal::config('saml_sp.settings')
        ->get('debug')) {
        if (\Drupal::moduleHandler()
          ->moduleExists('devel')) {
          dpm($account, '$account');
        }
        else {
          drupal_set_message('$account => <pre>' . print_r($account, TRUE) . '</pre>');
        }
        drupal_set_message(t('Response NameId: @nameid', [
          '@nameid' => $name_id,
        ]));
      }
      return FALSE;
    }

    // Reset any flood control.
    // @see user_login_final_validate().
    if (variable_get('user_failed_login_identifier_uid_only', FALSE)) {
      $identifier = $account->uid;
    }
    else {
      $identifier = $account->uid . '-' . ip_address();
    }

    /*
        $flood = \Drupal::flood();
        flood_clear_event('failed_login_attempt_user', $identifier);
    */

    // @see user_login_submit().
    global $user;
    $user = user_load($account->uid);
    $edit = array();

    // Adding redirect path to where user started the login from
    $edit['redirect'] = $_POST['RelayState'];
    \Drupal::logger('saml_sp')
      ->notice('User %name logging in through SAML via %idp_name. with NameID %mail', array(
      '%name' => $user->name,
      '%idp_name' => $idp->name,
      '%mail' => $email,
    ));

    // Store the fact that the user logged in via the SAML SP module.
    $_SESSION['authenticated_via_saml_sp'] = TRUE;
    user_login_finalize($edit);
  }
  return new RedirectResponse(\Drupal::url('<front>'));
}