You are here

class TfaContext in Two-factor Authentication (TFA) 8

Provide context for the current login attempt.

This class collects data needed to decide whether TFA is required and, if so, whether it is successful. This includes configuration of the module, the current request, and the user that is attempting to log in.

Hierarchy

Expanded class hierarchy of TfaContext

2 files declare their use of TfaContext
TfaContextTest.php in tests/src/Unit/TfaContextTest.php
TfaLoginForm.php in src/Form/TfaLoginForm.php

File

src/TfaContext.php, line 17

Namespace

Drupal\tfa
View source
class TfaContext implements TfaContextInterface {

  // Access to user's TFA settings.
  use TfaDataTrait;

  // Provides the getLoginHash() method.
  use TfaLoginTrait;

  /**
   * Validation plugin manager.
   *
   * @var \Drupal\tfa\TfaValidationPluginManager
   */
  protected $tfaValidationManager;

  /**
   * Login plugin manager.
   *
   * @var \Drupal\tfa\TfaLoginPluginManager
   */
  protected $tfaLoginManager;

  /**
   * The current validation plugin id being used by this context instance.
   *
   * @var string
   */
  protected $validationPluginName;

  /**
   * The tfaValidation plugin.
   *
   * @var \Drupal\tfa\Plugin\TfaValidationInterface|null
   */
  protected $tfaValidationPlugin;

  /**
   * Tfa settings config object.
   *
   * @var \Drupal\Core\Config\ImmutableConfig
   */
  protected $tfaSettings;

  /**
   * Entity for the user that is attempting to login.
   *
   * @var \Drupal\user\UserInterface
   */
  protected $user;

  /**
   * User data service.
   *
   * @var \Drupal\user\UserDataInterface
   */
  protected $userData;

  /**
   * Current request object.
   *
   * @var \Symfony\Component\HttpFoundation\Request
   */
  protected $request;

  /**
   * Array of login plugins for a given user.
   *
   * @var \Drupal\tfa\Plugin\TfaLoginInterface[]
   */
  protected $userLoginPlugins;

  /**
   * Array of login plugins.
   *
   * @var \Drupal\tfa\Plugin\TfaLoginInterface[]
   */
  protected $tfaLoginPlugins;

  /**
   * {@inheritdoc}
   */
  public function __construct(TfaValidationPluginManager $tfa_validation_manager, TfaLoginPluginManager $tfa_plugin_manager, ConfigFactoryInterface $config_factory, UserInterface $user, UserDataInterface $user_data, Request $request) {
    $this->tfaValidationManager = $tfa_validation_manager;
    $this->tfaLoginManager = $tfa_plugin_manager;
    $this->tfaSettings = $config_factory
      ->get('tfa.settings');
    $this->user = $user;
    $this->userData = $user_data;
    $this->request = $request;
    $this->tfaLoginPlugins = $this->tfaLoginManager
      ->getPlugins([
      'uid' => $user
        ->id(),
    ]);

    // If possible, set up an instance of tfaValidationPlugin and the user's
    // list of plugins.
    $this->validationPluginName = $this->tfaSettings
      ->get('default_validation_plugin');
    if (!empty($this->validationPluginName)) {
      $this->tfaValidationPlugin = $this->tfaValidationManager
        ->createInstance($this->validationPluginName, [
        'uid' => $user
          ->id(),
      ]);
      $this->userLoginPlugins = $this->tfaLoginManager
        ->getPlugins([
        'uid' => $user
          ->id(),
      ]);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function getUser() {
    return $this->user;
  }

  /**
   * {@inheritdoc}
   */
  public function isModuleSetup() {
    return intval($this->tfaSettings
      ->get('enabled')) && !empty($this->validationPluginName);
  }

  /**
   * {@inheritdoc}
   */
  public function isTfaRequired() {

    // If TFA has been set up for the user, then it is required.
    $user_tfa_data = $this
      ->tfaGetTfaData($this
      ->getUser()
      ->id(), $this->userData);
    if (!empty($user_tfa_data['status']) && !empty($user_tfa_data['data']['plugins'])) {
      return TRUE;
    }

    // If the user has a role that is required to use TFA, then return TRUE.
    $required_roles = array_filter($this->tfaSettings
      ->get('required_roles'));
    $user_roles = $this
      ->getUser()
      ->getRoles();
    return (bool) array_intersect($required_roles, $user_roles);
  }

  /**
   * {@inheritdoc}
   */
  public function isReady() {
    return isset($this->tfaValidationPlugin) && $this->tfaValidationPlugin
      ->ready();
  }

  /**
   * {@inheritdoc}
   */
  public function remainingSkips() {
    $allowed_skips = intval($this->tfaSettings
      ->get('validation_skip'));

    // Skipping TFA setup is not allowed.
    if (!$allowed_skips) {
      return FALSE;
    }
    $user_tfa_data = $this
      ->tfaGetTfaData($this
      ->getUser()
      ->id(), $this->userData);
    $validation_skipped = isset($user_tfa_data['validation_skipped']) ? $user_tfa_data['validation_skipped'] : 0;
    return max(0, $allowed_skips - $validation_skipped);
  }

  /**
   * {@inheritdoc}
   */
  public function hasSkipped() {
    $user_tfa_data = $this
      ->tfaGetTfaData($this
      ->getUser()
      ->id(), $this->userData);
    $validation_skipped = isset($user_tfa_data['validation_skipped']) ? $user_tfa_data['validation_skipped'] : 0;
    $user_tfa_data['validation_skipped'] = $validation_skipped + 1;
    $this
      ->tfaSaveTfaData($this
      ->getUser()
      ->id(), $this->userData, $user_tfa_data);
  }

  /**
   * {@inheritdoc}
   */
  public function pluginAllowsLogin() {
    if (!empty($this->tfaLoginPlugins)) {
      foreach ($this->tfaLoginPlugins as $plugin) {
        if ($plugin
          ->loginAllowed()) {
          return TRUE;
        }
      }
    }
    return FALSE;
  }

  /**
   * {@inheritdoc}
   *
   * @todo Set a hash mark to indicate TFA authorization has passed.
   */
  public function doUserLogin() {
    user_login_finalize($this
      ->getUser());
  }

}

Members

Namesort descending Modifiers Type Description Overrides
TfaContext::$request protected property Current request object.
TfaContext::$tfaLoginManager protected property Login plugin manager.
TfaContext::$tfaLoginPlugins protected property Array of login plugins.
TfaContext::$tfaSettings protected property Tfa settings config object.
TfaContext::$tfaValidationManager protected property Validation plugin manager.
TfaContext::$tfaValidationPlugin protected property The tfaValidation plugin.
TfaContext::$user protected property Entity for the user that is attempting to login.
TfaContext::$userData protected property User data service.
TfaContext::$userLoginPlugins protected property Array of login plugins for a given user.
TfaContext::$validationPluginName protected property The current validation plugin id being used by this context instance.
TfaContext::doUserLogin public function @todo Set a hash mark to indicate TFA authorization has passed. Overrides TfaContextInterface::doUserLogin
TfaContext::getUser public function Get the user object. Overrides TfaContextInterface::getUser
TfaContext::hasSkipped public function Increment the count of $this->getUser() logins without setting up TFA. Overrides TfaContextInterface::hasSkipped
TfaContext::isModuleSetup public function Is TFA enabled and configured? Overrides TfaContextInterface::isModuleSetup
TfaContext::isReady public function Check whether the Validation Plugin is set and ready for use. Overrides TfaContextInterface::isReady
TfaContext::isTfaRequired public function Check whether $this->getUser() is required to use TFA. Overrides TfaContextInterface::isTfaRequired
TfaContext::pluginAllowsLogin public function Whether at least one plugin allows authentication. Overrides TfaContextInterface::pluginAllowsLogin
TfaContext::remainingSkips public function Remaining number of allowed logins without setting up TFA. Overrides TfaContextInterface::remainingSkips
TfaContext::__construct public function TfaContextInterface constructor. Overrides TfaContextInterface::__construct
TfaDataTrait::deleteUserData protected function Deletes data stored for the current validated user account.
TfaDataTrait::getUserData protected function Returns data stored for the current validated user account.
TfaDataTrait::setUserData protected function Store user specific information.
TfaDataTrait::tfaGetTfaData protected function Get TFA data for an account.
TfaDataTrait::tfaSaveTfaData public function Save TFA data for an account.
TfaLoginTrait::getLoginHash protected function Generate a hash that can uniquely identify an account's state.