class OneTimeAuthentication

Same name and namespace in other branches
  1. main core/modules/user/src/OneTimeAuthentication.php \Drupal\user\OneTimeAuthentication

Generate and verify one time authentication codes.

One time authentication codes are used to build a unique and secure URL that is sent to the user by email for purposes such as resetting the user's password. The authentication code includes a timestamp, the user's last login time, the numeric user ID, the user's email address. This data is keyed by the users hashed password and the site's hash salt. All of this data is used to verify the authentication link whenever it is used.

Hierarchy

Expanded class hierarchy of OneTimeAuthentication

11 files declare their use of OneTimeAuthentication
OneTimeAuthenticationTest.php in core/modules/user/tests/src/Kernel/OneTimeAuthenticationTest.php
ServerCommand.php in core/lib/Drupal/Core/Command/ServerCommand.php
TestSiteUserLoginCommand.php in core/tests/Drupal/TestSite/Commands/TestSiteUserLoginCommand.php
UiHelperTrait.php in core/tests/Drupal/Tests/UiHelperTrait.php
user.module in core/modules/user/user.module

... See full list

File

core/modules/user/src/OneTimeAuthentication.php, line 24

Namespace

Drupal\user
View source
final readonly class OneTimeAuthentication {
  public function __construct(protected TimeInterface $time, protected LanguageManagerInterface $languageManager) {
  }
  
  /**
   * Create a one time authentication code.
   *
   * One time authentication codes are used to build a unique and secure URL
   * that is sent to the user by email for purposes such as resetting the user's
   * password.
   *
   * For a usage example, see
   * \Drupal\user\OneTimeAuthentication::generateCancelConfirmUrl() and
   * \Drupal\user\Controller\UserController::confirmCancel().
   *
   * @param \Drupal\user\UserInterface $account
   *   An object containing the user account.
   * @param int $timestamp
   *   A UNIX timestamp, typically \Drupal::time()->getRequestTime().
   *
   * @return string
   *   A string that is safe for use in URLs and SQL statements.
   */
  public function generateHmac(UserInterface $account, int $timestamp) : string {
    $data = $timestamp;
    $data .= ':' . $account->getLastLoginTime();
    $data .= ':' . $account->id();
    $data .= ':' . $account->getEmail();
    return Crypt::hmacBase64($data, Settings::getHashSalt() . $account->getPassword());
  }
  
  /**
   * Verify a one time authentication code and its timestamp.
   *
   * For a usage example, see
   * \Drupal\user\OneTimeAuthentication::generateCancelConfirmUrl() and
   * \Drupal\user\Controller\UserController::confirmCancel().
   *
   * @param \Drupal\user\UserInterface $account
   *   An account for which to verify the authentication code.
   * @param int $timestamp
   *   The timestamp of the authentication code.
   * @param string $hmac
   *   One time authentication code.
   * @param int $timeout
   *   Expiration timeout of authentication code.
   *
   * @return bool
   *   Whether the provided data are valid.
   */
  public function verifyHmac(UserInterface $account, int $timestamp, string $hmac, int $timeout = 0) : bool {
    $current = $this->time
      ->getRequestTime();
    $timeout_valid = !empty($timeout) && $current - $timestamp < $timeout || empty($timeout);
    return $timestamp >= $account->getLastLoginTime() && $timestamp <= $current && $timeout_valid && hash_equals($hmac, $this->generateHmac($account, $timestamp));
  }
  
  /**
   * Generates a unique URL for a user to log in and reset their password.
   *
   * @param \Drupal\user\UserInterface $account
   *   An object containing the user account.
   * @param array $options
   *   (optional) A keyed array of settings. Supported options are:
   *   - langcode: A language code to be used when generating locale-sensitive
   *     URLs. If langcode is NULL the users preferred language is used.
   * @param bool $immediate
   *   Whether or not to perform the login action immediately when the URL is
   *   opened. Defaults to false.
   */
  public function generateOneTimeLoginUrl(UserInterface $account, array $options = [], bool $immediate = FALSE) : Url {
    $timestamp = $this->time
      ->getCurrentTime();
    $langcode = $options['langcode'] ?? $account->getPreferredLangcode();
    $routeName = $immediate ? 'user.reset.login' : 'user.reset';
    return Url::fromRoute($routeName, [
      'uid' => $account->id(),
      'timestamp' => $timestamp,
      'hash' => $this->generateHmac($account, $timestamp),
    ], [
      'absolute' => TRUE,
      'language' => $this->languageManager
        ->getLanguage($langcode),
    ]);
  }
  
  /**
   * Generates a URL to confirm an account cancellation request.
   *
   * @param \Drupal\user\UserInterface $account
   *   The user account object.
   * @param array $options
   *   (optional) A keyed array of settings. Supported options are:
   *   - langcode: A language code to be used when generating locale-sensitive
   *     URLs. If langcode is NULL the users preferred language is used.
   *
   * @see ::tokens()
   * @see \Drupal\user\Controller\UserController::confirmCancel()
   */
  public function generateCancelConfirmUrl(UserInterface $account, array $options = []) : Url {
    $timestamp = $this->time
      ->getRequestTime();
    $langcode = $options['langcode'] ?? $account->getPreferredLangcode();
    return Url::fromRoute('user.cancel_confirm', [
      'user' => $account->id(),
      'timestamp' => $timestamp,
      'hashed_pass' => $this->generateHmac($account, $timestamp),
    ], [
      'absolute' => TRUE,
      'language' => $this->languageManager
        ->getLanguage($langcode),
    ]);
  }
  
  /**
   * Token callback to add unsafe tokens for user notifications.
   *
   * This function is used by \Drupal\Core\Utility\Token::replace() to set up
   * some additional tokens that can be used in notifications generated by
   * user_mail().
   *
   * @param array $replacements
   *   An associative array variable containing mappings from token names to
   *   values (for use with strtr()).
   * @param array $data
   *   An associative array of token replacement values. If the 'user' element
   *   exists, it must contain a user account.
   * @param array $options
   *   A keyed array of settings and flags to control the token replacement
   *   process. See \Drupal\Core\Utility\Token::replace().
   * @param \Drupal\Core\Render\BubbleableMetadata $bubbleableMetadata
   *   Target for adding metadata.
   *
   * @internal
   */
  public function tokens(&$replacements, $data, $options, BubbleableMetadata $bubbleableMetadata) : void {
    if (isset($data['user'])) {
      $oneTimeLoginUrl = $this->generateOneTimeLoginUrl($data['user'], $options)
        ->toString(TRUE);
      $bubbleableMetadata->addCacheableDependency($oneTimeLoginUrl);
      $replacements['[user:one-time-login-url]'] = $oneTimeLoginUrl->getGeneratedUrl();
      $cancelConfirmUrl = $this->generateCancelConfirmUrl($data['user'], $options)
        ->toString(TRUE);
      $bubbleableMetadata->addCacheableDependency($cancelConfirmUrl);
      $replacements['[user:cancel-url]'] = $cancelConfirmUrl->getGeneratedUrl();
    }
  }

}

Members

Title Sort descending Modifiers Object type Summary
OneTimeAuthentication::generateCancelConfirmUrl public function Generates a URL to confirm an account cancellation request.
OneTimeAuthentication::generateHmac public function Create a one time authentication code.
OneTimeAuthentication::generateOneTimeLoginUrl public function Generates a unique URL for a user to log in and reset their password.
OneTimeAuthentication::tokens public function Token callback to add unsafe tokens for user notifications.
OneTimeAuthentication::verifyHmac public function Verify a one time authentication code and its timestamp.
OneTimeAuthentication::__construct public function

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.