Skip to content

Commit 015df9b

Browse files
authored
Merge pull request #177 from ppatrik/patch-3
Draft: feat: add 30s grace period for access token expiration
2 parents 45f871c + 54255ba commit 015df9b

2 files changed

Lines changed: 53 additions & 1 deletion

File tree

src/Http/Client.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public function request(string $method, string $path = '', array $options = []):
6868

6969
public function isAuthorized(): bool
7070
{
71-
return $this->tokenStorage->retrieveAccessToken()?->isExpired(new DateTime()) === false;
71+
return $this->tokenStorage->retrieveAccessToken()?->isExpired((new DateTime())->add(new \DateInterval('PT30S'))) === false;
7272
}
7373

7474
private function authorize(): void

tests/Unit/Http/ClientTest.php

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,58 @@ public function testIsAuthorizedIfTokenStorageContainsUnexpiredAccessToken(): vo
121121
static::assertTrue($client->isAuthorized());
122122
}
123123

124+
public function testIsNotAuthorizedIfTokenExpiresWithinGracePeriod(): void
125+
{
126+
$accessToken = $this->generateToken((new DateTimeImmutable())->modify('+15 seconds'));
127+
128+
$tokenStorage = new InMemoryTokenStorage();
129+
$tokenStorage->storeAccessToken($accessToken);
130+
131+
$client = new Client(
132+
$this->keycloak,
133+
$this->createMock(ClientInterface::class),
134+
$tokenStorage,
135+
);
136+
137+
static::assertFalse($client->isAuthorized());
138+
}
139+
140+
public function testIsAuthorizedIfTokenExpiresAfterGracePeriod(): void
141+
{
142+
$accessToken = $this->generateToken((new DateTimeImmutable())->modify('+60 seconds'));
143+
144+
$tokenStorage = new InMemoryTokenStorage();
145+
$tokenStorage->storeAccessToken($accessToken);
146+
147+
$client = new Client(
148+
$this->keycloak,
149+
$this->createMock(ClientInterface::class),
150+
$tokenStorage,
151+
);
152+
153+
static::assertTrue($client->isAuthorized());
154+
}
155+
156+
public function testReAuthorizesWhenTokenIsWithinGracePeriod(): void
157+
{
158+
$expiringAccessToken = $this->generateToken((new DateTimeImmutable())->modify('+15 seconds'));
159+
$refreshToken = $this->generateToken((new DateTimeImmutable())->modify('+1 hour'));
160+
161+
$tokenStorage = new InMemoryTokenStorage();
162+
$tokenStorage->storeAccessToken($expiringAccessToken);
163+
$tokenStorage->storeRefreshToken($refreshToken);
164+
165+
$guzzleClient = new GuzzleClient(['handler' => new MockHandler([
166+
$this->generateTokenResponse(),
167+
new Response(),
168+
])]);
169+
170+
$client = new Client($this->keycloak, $guzzleClient, $tokenStorage);
171+
$client->request('GET', '/admin/realms');
172+
173+
static::assertNotEquals($expiringAccessToken->toString(), $tokenStorage->retrieveAccessToken()->toString());
174+
}
175+
124176
public function testAuthenticatesUsingConfiguredRealm(): void
125177
{
126178
$accessToken = $this->generateToken((new DateTimeImmutable())->modify('+1 hour'));

0 commit comments

Comments
 (0)