Skip to content

Commit 8da0e80

Browse files
author
ogorkun
committed
MC-32830: Do not store admin and customer tokens in DB
1 parent 04225f2 commit 8da0e80

File tree

7 files changed

+459
-4
lines changed

7 files changed

+459
-4
lines changed

app/code/Magento/JwtUserToken/Model/ConfigurableJwtSettingsProvider.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ public function __construct(
5757
$this->configReader = $configReader;
5858
}
5959

60+
/**
61+
* @inheritDoc
62+
*/
6063
public function prepareSettingsFor(UserContextInterface $userContext): EncryptionSettingsInterface
6164
{
6265
return $this->prepareAllAccepted()[0];

app/code/Magento/JwtUserToken/Model/Data/JwtTokenParameters.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,17 @@ class JwtTokenParameters
1919
/**
2020
* @var HeaderParameterInterface[]
2121
*/
22-
private $protectedHeaderParameters;
22+
private $protectedHeaderParameters = [];
2323

2424
/**
2525
* @var HeaderParameterInterface[]
2626
*/
27-
private $publicHeaderParameters;
27+
private $publicHeaderParameters = [];
2828

2929
/**
3030
* @var ClaimInterface[]
3131
*/
32-
private $claims;
32+
private $claims = [];
3333

3434
/**
3535
* @return HeaderParameterInterface[]

app/code/Magento/JwtUserToken/Model/ResourceModel/FastStorageRevokedWrapper.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,9 @@ private function cacheData(Revoked $revoked): void
8888
}
8989
$this->cache->save(
9090
(string) $revoked->getBeforeTimestamp(),
91-
sprintf(self::CACHE_ID, $revoked->getUserTypeId(), $revoked->getUserId())
91+
sprintf(self::CACHE_ID, $revoked->getUserTypeId(), $revoked->getUserId()),
92+
[],
93+
$ttlMin * 60
9294
);
9395
}
9496
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\JwtUserToken\Api;
10+
11+
use Magento\Authorization\Model\UserContextInterface;
12+
use Magento\JwtUserToken\Api\Data\Revoked;
13+
use Magento\TestFramework\Helper\Bootstrap;
14+
use PHPUnit\Framework\TestCase;
15+
16+
class RevokedRepositoryTest extends TestCase
17+
{
18+
/**
19+
* @var RevokedRepositoryInterface
20+
*/
21+
private $model;
22+
23+
/**
24+
* @inheritDoc
25+
*/
26+
protected function setUp(): void
27+
{
28+
parent::setUp();
29+
30+
$objectManager = Bootstrap::getObjectManager();
31+
32+
$this->model = $objectManager->get(RevokedRepositoryInterface::class);
33+
}
34+
35+
public function testSave(): void
36+
{
37+
$id = 169691;
38+
$type = UserContextInterface::USER_TYPE_CUSTOMER;
39+
$ts = time();
40+
41+
$this->model->saveRevoked(new Revoked($type, $id, $ts));
42+
43+
$found = $this->model->findRevoked($type, $id);
44+
$this->assertNotNull($found);
45+
$this->assertEquals($ts, $found->getBeforeTimestamp());
46+
}
47+
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\JwtUserToken\Model;
10+
11+
use Magento\Authorization\Model\UserContextInterface;
12+
use Magento\Customer\Api\CustomerRepositoryInterface;
13+
use Magento\Framework\Jwt\Claim\PrivateClaim;
14+
use Magento\JwtUserToken\Model\Data\JwtTokenParameters;
15+
use Magento\JwtUserToken\Model\Data\JwtUserContext;
16+
use Magento\TestFramework\Helper\Bootstrap;
17+
use Magento\User\Model\User as UserModel;
18+
use PHPUnit\Framework\TestCase;
19+
use Magento\Integration\Api\Data\UserTokenParametersInterface;
20+
use Magento\Integration\Api\Data\UserTokenParametersInterfaceFactory;
21+
22+
class IssuerTest extends TestCase
23+
{
24+
/**
25+
* @var Issuer
26+
*/
27+
private $model;
28+
29+
/**
30+
* @var CustomerRepositoryInterface
31+
*/
32+
private $customerRepo;
33+
34+
/**
35+
* @var UserModel
36+
*/
37+
private $userModel;
38+
39+
/**
40+
* @var UserTokenParametersInterfaceFactory
41+
*/
42+
private $paramsFactory;
43+
44+
/**
45+
* @inheritDoc
46+
*/
47+
protected function setUp(): void
48+
{
49+
parent::setUp();
50+
51+
$objectManager = Bootstrap::getObjectManager();
52+
53+
$this->model = $objectManager->get(Issuer::class);
54+
$this->customerRepo = $objectManager->get(CustomerRepositoryInterface::class);
55+
$this->userModel = $objectManager->create(UserModel::class);
56+
$this->paramsFactory = $objectManager->get(UserTokenParametersInterfaceFactory::class);
57+
}
58+
59+
/**
60+
* Verify that a token can be issued for a customer.
61+
*
62+
* @return void
63+
* @throws \Throwable
64+
* @magentoDataFixture Magento/Customer/_files/customer.php
65+
*/
66+
public function testIssueForCustomer(): void
67+
{
68+
$customer = $this->customerRepo->get('[email protected]');
69+
/** @var UserTokenParametersInterface $params */
70+
$params = $this->paramsFactory->create();
71+
$jwtParams = new JwtTokenParameters();
72+
$jwtParams->setClaims([new PrivateClaim('custom-claim', 'value')]);
73+
$params->getExtensionAttributes()->setJwtParams($jwtParams);
74+
$token = $this->model->create(
75+
new JwtUserContext((int) $customer->getId(), UserContextInterface::USER_TYPE_CUSTOMER),
76+
$params
77+
);
78+
79+
$this->assertNotEmpty($token);
80+
}
81+
82+
/**
83+
* Verify that a token can be issued for an admin user.
84+
*
85+
* @return void
86+
* @throws \Throwable
87+
* @magentoDataFixture Magento/User/_files/user_with_role.php
88+
*/
89+
public function testIssueForAdmin(): void
90+
{
91+
$admin = $this->userModel->loadByUsername('adminUser');
92+
/** @var UserTokenParametersInterface $params */
93+
$params = $this->paramsFactory->create();
94+
$token = $this->model->create(
95+
new JwtUserContext((int) $admin->getId(), UserContextInterface::USER_TYPE_ADMIN),
96+
$params
97+
);
98+
99+
$this->assertNotEmpty($token);
100+
}
101+
}
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\JwtUserToken\Model;
10+
11+
use Magento\Authorization\Model\UserContextInterface;
12+
use Magento\Customer\Api\CustomerRepositoryInterface;
13+
use Magento\Framework\App\Config\MutableScopeConfigInterface;
14+
use Magento\Framework\Jwt\Claim\PrivateClaim;
15+
use Magento\Framework\Jwt\Header\PrivateHeaderParameter;
16+
use Magento\Framework\Jwt\Jwe\JweEncryptionSettingsInterface;
17+
use Magento\Framework\Jwt\Jwk;
18+
use Magento\Framework\Jwt\Jws\JwsInterface;
19+
use Magento\JwtUserToken\Api\ConfigReaderInterface;
20+
use Magento\JwtUserToken\Api\Data\JwtTokenDataInterface;
21+
use Magento\JwtUserToken\Model\Config\ConfigReader;
22+
use Magento\JwtUserToken\Model\Data\JwtTokenParameters;
23+
use Magento\JwtUserToken\Model\Data\JwtUserContext;
24+
use Magento\TestFramework\Helper\Bootstrap;
25+
use Magento\TestFramework\ObjectManager;
26+
use Magento\User\Model\User as UserModel;
27+
use PHPUnit\Framework\TestCase;
28+
use Magento\Integration\Api\Data\UserTokenParametersInterface;
29+
use Magento\Integration\Api\Data\UserTokenParametersInterfaceFactory;
30+
31+
class ReaderTest extends TestCase
32+
{
33+
/**
34+
* @var Reader
35+
*/
36+
private $model;
37+
38+
/**
39+
* @var Issuer
40+
*/
41+
private $issuer;
42+
43+
/**
44+
* @var CustomerRepositoryInterface
45+
*/
46+
private $customerRepo;
47+
48+
/**
49+
* @var UserModel
50+
*/
51+
private $userModel;
52+
53+
/**
54+
* @var UserTokenParametersInterfaceFactory
55+
*/
56+
private $paramsFactory;
57+
58+
/**
59+
* @var MutableScopeConfigInterface
60+
*/
61+
private $config;
62+
63+
public function getJwtCases(): array
64+
{
65+
return [
66+
'jws-hs256' => [Jwk::ALGORITHM_HS256, JweEncryptionSettingsInterface::CONTENT_ENCRYPTION_ALGO_A128GCM],
67+
'jws-hs384' => [Jwk::ALGORITHM_HS384, JweEncryptionSettingsInterface::CONTENT_ENCRYPTION_ALGO_A128GCM],
68+
'jwe-a128kw-a128gcm' => [
69+
Jwk::ALGORITHM_A128KW,
70+
JweEncryptionSettingsInterface::CONTENT_ENCRYPTION_ALGO_A128GCM
71+
],
72+
'jwe-a256gcmkw-a192hs384' => [
73+
Jwk::ALGORITHM_A256GCMKW,
74+
JweEncryptionSettingsInterface::CONTENT_ENCRYPTION_ALGO_A192_HS384
75+
],
76+
];
77+
}
78+
79+
/**
80+
* Verify that a JWT token can be issued for a customer using various algorithms.
81+
*
82+
* @param string $jwtAlg JWT algorithm to use.
83+
* @param string $jweAlg JWE content encryption algorithm.
84+
* @return void
85+
* @throws \Throwable
86+
* @magentoDataFixture Magento/Customer/_files/customer.php
87+
* @dataProvider getJwtCases
88+
*/
89+
public function testIssueForCustomer(string $jwtAlg, string $jweAlg): void
90+
{
91+
$this->config->setValue('webapi/jwtauth/jwt_alg', $jwtAlg);
92+
$this->config->setValue('webapi/jwtauth/jwe_alg', $jweAlg);
93+
94+
$customer = $this->customerRepo->get('[email protected]');
95+
/** @var UserTokenParametersInterface $params */
96+
$params = $this->paramsFactory->create();
97+
$jwtParams = new JwtTokenParameters();
98+
$jwtParams->setClaims([new PrivateClaim($claim = 'custom-claim', $claimValue = 'value')]);
99+
$jwtParams->setProtectedHeaderParameters(
100+
[new PrivateHeaderParameter($header = 'custom-header', $headerValue = 42)]
101+
);
102+
$params->getExtensionAttributes()->setJwtParams($jwtParams);
103+
$token = $this->issuer->create(
104+
new JwtUserContext((int) $customer->getId(), UserContextInterface::USER_TYPE_CUSTOMER),
105+
$params
106+
);
107+
108+
$data = $this->model->read($token);
109+
$this->assertInstanceOf(JwtTokenDataInterface::class, $data->getData());
110+
/** @var JwtTokenDataInterface $tokenData */
111+
$tokenData = $data->getData();
112+
$this->assertEquals(UserContextInterface::USER_TYPE_CUSTOMER, $data->getUserContext()->getUserType());
113+
$this->assertEquals((int) $customer->getId(), $data->getUserContext()->getUserId());
114+
$this->assertGreaterThan($tokenData->getIssued(), $tokenData->getExpires());
115+
$claims = [];
116+
foreach ($tokenData->getJwtClaims()->getClaims() as $item) {
117+
$claims[$item->getName()] = $item;
118+
}
119+
$this->assertArrayHasKey($claim, $claims);
120+
$this->assertEquals($claimValue, $claims[$claim]->getValue());
121+
$headerFound = $tokenData->getJwtHeader()->getParameter($header);
122+
$this->assertNotNull($headerFound);
123+
$this->assertEquals($headerValue, $headerFound->getValue());
124+
$this->assertEquals($jwtAlg, $tokenData->getJwtHeader()->getParameter('alg')->getValue());
125+
if ($enc = $tokenData->getJwtHeader()->getParameter('enc')) {
126+
$this->assertEquals($jweAlg, $enc->getValue());
127+
}
128+
}
129+
130+
/**
131+
* Verify that a token can be issued for an admin user.
132+
*
133+
* @return void
134+
* @throws \Throwable
135+
* @magentoDataFixture Magento/User/_files/user_with_role.php
136+
*/
137+
public function testIssueForAdminCases(): void
138+
{
139+
$admin = $this->userModel->loadByUsername('adminUser');
140+
/** @var UserTokenParametersInterface $params */
141+
$params = $this->paramsFactory->create();
142+
$token = $this->issuer->create(
143+
new JwtUserContext((int) $admin->getId(), UserContextInterface::USER_TYPE_ADMIN),
144+
$params
145+
);
146+
147+
$data = $this->model->read($token);
148+
$this->assertInstanceOf(JwtTokenDataInterface::class, $data->getData());
149+
/** @var JwtTokenDataInterface $tokenData */
150+
$this->assertEquals(UserContextInterface::USER_TYPE_ADMIN, $data->getUserContext()->getUserType());
151+
$this->assertEquals((int) $admin->getId(), $data->getUserContext()->getUserId());
152+
$this->assertGreaterThan($data->getData()->getIssued(), $data->getData()->getExpires());
153+
}
154+
155+
/**
156+
* @inheritDoc
157+
*/
158+
protected function setUp(): void
159+
{
160+
parent::setUp();
161+
162+
/** @var ObjectManager $objectManager */
163+
$objectManager = Bootstrap::getObjectManager();
164+
165+
$this->model = $objectManager->get(Reader::class);
166+
$this->issuer = $objectManager->get(Issuer::class);
167+
$this->customerRepo = $objectManager->get(CustomerRepositoryInterface::class);
168+
$this->userModel = $objectManager->create(UserModel::class);
169+
$this->paramsFactory = $objectManager->get(UserTokenParametersInterfaceFactory::class);
170+
$this->config = $objectManager->get(MutableScopeConfigInterface::class);
171+
}
172+
}

0 commit comments

Comments
 (0)