You are here

class GALoginHotpSetup in Google Authenticator login 8

HOTP setup class to setup HOTP validation.

Plugin annotation


@TfaSetup(
  id = "ga_login_hotp_setup",
  label = @Translation("GA Login Hotp Setup"),
  description = @Translation("GA Login Hotp Setup Plugin"),
  helpLinks = {
   "Google Authenticator (Android/iPhone/BlackBerry)" = "https://support.google.com/accounts/answer/1066447?hl=en",
   "Authy (Android/iPhone)" = "http://authy.com/download/",
   "FreeOTP (Android)" = "https://play.google.com/store/apps/details?id=org.fedorahosted.freeotp",
   "GAuth Authenticator (desktop)" = "https://github.com/gbraad/html5-google-authenticator"
  },
  setupMessages = {
   "saved" = @Translation("Application code verified."),
   "skipped" = @Translation("Application codes not enabled.")
  }
)

Hierarchy

Expanded class hierarchy of GALoginHotpSetup

File

src/Plugin/TfaSetup/GALoginHotpSetup.php, line 38

Namespace

Drupal\ga_login\Plugin\TfaSetup
View source
class GALoginHotpSetup extends GALoginHotpValidation implements TfaSetupInterface {

  /**
   * Un-encrypted seed.
   *
   * @var string
   */
  protected $seed;

  /**
   * {@inheritdoc}
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, UserDataInterface $user_data, EncryptionProfileManagerInterface $encryption_profile_manager, EncryptServiceInterface $encrypt_service, ConfigFactoryInterface $config_factory, TimeInterface $time) {
    parent::__construct($configuration, $plugin_id, $plugin_definition, $user_data, $encryption_profile_manager, $encrypt_service, $config_factory, $time);

    // Generate seed.
    $this
      ->setSeed($this
      ->createSeed());
  }

  /**
   * {@inheritdoc}
   */
  public function getSetupForm(array $form, FormStateInterface $form_state) {
    $help_links = $this
      ->getHelpLinks();
    $items = [];
    foreach ($help_links as $item => $link) {
      $items[] = Link::fromTextAndUrl($item, Url::fromUri($link, [
        'attributes' => [
          'target' => '_blank',
        ],
      ]));
    }
    $form['apps'] = [
      '#theme' => 'item_list',
      '#items' => $items,
      '#title' => $this
        ->t('Install authentication code application on your mobile or desktop device:'),
    ];
    $form['info'] = [
      '#type' => 'html_tag',
      '#tag' => 'p',
      '#value' => $this
        ->t('The two-factor authentication application will be used during this setup and for generating codes during regular authentication. If the application supports it, scan the QR code below to get the setup code otherwise you can manually enter the text code.'),
    ];
    $form['seed'] = [
      '#type' => 'textfield',
      '#value' => $this->seed,
      '#disabled' => TRUE,
      '#description' => $this
        ->t('Enter this code into your two-factor authentication app or scan the QR code below.'),
    ];

    // QR image of seed.
    $form['qr_image'] = [
      '#prefix' => '<div class="ga-login-qr-code"',
      '#theme' => 'image',
      '#uri' => $this
        ->getQrCodeUri(),
      '#alt' => $this
        ->t('QR code for TFA setup'),
      '#suffix' => '</div>',
    ];

    // QR code css giving it a fixed width.
    $form['page']['#attached']['html_head'][] = [
      [
        '#tag' => 'style',
        '#value' => ".ga-login-qr-code { width:200px }",
      ],
      'qrcode-css',
    ];

    // Include code entry form.
    $form = $this
      ->getForm($form, $form_state);
    $form['actions']['login']['#value'] = $this
      ->t('Verify and save');

    // Alter code description.
    $form['code']['#description'] = $this
      ->t('A verification code will be generated after you scan the above QR code or manually enter the setup code. The verification code is six digits long.');
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateSetupForm(array $form, FormStateInterface $form_state) {
    if (!$this
      ->validate($form_state
      ->getValue('code'))) {
      $this->errorMessages['code'] = $this
        ->t('Invalid application code. Please try again.');
      return FALSE;
    }
    $this
      ->storeAcceptedCode($form_state
      ->getValue('code'));
    return TRUE;
  }

  /**
   * {@inheritdoc}
   */
  protected function validate($code) {

    // The counter is set as 1 because that is the initial value.
    // This ensures that things work even if we reset the application.
    $code = preg_replace('/\\s+/', '', $code);
    $counter = $this->auth->otp
      ->checkHotpResync(Encoding::base32DecodeUpper($this->seed), 1, $code, $this->counterWindow);
    $this
      ->setUserData('tfa', [
      'tfa_hotp_counter' => ++$counter,
    ], $this->uid, $this->userData);
    return (bool) $counter;
  }

  /**
   * {@inheritdoc}
   */
  public function submitSetupForm(array $form, FormStateInterface $form_state) {

    // Write seed for user.
    $this
      ->storeSeed($this->seed);
    return TRUE;
  }

  /**
   * Get a base64 qrcode image uri of seed.
   *
   * @return string
   *   QR-code uri.
   */
  protected function getQrCodeUri() {
    return (new QRCode())
      ->render('otpauth://hotp/' . $this
      ->accountName() . '?secret=' . $this->seed . '&counter=1&issuer=' . urlencode($this->issuer));
  }

  /**
   * Create OTP seed for account.
   *
   * @return string
   *   Un-encrypted seed.
   */
  protected function createSeed() {
    return $this->auth->ga
      ->generateRandom();
  }

  /**
   * Setter for OTP secret key.
   *
   * @param string $seed
   *   The OTP secret key.
   */
  public function setSeed($seed) {
    $this->seed = $seed;
  }

  /**
   * Get account name for QR image.
   *
   * @return string
   *   URL encoded string.
   */
  protected function accountName() {

    /** @var \Drupal\user\Entity\User $account */
    $account = User::load($this->configuration['uid']);
    $prefix = $this->siteNamePrefix ? preg_replace('@[^a-z0-9-]+@', '-', strtolower(\Drupal::config('system.site')
      ->get('name'))) : $this->namePrefix;
    return urlencode($prefix . '-' . $account
      ->getAccountName());
  }

  /**
   * {@inheritdoc}
   */
  public function getOverview(array $params) {
    $plugin_text = $this
      ->t('Validation Plugin: @plugin', [
      '@plugin' => str_replace(' Setup', '', $this
        ->getLabel()),
    ]);
    $output = [
      'heading' => [
        '#type' => 'html_tag',
        '#tag' => 'h2',
        '#value' => $this
          ->t('TFA application'),
      ],
      'validation_plugin' => [
        '#type' => 'markup',
        '#markup' => '<p>' . $plugin_text . '</p>',
      ],
      'description' => [
        '#type' => 'html_tag',
        '#tag' => 'p',
        '#value' => $this
          ->t('Generate verification codes from a mobile or desktop application.'),
      ],
      'link' => [
        '#theme' => 'links',
        '#links' => [
          'admin' => [
            'title' => !$params['enabled'] ? $this
              ->t('Set up application') : $this
              ->t('Reset application'),
            'url' => Url::fromRoute('tfa.validation.setup', [
              'user' => $params['account']
                ->id(),
              'method' => $params['plugin_id'],
            ]),
          ],
        ],
      ],
    ];
    return $output;
  }

  /**
   * {@inheritdoc}
   */
  public function getHelpLinks() {
    return $this->pluginDefinition['helpLinks'];
  }

  /**
   * {@inheritdoc}
   */
  public function getSetupMessages() {
    return $this->pluginDefinition['setupMessages'] ?: '';
  }

}

Members

Namesort descending Modifiers Type Description Overrides
DependencySerializationTrait::$_entityStorages protected property An array of entity type IDs keyed by the property name of their storages.
DependencySerializationTrait::$_serviceIds protected property An array of service IDs keyed by property name used for serialization.
DependencySerializationTrait::__sleep public function 1
DependencySerializationTrait::__wakeup public function 2
GALoginHotpSetup::$seed protected property Un-encrypted seed.
GALoginHotpSetup::accountName protected function Get account name for QR image.
GALoginHotpSetup::createSeed protected function Create OTP seed for account.
GALoginHotpSetup::getHelpLinks public function Returns a list of links containing helpful information for plugin use. Overrides TfaSetupInterface::getHelpLinks
GALoginHotpSetup::getOverview public function Plugin overview page. Overrides TfaSetupInterface::getOverview
GALoginHotpSetup::getQrCodeUri protected function Get a base64 qrcode image uri of seed.
GALoginHotpSetup::getSetupForm public function Get the setup form for the validation method. Overrides TfaSetupInterface::getSetupForm
GALoginHotpSetup::getSetupMessages public function Returns a list of messages for plugin step. Overrides TfaSetupInterface::getSetupMessages
GALoginHotpSetup::setSeed public function Setter for OTP secret key.
GALoginHotpSetup::submitSetupForm public function Submit the setup form. Overrides TfaSetupInterface::submitSetupForm
GALoginHotpSetup::validate protected function Validate code. Overrides GALoginHotpValidation::validate
GALoginHotpSetup::validateSetupForm public function Validate the setup data. Overrides TfaSetupInterface::validateSetupForm
GALoginHotpSetup::__construct public function Constructs a new Tfa plugin object. Overrides GALoginHotpValidation::__construct
GALoginHotpValidation::$alreadyAccepted protected property Whether the code has already been used or not. Overrides TfaBasePlugin::$alreadyAccepted
GALoginHotpValidation::$auth public property Object containing the external validation library.
GALoginHotpValidation::$counterWindow protected property The counter window in which the validation should be done.
GALoginHotpValidation::$issuer protected property Configurable name of the issuer.
GALoginHotpValidation::$namePrefix protected property Name prefix.
GALoginHotpValidation::$siteNamePrefix protected property Whether or not the prefix should use the site name.
GALoginHotpValidation::$time protected property The Datetime service.
GALoginHotpValidation::buildConfigurationForm public function The configuration form for this validation plugin.
GALoginHotpValidation::create public static function Creates an instance of the plugin. Overrides ContainerFactoryPluginInterface::create
GALoginHotpValidation::deleteSeed protected function Delete the seed of the current validated user.
GALoginHotpValidation::getForm public function Get TFA process form from plugin. Overrides TfaValidationInterface::getForm
GALoginHotpValidation::getHotpCounter public function Get the HOTP counter.
GALoginHotpValidation::getSeed protected function Get seed for this account.
GALoginHotpValidation::isAlreadyAccepted public function Returns whether code has already been used or not.
GALoginHotpValidation::ready public function Determine if the plugin can run for the current TFA context. Overrides TfaBasePlugin::ready
GALoginHotpValidation::storeSeed public function Save seed for account.
GALoginHotpValidation::validateForm public function Validate form. Overrides TfaValidationInterface::validateForm
GALoginHotpValidation::validateRequest public function Simple validate for web services.
PluginBase::$configuration protected property Configuration information passed into the plugin. 1
PluginBase::$pluginDefinition protected property The plugin implementation definition. 1
PluginBase::$pluginId protected property The plugin_id.
PluginBase::DERIVATIVE_SEPARATOR constant A string which is used to separate base plugin IDs from the derivative ID.
PluginBase::getBaseId public function Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface::getBaseId
PluginBase::getDerivativeId public function Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface::getDerivativeId
PluginBase::getPluginDefinition public function Gets the definition of the plugin implementation. Overrides PluginInspectionInterface::getPluginDefinition 3
PluginBase::getPluginId public function Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface::getPluginId
PluginBase::isConfigurable public function Determines if the plugin is configurable.
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.
TfaBasePlugin::$code protected property The user submitted code to be validated.
TfaBasePlugin::$codeLength protected property The allowed code length.
TfaBasePlugin::$encryptionProfile protected property Encryption profile.
TfaBasePlugin::$encryptService protected property Encryption service.
TfaBasePlugin::$errorMessages protected property The error for the current validation.
TfaBasePlugin::$isValid protected property Whether the validation succeeded or not.
TfaBasePlugin::$uid protected property The user id.
TfaBasePlugin::$userData protected property Provides the user data service object.
TfaBasePlugin::alreadyAcceptedCode protected function Whether code has already been used.
TfaBasePlugin::decrypt protected function Decrypt a encrypted string.
TfaBasePlugin::encrypt protected function Encrypt a plaintext string.
TfaBasePlugin::getErrorMessages public function Get error messages suitable for form_set_error().
TfaBasePlugin::getLabel public function Get the plugin label.
TfaBasePlugin::storeAcceptedCode protected function Store validated code to prevent replay attack.
TfaBasePlugin::submitForm public function Submit form. 1
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.