123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316 |
- <?php
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- namespace Magento\Integration\Model;
- use Magento\Customer\Api\AccountManagementInterface;
- use Magento\Framework\Exception\InputException;
- use Magento\Integration\Model\Oauth\Token as TokenModel;
- use Magento\TestFramework\Helper\Bootstrap;
- use Magento\TestFramework\TestCase\WebapiAbstract;
- use Magento\User\Model\User as UserModel;
- use Magento\Framework\Webapi\Exception as HTTPExceptionCodes;
- use Magento\Integration\Model\ResourceModel\Oauth\Token\CollectionFactory;
- use Magento\Integration\Model\Oauth\Token\RequestLog\Config as TokenThrottlerConfig;
- use Magento\Integration\Api\CustomerTokenServiceInterface;
- /**
- * api-functional test for \Magento\Integration\Model\CustomerTokenService.
- *
- * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
- */
- class CustomerTokenServiceTest extends WebapiAbstract
- {
- const SERVICE_NAME = "integrationCustomerTokenServiceV1";
- const SERVICE_VERSION = "V1";
- const RESOURCE_PATH_CUSTOMER_TOKEN = "/V1/integration/customer/token";
- /**
- * @var CustomerTokenServiceInterface
- */
- private $tokenService;
- /**
- * @var AccountManagementInterface
- */
- private $customerAccountManagement;
- /**
- * @var CollectionFactory
- */
- private $tokenCollection;
- /**
- * @var UserModel
- */
- private $userModel;
- /**
- * @var int
- */
- private $attemptsCountToLockAccount;
- /**
- * Setup CustomerTokenService
- */
- public function setUp()
- {
- $this->_markTestAsRestOnly();
- $this->tokenService = Bootstrap::getObjectManager()->get(
- \Magento\Integration\Model\CustomerTokenService::class
- );
- $this->customerAccountManagement = Bootstrap::getObjectManager()->get(
- \Magento\Customer\Api\AccountManagementInterface::class
- );
- $tokenCollectionFactory = Bootstrap::getObjectManager()->get(
- \Magento\Integration\Model\ResourceModel\Oauth\Token\CollectionFactory::class
- );
- $this->tokenCollection = $tokenCollectionFactory->create();
- $this->userModel = Bootstrap::getObjectManager()->get(\Magento\User\Model\User::class);
- /** @var TokenThrottlerConfig $tokenThrottlerConfig */
- $tokenThrottlerConfig = Bootstrap::getObjectManager()->get(TokenThrottlerConfig::class);
- $this->attemptsCountToLockAccount = $tokenThrottlerConfig->getMaxFailuresCount();
- }
- /**
- * @magentoApiDataFixture Magento/Customer/_files/customer.php
- */
- public function testCreateCustomerAccessToken()
- {
- $userName = 'customer@example.com';
- $password = 'password';
- $serviceInfo = [
- 'rest' => [
- 'resourcePath' => self::RESOURCE_PATH_CUSTOMER_TOKEN,
- 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST,
- ],
- ];
- $requestData = ['username' => $userName, 'password' => $password];
- $accessToken = $this->_webApiCall($serviceInfo, $requestData);
- $this->assertToken($accessToken, $userName, $password);
- }
- /**
- * @dataProvider validationDataProvider
- */
- public function testCreateCustomerAccessTokenEmptyOrNullCredentials($username, $password)
- {
- $noExceptionOccurred = false;
- try {
- $serviceInfo = [
- 'rest' => [
- 'resourcePath' => self::RESOURCE_PATH_CUSTOMER_TOKEN,
- 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST,
- ],
- ];
- $requestData = ['username' => $username, 'password' => $password];
- $this->_webApiCall($serviceInfo, $requestData);
- $noExceptionOccurred = true;
- } catch (\Exception $e) {
- $this->assertInputExceptionMessages($e);
- }
- if ($noExceptionOccurred) {
- $this->fail("Exception was expected to be thrown when provided credentials are invalid.");
- }
- }
- public function testCreateCustomerAccessTokenInvalidCustomer()
- {
- $customerUserName = 'invalid';
- $password = 'invalid';
- $noExceptionOccurred = false;
- try {
- $serviceInfo = [
- 'rest' => [
- 'resourcePath' => self::RESOURCE_PATH_CUSTOMER_TOKEN,
- 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST,
- ],
- ];
- $requestData = ['username' => $customerUserName, 'password' => $password];
- $this->_webApiCall($serviceInfo, $requestData);
- $noExceptionOccurred = true;
- } catch (\Exception $e) {
- $this->assertInvalidCredentialsException($e);
- }
- if ($noExceptionOccurred) {
- $this->fail("Exception was expected to be thrown when provided credentials are invalid.");
- }
- }
- /**
- * Provider to test input validation
- *
- * @return array
- */
- public function validationDataProvider()
- {
- return [
- 'Check for empty credentials' => ['', ''],
- 'Check for null credentials' => [null, null]
- ];
- }
- /**
- * Assert for presence of Input exception messages
- *
- * @param \Exception $e
- */
- private function assertInputExceptionMessages($e)
- {
- $this->assertEquals(HTTPExceptionCodes::HTTP_BAD_REQUEST, $e->getCode());
- $exceptionData = $this->processRestExceptionResult($e);
- $expectedExceptionData = [
- 'message' => 'One or more input exceptions have occurred.',
- 'errors' => [
- [
- 'message' => '"%fieldName" is required. Enter and try again.',
- 'parameters' => [
- 'fieldName' => 'username',
- ],
- ],
- [
- 'message' => '"%fieldName" is required. Enter and try again.',
- 'parameters' => [
- 'fieldName' => 'password',
- ]
- ],
- ],
- ];
- $this->assertEquals($expectedExceptionData, $exceptionData);
- }
- /**
- * @magentoApiDataFixture Magento/Customer/_files/customer.php
- */
- public function testThrottlingMaxAttempts()
- {
- $userNameFromFixture = 'customer@example.com';
- $passwordFromFixture = 'password';
- $serviceInfo = [
- 'rest' => [
- 'resourcePath' => self::RESOURCE_PATH_CUSTOMER_TOKEN,
- 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST,
- ],
- ];
- $invalidCredentials = [
- 'username' => $userNameFromFixture,
- 'password' => 'invalid',
- ];
- $validCredentials = [
- 'username' => $userNameFromFixture,
- 'password' => $passwordFromFixture,
- ];
- /* Try to get token using invalid credentials for 5 times (account is locked after 6 attempts) */
- $noExceptionOccurred = false;
- for ($i = 0; $i < ($this->attemptsCountToLockAccount - 1); $i++) {
- try {
- $this->_webApiCall($serviceInfo, $invalidCredentials);
- $noExceptionOccurred = true;
- } catch (\Exception $e) {
- }
- }
- if ($noExceptionOccurred) {
- $this->fail(
- "Precondition failed: exception should have occurred when token was requested with invalid credentials."
- );
- }
- /** On 6th attempt it still should be possible to get token if valid credentials are specified */
- $accessToken = $this->_webApiCall($serviceInfo, $validCredentials);
- $this->assertToken($accessToken, $userNameFromFixture, $passwordFromFixture);
- }
- /**
- * @magentoApiDataFixture Magento/Customer/_files/customer.php
- */
- public function testThrottlingAccountLockout()
- {
- $userNameFromFixture = 'customer@example.com';
- $passwordFromFixture = 'password';
- $serviceInfo = [
- 'rest' => [
- 'resourcePath' => self::RESOURCE_PATH_CUSTOMER_TOKEN,
- 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST,
- ],
- ];
- $invalidCredentials = [
- 'username' => $userNameFromFixture,
- 'password' => 'invalid',
- ];
- $validCredentials = [
- 'username' => $userNameFromFixture,
- 'password' => $passwordFromFixture,
- ];
- /* Try to get token using invalid credentials for 5 times (account would be locked after 6 attempts) */
- $noExceptionOccurred = false;
- for ($i = 0; $i < $this->attemptsCountToLockAccount; $i++) {
- try {
- $this->_webApiCall($serviceInfo, $invalidCredentials);
- $noExceptionOccurred = true;
- } catch (\Exception $e) {
- $this->assertInvalidCredentialsException($e);
- }
- if ($noExceptionOccurred) {
- $this->fail("Exception was expected to be thrown when provided credentials are invalid.");
- }
- }
- $noExceptionOccurred = false;
- try {
- $this->_webApiCall($serviceInfo, $validCredentials);
- $noExceptionOccurred = true;
- } catch (\Exception $e) {
- $this->assertInvalidCredentialsException($e);
- }
- if ($noExceptionOccurred) {
- $this->fail("Exception was expected to be thrown because account should have been locked at this point.");
- }
- }
- /**
- * Make sure that status code and message are correct in case of authentication failure.
- *
- * @param \Exception $e
- */
- private function assertInvalidCredentialsException($e)
- {
- $this->assertEquals(HTTPExceptionCodes::HTTP_UNAUTHORIZED, $e->getCode(), "Response HTTP code is invalid.");
- $exceptionData = $this->processRestExceptionResult($e);
- $expectedExceptionData = [
- 'message' => 'The account sign-in was incorrect or your account is disabled temporarily. '
- . 'Please wait and try again later.'
- ];
- $this->assertEquals($expectedExceptionData, $exceptionData, "Exception message is invalid.");
- }
- /**
- * Make sure provided token is valid and belongs to the specified user.
- *
- * @param string $accessToken
- * @param string $userName
- * @param string $password
- */
- private function assertToken($accessToken, $userName, $password)
- {
- $customerData = $this->customerAccountManagement->authenticate($userName, $password);
- /** @var $this ->tokenCollection \Magento\Integration\Model\ResourceModel\Oauth\Token\Collection */
- $this->tokenCollection->addFilterByCustomerId($customerData->getId());
- $isTokenCorrect = false;
- foreach ($this->tokenCollection->getItems() as $item) {
- /** @var $item TokenModel */
- if ($item->getToken() == $accessToken) {
- $isTokenCorrect = true;
- }
- }
- $this->assertTrue($isTokenCorrect);
- }
- }
|