View source
<?php
namespace Drupal\Tests\ga_login\Functional;
use Drupal\Tests\tfa\Functional\TfaTestBase;
use Drupal\tfa\TfaDataTrait;
use Drupal\tfa\TfaLoginTrait;
use ParagonIE\ConstantTime\Encoding;
class GALoginTotpValidationPluginTest extends TfaTestBase {
use TfaLoginTrait;
use TfaDataTrait;
public $userAccount;
public $validationPluginId = 'ga_login_totp';
public $validationPlugin;
public $seed;
public static $modules = [
'tfa',
'encrypt',
'encrypt_test',
'key',
'ga_login',
];
public function setUp() {
parent::setUp();
$this
->canEnableValidationPlugin($this->validationPluginId);
$this->userAccount = $this
->drupalCreateUser([
'setup own tfa',
'disable own tfa',
]);
$this->validationPlugin = \Drupal::service('plugin.manager.tfa.validation')
->createInstance($this->validationPluginId, [
'uid' => $this->userAccount
->id(),
]);
$this
->drupalLogin($this->userAccount);
$this
->setupUserTotp();
$this
->drupalLogout();
}
public function setupUserTotp() {
$edit = [
'current_pass' => $this->userAccount->passRaw,
];
$this
->drupalPostForm('user/' . $this->userAccount
->id() . '/security/tfa/' . $this->validationPluginId, $edit, 'Confirm');
$result = $this
->xpath('//input[@name="seed"]');
if (empty($result)) {
$this
->fail('Unable to extract seed from page. Aborting test.');
return;
}
$this->seed = $result[0]
->getValue();
$this->validationPlugin
->storeSeed($this->seed);
$edit = [
'code' => $this->validationPlugin->auth->otp
->totp(Encoding::base32DecodeUpper($this->seed)),
];
$this
->drupalPostForm(NULL, $edit, 'Verify and save');
$this
->assertSession()
->linkExists('Disable TFA');
}
public function testTotpLogin() {
$assert = $this
->assertSession();
$edit = [
'name' => $this->userAccount
->getAccountName(),
'pass' => $this->userAccount->passRaw,
];
$this
->drupalPostForm('user/login', $edit, 'Log in');
$assert
->statusCodeEquals(200);
$assert
->pageTextContains('Verification code is application generated and 6 digits long.');
$edit = [
'code' => 112233,
];
$this
->drupalPostForm(NULL, $edit, 'Verify');
$assert
->statusCodeEquals(200);
$assert
->pageTextContains('Invalid application code. Please try again.');
$this->validationPlugin->auth->otp
->setTotpOffset(-1800);
$old_code = $this->validationPlugin->auth->otp
->totp(Encoding::base32DecodeUpper($this->seed));
$edit = [
'code' => $old_code,
];
$this
->drupalPostForm(NULL, $edit, 'Verify');
$assert
->statusCodeEquals(200);
$assert
->pageTextContains('Invalid application code. Please try again.');
$this->validationPlugin->auth->otp
->setTotpOffset($this->validationPlugin
->getTimeSkew() * 30);
$valid_code = $this->validationPlugin->auth->otp
->totp(Encoding::base32DecodeUpper($this->seed));
$edit = [
'code' => $valid_code,
];
$this
->drupalPostForm(NULL, $edit, 'Verify');
$assert
->statusCodeEquals(200);
$assert
->pageTextContains($this->userAccount
->getDisplayName());
$this
->drupalLogout();
$edit = [
'name' => $this->userAccount
->getAccountName(),
'pass' => $this->userAccount->passRaw,
];
$this
->drupalPostForm('user/login', $edit, 'Log in');
$assert
->statusCodeEquals(200);
$assert
->pageTextContains('Verification code is application generated and 6 digits long.');
$edit = [
'code' => $valid_code,
];
$this
->drupalPostForm(NULL, $edit, 'Verify');
$assert
->statusCodeEquals(200);
$assert
->pageTextContains('Invalid code, it was recently used for a login. Please try a new code.');
}
}