Skip to content

Commit 54f954e

Browse files
committed
Merge remote-tracking branch 'origin/b-7.2.x' into b-7.2.x
2 parents e4d5358 + e19f6d0 commit 54f954e

6 files changed

Lines changed: 63 additions & 26 deletions

File tree

CHANGELOG-v10.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3030
- New methods:
3131
- `OxidEsales\GraphQL\Base\Infrastructure\RefreshTokenRepositoryInterface::invalidateUserTokens`
3232
- `OxidEsales\GraphQL\Base\Infrastructure\Token::invalidateUserTokens`
33+
- `OxidEsales\GraphQL\Base\Infrastructure\Token::isTokenExpired`
3334
- New event subscriber:
3435
- `OxidEsales\GraphQL\Base\Event\Subscriber\PasswordChangeSubscriber`
3536

src/Infrastructure/Token.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,26 @@ public function isTokenRegistered(string $tokenId): bool
4949
return $storage->isLoaded();
5050
}
5151

52+
public function isTokenExpired(string $tokenId): bool
53+
{
54+
$queryBuilder = $this->queryBuilderFactory->create()
55+
->select('oxid')
56+
->from('oegraphqltoken')
57+
->where('OXID = :tokenId')
58+
->andWhere('EXPIRES_AT <= NOW()')
59+
->setParameters([
60+
'tokenId' => $tokenId,
61+
]);
62+
63+
$result = $queryBuilder->execute();
64+
65+
if (is_object($result)) {
66+
return $result->fetchOne() > 0;
67+
}
68+
69+
return false;
70+
}
71+
5272
public function removeExpiredTokens(UserInterface $user): void
5373
{
5474
$queryBuilder = $this->queryBuilderFactory->create()

src/Service/TokenValidator.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public function __construct(
4141
*/
4242
public function validateToken(UnencryptedToken $token): void
4343
{
44-
if (!$this->areConstraintsValid($token)) {
44+
if (!$this->areConstraintsValid($token) || $this->isTokenExpired($token)) {
4545
throw new InvalidToken();
4646
}
4747

@@ -62,6 +62,11 @@ private function areConstraintsValid(UnencryptedToken $token): bool
6262
return $validator->validate($token, ...$config->validationConstraints());
6363
}
6464

65+
private function isTokenExpired(UnencryptedToken $token): bool
66+
{
67+
return $this->tokenInfrastructure->isTokenExpired($token->claims()->get(Token::CLAIM_TOKENID));
68+
}
69+
6570
private function isUserBlocked(?string $userId): bool
6671
{
6772
$groups = $this->legacyInfrastructure->getUserGroupIds($userId);

tests/Integration/Infrastructure/TokenTest.php

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@
1313
use Lcobucci\JWT\Token\DataSet;
1414
use Lcobucci\JWT\UnencryptedToken;
1515
use OxidEsales\Eshop\Application\Model\User;
16-
use OxidEsales\EshopCommunity\Internal\Framework\Database\ConnectionProviderInterface;
1716
use OxidEsales\EshopCommunity\Tests\Integration\IntegrationTestCase;
1817
use OxidEsales\EshopCommunity\Tests\TestContainerFactory;
1918
use OxidEsales\GraphQL\Base\DataType\Token as TokenDataType;
2019
use OxidEsales\GraphQL\Base\DataType\User as UserDataType;
2120
use OxidEsales\GraphQL\Base\Infrastructure\Model\Token as TokenModel;
2221
use OxidEsales\GraphQL\Base\Infrastructure\Token as TokenInfrastructure;
22+
use OxidEsales\GraphQL\Base\Service\Token;
2323
use OxidEsales\GraphQL\Base\Service\Token as TokenService;
2424

2525
class TokenTest extends IntegrationTestCase
@@ -31,17 +31,13 @@ class TokenTest extends IntegrationTestCase
3131
/** @var TokenInfrastructure */
3232
private $tokenInfrastructure;
3333

34-
/** @var ConnectionProviderInterface */
35-
private $connection;
36-
3734
public function setUp(): void
3835
{
3936
parent::setUp();
4037
$containerFactory = new TestContainerFactory();
4138
$container = $containerFactory->create();
4239
$container->compile();
4340
$this->tokenInfrastructure = $container->get(TokenInfrastructure::class);
44-
$this->connection = $container->get(ConnectionProviderInterface::class)->get();
4541
}
4642

4743
public function testRegisterToken(): void
@@ -74,6 +70,28 @@ public function testIsTokenRegisteredNo(): void
7470
$this->assertFalse($this->tokenInfrastructure->isTokenRegistered('not_registered_token'));
7571
}
7672

73+
public function testIsTokenExpired(): void
74+
{
75+
$this->tokenInfrastructure->registerToken(
76+
$this->getTokenMock('valid_token'),
77+
new DateTimeImmutable('now'),
78+
new DateTimeImmutable('+8 hours')
79+
);
80+
81+
$this->assertFalse($this->tokenInfrastructure->isTokenExpired('valid_token'));
82+
}
83+
84+
public function testIsTokenExpiredNo(): void
85+
{
86+
$this->tokenInfrastructure->registerToken(
87+
$this->getTokenMock('expired_token'),
88+
new DateTimeImmutable('now'),
89+
new DateTimeImmutable('-8 hours')
90+
);
91+
92+
$this->assertTrue($this->tokenInfrastructure->isTokenExpired('expired_token'));
93+
}
94+
7795
public function testRemoveExpiredTokens(): void
7896
{
7997
$this->tokenInfrastructure->registerToken(
@@ -323,13 +341,7 @@ public function testInvalidateAccessTokens(): void
323341
);
324342

325343
$this->tokenInfrastructure->invalidateUserTokens($userId);
326-
$result = $this->connection->executeQuery(
327-
"select expires_at from `oegraphqltoken` where oxid=:tokenId",
328-
['tokenId' => $token]
329-
);
330-
$expiresAtAfterChange = $result->fetchOne();
331-
332-
$this->assertTrue(new DateTimeImmutable($expiresAtAfterChange) <= new DateTimeImmutable('now'));
344+
$this->assertTrue($this->tokenInfrastructure->isTokenExpired($token));
333345
}
334346

335347
public function testInvalidateAccessTokensWrongUserId(): void
@@ -344,13 +356,7 @@ public function testInvalidateAccessTokensWrongUserId(): void
344356
);
345357

346358
$this->tokenInfrastructure->invalidateUserTokens('wrong_user_id');
347-
$result = $this->connection->executeQuery(
348-
"select expires_at from `oegraphqltoken` where oxid=:tokenId",
349-
['tokenId' => $token]
350-
);
351-
$expiresAtAfterChange = $result->fetchOne();
352-
353-
$this->assertFalse(new DateTimeImmutable($expiresAtAfterChange) <= new DateTimeImmutable('now'));
359+
$this->assertFalse($this->tokenInfrastructure->isTokenExpired($token));
354360
}
355361

356362
private function getTokenMock(

tests/Integration/TestCase.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,11 @@ public function isTokenRegistered(string $tokenId): bool
323323
return true;
324324
}
325325

326+
public function isTokenExpired(string $tokenId): bool
327+
{
328+
return false;
329+
}
330+
326331
public function registerToken(UnencryptedToken $token, DateTimeImmutable $time, DateTimeImmutable $expire): void
327332
{
328333
}

tests/Unit/Service/TokenValidatorTest.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public function testTokenShopIdValidation(): void
2626

2727
$tokenInfrastructure = $this->createPartialMock(
2828
TokenInfrastructure::class,
29-
['registerToken', 'isTokenRegistered', 'removeExpiredTokens', 'canIssueToken']
29+
['registerToken', 'isTokenRegistered', 'isTokenExpired', 'removeExpiredTokens', 'canIssueToken']
3030
);
3131
$tokenInfrastructure->method('isTokenRegistered')->willReturn(true);
3232
$tokenInfrastructure->method('canIssueToken')->willReturn(true);
@@ -54,7 +54,7 @@ public function testTokenShopUrlValidation(): void
5454

5555
$tokenInfrastructure = $this->createPartialMock(
5656
TokenInfrastructure::class,
57-
['registerToken', 'isTokenRegistered', 'removeExpiredTokens', 'canIssueToken']
57+
['registerToken', 'isTokenRegistered', 'isTokenExpired', 'removeExpiredTokens', 'canIssueToken']
5858
);
5959
$tokenInfrastructure->method('isTokenRegistered')->willReturn(true);
6060
$tokenInfrastructure->method('canIssueToken')->willReturn(true);
@@ -85,7 +85,7 @@ public function testTokenUserInBlockedGroup(): void
8585

8686
$tokenInfrastructure = $this->createPartialMock(
8787
TokenInfrastructure::class,
88-
['registerToken', 'isTokenRegistered', 'removeExpiredTokens', 'canIssueToken']
88+
['registerToken', 'isTokenRegistered', 'isTokenExpired', 'removeExpiredTokens', 'canIssueToken']
8989
);
9090
$tokenInfrastructure->method('isTokenRegistered')->willReturn(true);
9191
$tokenInfrastructure->method('canIssueToken')->willReturn(true);
@@ -108,7 +108,7 @@ public function testExpiredToken(): void
108108

109109
$tokenInfrastructure = $this->createPartialMock(
110110
TokenInfrastructure::class,
111-
['registerToken', 'isTokenRegistered', 'removeExpiredTokens', 'canIssueToken']
111+
['registerToken', 'isTokenRegistered', 'isTokenExpired', 'removeExpiredTokens', 'canIssueToken']
112112
);
113113
$tokenInfrastructure->method('isTokenRegistered')->willReturn(true);
114114
$tokenInfrastructure->method('canIssueToken')->willReturn(true);
@@ -134,7 +134,7 @@ public function testDeletedToken(): void
134134

135135
$tokenInfrastructure = $this->createPartialMock(
136136
TokenInfrastructure::class,
137-
['registerToken', 'isTokenRegistered', 'removeExpiredTokens', 'canIssueToken']
137+
['registerToken', 'isTokenRegistered', 'isTokenExpired', 'removeExpiredTokens', 'canIssueToken']
138138
);
139139
$tokenInfrastructure->method('isTokenRegistered')->willReturn(false);
140140
$tokenInfrastructure->method('canIssueToken')->willReturn(true);
@@ -157,7 +157,7 @@ public function testAnonymousToken(): void
157157

158158
$tokenInfrastructure = $this->createPartialMock(
159159
TokenInfrastructure::class,
160-
['registerToken', 'isTokenRegistered', 'removeExpiredTokens', 'canIssueToken']
160+
['registerToken', 'isTokenRegistered', 'isTokenExpired', 'removeExpiredTokens', 'canIssueToken']
161161
);
162162
$tokenInfrastructure->method('canIssueToken')->willReturn(true);
163163
$validator = $this->getTokenValidator($legacy, $tokenInfrastructure);

0 commit comments

Comments
 (0)