Skip to content

Commit f1b5c20

Browse files
frankdekkerchalasr
authored andcommitted
Unlink cleaned up access tokens from refresh tokens
1 parent 7d890a6 commit f1b5c20

File tree

3 files changed

+39
-12
lines changed

3 files changed

+39
-12
lines changed

src/Manager/Doctrine/AccessTokenManager.php

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use League\Bundle\OAuth2ServerBundle\Manager\AccessTokenManagerInterface;
99
use League\Bundle\OAuth2ServerBundle\Model\AccessToken;
1010
use League\Bundle\OAuth2ServerBundle\Model\AccessTokenInterface;
11+
use League\Bundle\OAuth2ServerBundle\Model\RefreshToken;
1112

1213
final class AccessTokenManager implements AccessTokenManagerInterface
1314
{
@@ -50,12 +51,39 @@ public function clearExpired(): int
5051
return 0;
5152
}
5253

53-
/** @var int */
54-
return $this->entityManager->createQueryBuilder()
55-
->delete(AccessToken::class, 'at')
54+
/** @var array{identifier: string}[] */
55+
$results = $this->entityManager->createQueryBuilder()
56+
->select('at.identifier')
57+
->from(AccessToken::class, 'at')
5658
->where('at.expiry < :expiry')
5759
->setParameter('expiry', new \DateTimeImmutable(), 'datetime_immutable')
5860
->getQuery()
61+
->getScalarResult();
62+
if (0 === \count($results)) {
63+
return 0;
64+
}
65+
66+
/** @var string[] */
67+
$ids = array_column($results, 'identifier');
68+
69+
// unlink access tokens from refresh tokens
70+
$this->entityManager->createQueryBuilder()
71+
->update(RefreshToken::class, 'rt')
72+
->set('rt.accessToken', ':null')
73+
->where('rt.accessToken IN (:ids)')
74+
->setParameter('null', null)
75+
->setParameter('ids', $ids)
76+
->getQuery()
5977
->execute();
78+
79+
// delete expired access tokens
80+
$this->entityManager->createQueryBuilder()
81+
->delete(AccessToken::class, 'at')
82+
->where('at.identifier IN (:ids)')
83+
->setParameter('ids', $ids)
84+
->getQuery()
85+
->execute();
86+
87+
return \count($ids);
6088
}
6189
}

tests/Acceptance/DoctrineAccessTokenManagerTest.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,9 @@ public function testClearExpiredWithRefreshToken(): void
123123

124124
$this->assertSame(3, $doctrineAccessTokenManager->clearExpired());
125125

126-
$this->assertSame(
127-
$testData['output'],
128-
$em->getRepository(RefreshToken::class)->findBy(['accessToken' => null], ['identifier' => 'ASC'])
129-
);
126+
$em->clear();
127+
128+
self::assertCount(3, $em->getRepository(RefreshToken::class)->findBy(['accessToken' => null], ['identifier' => 'ASC']));
130129
}
131130

132131
public function testClearExpiredWithRefreshTokenWithoutSavingAccessToken(): void

tests/Acceptance/DoctrineClientManagerTest.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ final class DoctrineClientManagerTest extends AbstractAcceptanceTest
2222
{
2323
public function testSimpleDelete(): void
2424
{
25-
/** @var $em EntityManagerInterface */
25+
/** @var EntityManagerInterface $em */
2626
$em = $this->client->getContainer()->get('doctrine.orm.entity_manager');
2727
$doctrineClientManager = new DoctrineClientManager($em, self::getContainer()->get(EventDispatcherInterface::class), Client::class);
2828

@@ -41,7 +41,7 @@ public function testSimpleDelete(): void
4141

4242
public function testClientDeleteCascadesToAccessTokens(): void
4343
{
44-
/** @var $em EntityManagerInterface */
44+
/** @var EntityManagerInterface $em */
4545
$em = $this->client->getContainer()->get('doctrine.orm.entity_manager');
4646
$doctrineClientManager = new DoctrineClientManager($em, self::getContainer()->get(EventDispatcherInterface::class), Client::class);
4747

@@ -74,7 +74,7 @@ public function testClientDeleteCascadesToAccessTokens(): void
7474

7575
public function testSaveClientWithoutScopeAddDefaultScopes(): void
7676
{
77-
/** @var $em EntityManagerInterface */
77+
/** @var EntityManagerInterface $em */
7878
$em = $this->client->getContainer()->get('doctrine.orm.entity_manager');
7979
$doctrineClientManager = new DoctrineClientManager($em, self::getContainer()->get(EventDispatcherInterface::class), Client::class);
8080

@@ -88,7 +88,7 @@ public function testSaveClientWithoutScopeAddDefaultScopes(): void
8888

8989
public function testClientDeleteCascadesToAccessTokensAndRefreshTokens(): void
9090
{
91-
/** @var $em EntityManagerInterface */
91+
/** @var EntityManagerInterface $em */
9292
$em = $this->client->getContainer()->get('doctrine.orm.entity_manager');
9393
$doctrineClientManager = new DoctrineClientManager($em, self::getContainer()->get(EventDispatcherInterface::class), Client::class);
9494

@@ -122,7 +122,7 @@ public function testClientDeleteCascadesToAccessTokensAndRefreshTokens(): void
122122
->find($accessToken->getIdentifier())
123123
);
124124

125-
/** @var $refreshToken RefreshToken */
125+
/** @var RefreshToken $refreshToken */
126126
$refreshToken = $em
127127
->getRepository(RefreshToken::class)
128128
->find($refreshToken->getIdentifier())

0 commit comments

Comments
 (0)