diff --git a/src/Infrastructure/Token.php b/src/Infrastructure/Token.php index 16065e91..34ef1d8b 100644 --- a/src/Infrastructure/Token.php +++ b/src/Infrastructure/Token.php @@ -49,6 +49,26 @@ public function isTokenRegistered(string $tokenId): bool return $storage->isLoaded(); } + public function isTokenExpired(string $tokenId): bool + { + $queryBuilder = $this->queryBuilderFactory->create() + ->select('oxid') + ->from('oegraphqltoken') + ->where('OXID = :tokenId') + ->andWhere('EXPIRES_AT <= NOW()') + ->setParameters([ + 'tokenId' => $tokenId, + ]); + + $result = $queryBuilder->execute(); + + if (is_object($result)) { + return $result->fetchOne() > 0; + } + + return false; + } + public function removeExpiredTokens(UserInterface $user): void { $queryBuilder = $this->queryBuilderFactory->create() diff --git a/src/Service/TokenValidator.php b/src/Service/TokenValidator.php index 02aa358f..8725d5d5 100644 --- a/src/Service/TokenValidator.php +++ b/src/Service/TokenValidator.php @@ -41,7 +41,7 @@ public function __construct( */ public function validateToken(UnencryptedToken $token): void { - if (!$this->areConstraintsValid($token)) { + if (!$this->areConstraintsValid($token) || $this->isTokenExpired($token)) { throw new InvalidToken(); } @@ -62,6 +62,11 @@ private function areConstraintsValid(UnencryptedToken $token): bool return $validator->validate($token, ...$config->validationConstraints()); } + private function isTokenExpired(UnencryptedToken $token) + { + return $this->tokenInfrastructure->isTokenExpired($token->claims()->get(Token::CLAIM_TOKENID)); + } + private function isUserBlocked(?string $userId): bool { $groups = $this->legacyInfrastructure->getUserGroupIds($userId); diff --git a/tests/Integration/TestCase.php b/tests/Integration/TestCase.php index a428ca61..772ac35a 100644 --- a/tests/Integration/TestCase.php +++ b/tests/Integration/TestCase.php @@ -323,6 +323,11 @@ public function isTokenRegistered(string $tokenId): bool return true; } + public function isTokenExpired(string $tokenId): bool + { + return false; + } + public function registerToken(UnencryptedToken $token, DateTimeImmutable $time, DateTimeImmutable $expire): void { } diff --git a/tests/Unit/Service/TokenValidatorTest.php b/tests/Unit/Service/TokenValidatorTest.php index ed4e051d..37f116ac 100644 --- a/tests/Unit/Service/TokenValidatorTest.php +++ b/tests/Unit/Service/TokenValidatorTest.php @@ -26,7 +26,7 @@ public function testTokenShopIdValidation(): void $tokenInfrastructure = $this->createPartialMock( TokenInfrastructure::class, - ['registerToken', 'isTokenRegistered', 'removeExpiredTokens', 'canIssueToken'] + ['registerToken', 'isTokenRegistered', 'isTokenExpired', 'removeExpiredTokens', 'canIssueToken'] ); $tokenInfrastructure->method('isTokenRegistered')->willReturn(true); $tokenInfrastructure->method('canIssueToken')->willReturn(true); @@ -54,7 +54,7 @@ public function testTokenShopUrlValidation(): void $tokenInfrastructure = $this->createPartialMock( TokenInfrastructure::class, - ['registerToken', 'isTokenRegistered', 'removeExpiredTokens', 'canIssueToken'] + ['registerToken', 'isTokenRegistered', 'isTokenExpired', 'removeExpiredTokens', 'canIssueToken'] ); $tokenInfrastructure->method('isTokenRegistered')->willReturn(true); $tokenInfrastructure->method('canIssueToken')->willReturn(true); @@ -85,7 +85,7 @@ public function testTokenUserInBlockedGroup(): void $tokenInfrastructure = $this->createPartialMock( TokenInfrastructure::class, - ['registerToken', 'isTokenRegistered', 'removeExpiredTokens', 'canIssueToken'] + ['registerToken', 'isTokenRegistered', 'isTokenExpired', 'removeExpiredTokens', 'canIssueToken'] ); $tokenInfrastructure->method('isTokenRegistered')->willReturn(true); $tokenInfrastructure->method('canIssueToken')->willReturn(true); @@ -108,7 +108,7 @@ public function testExpiredToken(): void $tokenInfrastructure = $this->createPartialMock( TokenInfrastructure::class, - ['registerToken', 'isTokenRegistered', 'removeExpiredTokens', 'canIssueToken'] + ['registerToken', 'isTokenRegistered', 'isTokenExpired', 'removeExpiredTokens', 'canIssueToken'] ); $tokenInfrastructure->method('isTokenRegistered')->willReturn(true); $tokenInfrastructure->method('canIssueToken')->willReturn(true); @@ -134,7 +134,7 @@ public function testDeletedToken(): void $tokenInfrastructure = $this->createPartialMock( TokenInfrastructure::class, - ['registerToken', 'isTokenRegistered', 'removeExpiredTokens', 'canIssueToken'] + ['registerToken', 'isTokenRegistered', 'isTokenExpired', 'removeExpiredTokens', 'canIssueToken'] ); $tokenInfrastructure->method('isTokenRegistered')->willReturn(false); $tokenInfrastructure->method('canIssueToken')->willReturn(true); @@ -157,7 +157,7 @@ public function testAnonymousToken(): void $tokenInfrastructure = $this->createPartialMock( TokenInfrastructure::class, - ['registerToken', 'isTokenRegistered', 'removeExpiredTokens', 'canIssueToken'] + ['registerToken', 'isTokenRegistered', 'isTokenExpired', 'removeExpiredTokens', 'canIssueToken'] ); $tokenInfrastructure->method('canIssueToken')->willReturn(true); $validator = $this->getTokenValidator($legacy, $tokenInfrastructure);