From 9a3534ea2b9705b3fa4eb3ff7b71a856e4e882df Mon Sep 17 00:00:00 2001 From: ErickSkrauch Date: Mon, 8 Mar 2021 11:26:47 +0100 Subject: [PATCH] Add totp field for Minecraft auth protocol to login into accounts, protected with 2FA [deploy] --- .../authserver/models/AuthenticationForm.php | 7 +++++++ .../functional/authserver/AuthorizationCest.php | 17 +++++++++++++++++ .../models/AuthenticationFormTest.php | 14 ++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/api/modules/authserver/models/AuthenticationForm.php b/api/modules/authserver/models/AuthenticationForm.php index e17056e..e6775c9 100644 --- a/api/modules/authserver/models/AuthenticationForm.php +++ b/api/modules/authserver/models/AuthenticationForm.php @@ -29,6 +29,11 @@ class AuthenticationForm extends ApiForm { */ public $password; + /** + * @var string + */ + public $totp; + /** * @var string */ @@ -42,6 +47,7 @@ class AuthenticationForm extends ApiForm { public function rules(): array { return [ [['username', 'password', 'clientToken'], RequiredValidator::class], + [['totp'], 'string'], [['clientToken'], ClientTokenValidator::class], [['requestUser'], 'boolean'], ]; @@ -65,6 +71,7 @@ class AuthenticationForm extends ApiForm { $loginForm = new LoginForm(); $loginForm->login = $this->username; $loginForm->password = $this->password; + $loginForm->totp = $this->totp; if (!$loginForm->validate() || $loginForm->getAccount()->status === Account::STATUS_DELETED) { $errors = $loginForm->getFirstErrors(); if (isset($errors['totp'])) { diff --git a/api/tests/functional/authserver/AuthorizationCest.php b/api/tests/functional/authserver/AuthorizationCest.php index 31a44fe..65cd480 100644 --- a/api/tests/functional/authserver/AuthorizationCest.php +++ b/api/tests/functional/authserver/AuthorizationCest.php @@ -5,6 +5,7 @@ namespace api\tests\functional\authserver; use api\tests\FunctionalTester; use Codeception\Example; +use OTPHP\TOTP; use Ramsey\Uuid\Uuid; class AuthorizationCest { @@ -91,6 +92,22 @@ class AuthorizationCest { ]); } + public function byEmailWithEnabledTwoFactorAuthAndCorrectToken(FunctionalTester $I) { + $I->sendPOST('/api/authserver/authentication/authenticate', [ + 'username' => 'otp@gmail.com', + 'password' => 'password_0', + 'totp' => TOTP::create('BBBB')->now(), + 'clientToken' => Uuid::uuid4()->toString(), + ]); + $I->canSeeResponseCodeIs(200); + $I->canSeeResponseContainsJson([ + 'selectedProfile' => [ + 'id' => '15d0afa7a2bb44d39f31964cbccc6043', + 'name' => 'AccountWithEnabledOtp', + ], + ]); + } + public function tooLongClientToken(FunctionalTester $I) { $I->wantTo('send non uuid clientToken with more then 255 characters length'); $I->sendPOST('/api/authserver/authentication/authenticate', [ diff --git a/api/tests/unit/modules/authserver/models/AuthenticationFormTest.php b/api/tests/unit/modules/authserver/models/AuthenticationFormTest.php index ec4317a..1fa674c 100644 --- a/api/tests/unit/modules/authserver/models/AuthenticationFormTest.php +++ b/api/tests/unit/modules/authserver/models/AuthenticationFormTest.php @@ -10,6 +10,7 @@ use common\models\OauthClient; use common\models\OauthSession; use common\tests\fixtures\AccountFixture; use common\tests\fixtures\OauthClientFixture; +use OTPHP\TOTP; use Ramsey\Uuid\Uuid; class AuthenticationFormTest extends TestCase { @@ -51,6 +52,19 @@ class AuthenticationFormTest extends TestCase { ], $result['user']); } + public function testAuthenticateByValidCredentialsWith2FA() { + $authForm = new AuthenticationForm(); + $authForm->username = 'otp@gmail.com'; + $authForm->password = 'password_0'; + $authForm->totp = TOTP::create('BBBB')->now(); + $authForm->clientToken = Uuid::uuid4()->toString(); + + // Just ensure that there is no exception + $this->expectNotToPerformAssertions(); + + $authForm->authenticate(); + } + /** * @dataProvider getInvalidCredentialsCases */