Skip to content

Commit d50b867

Browse files
authored
Merge pull request #4 from retailcrm/task-add-verify-event
Add token verification and post-issuance event handlers
2 parents 3dd446d + d2c796d commit d50b867

File tree

6 files changed

+91
-8
lines changed

6 files changed

+91
-8
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace OAuth\Event;
6+
7+
use OAuth\Model\ClientInterface;
8+
use Symfony\Component\Security\Core\User\UserInterface;
9+
10+
class AfterCreateAccessTokenEvent
11+
{
12+
public function __construct(
13+
private readonly ClientInterface $client,
14+
private readonly ?UserInterface $user,
15+
private readonly string $accessToken,
16+
private readonly ?string $refreshToken,
17+
) {
18+
}
19+
20+
public function getClient(): ClientInterface
21+
{
22+
return $this->client;
23+
}
24+
25+
public function getUser(): ?UserInterface
26+
{
27+
return $this->user;
28+
}
29+
30+
public function getAccessToken(): string
31+
{
32+
return $this->accessToken;
33+
}
34+
35+
public function getRefreshToken(): ?string
36+
{
37+
return $this->refreshToken;
38+
}
39+
}

src/Event/VerifyTokenEvent.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace OAuth\Event;
6+
7+
use OAuth\Model\TokenInterface;
8+
9+
class VerifyTokenEvent
10+
{
11+
public function __construct(
12+
private readonly TokenInterface $token,
13+
) {
14+
}
15+
16+
public function getToken(): TokenInterface
17+
{
18+
return $this->token;
19+
}
20+
}

src/Resources/config/grant_extension.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
$services
3131
->set('oauth_server.grant_extension.refresh_token', RefreshTokenGrantExtension::class)
3232
->args([
33+
service('event_dispatcher'),
3334
service('oauth_server.doctrine_storage.refresh_token'),
3435
])
3536
->alias(RefreshTokenGrantExtension::class, 'oauth_server.grant_extension.refresh_token')

src/Server/GrantExtension/RefreshTokenGrantExtension.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,20 @@
55
namespace OAuth\Server\GrantExtension;
66

77
use OAuth\Enum\ErrorCode;
8+
use OAuth\Event\VerifyTokenEvent;
89
use OAuth\Exception\OAuthServerException;
910
use OAuth\Model\ClientInterface;
1011
use OAuth\Server\Config;
1112
use OAuth\Server\Storage\RefreshTokenStorageInterface;
1213
use Symfony\Component\HttpFoundation\Response;
14+
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
1315

1416
class RefreshTokenGrantExtension implements GrantExtensionInterface
1517
{
16-
public function __construct(private readonly RefreshTokenStorageInterface $storage)
17-
{
18+
public function __construct(
19+
private readonly EventDispatcherInterface $dispatcher,
20+
private readonly RefreshTokenStorageInterface $storage,
21+
) {
1822
}
1923

2024
public function checkGrantExtension(ClientInterface $client, Config $config, string $grantType, array $input): Grant
@@ -33,6 +37,8 @@ public function checkGrantExtension(ClientInterface $client, Config $config, str
3337
throw new OAuthServerException(Response::HTTP_BAD_REQUEST, ErrorCode::ERROR_INVALID_GRANT, 'Refresh token has expired');
3438
}
3539

40+
$this->dispatcher->dispatch(new VerifyTokenEvent($token));
41+
3642
$this->storage->unsetRefreshToken($token->getToken());
3743

3844
return new Grant($token->getUser(), $token->getScope());

src/Server/Handler.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66

77
use OAuth\Enum\ErrorCode;
88
use OAuth\Enum\TransportMethod;
9+
use OAuth\Event\AfterCreateAccessTokenEvent;
910
use OAuth\Event\AfterGrantAccessEvent;
11+
use OAuth\Event\VerifyTokenEvent;
1012
use OAuth\Exception\OAuthAuthenticateException;
1113
use OAuth\Exception\OAuthRedirectException;
1214
use OAuth\Exception\OAuthServerException;
@@ -115,6 +117,8 @@ public function verifyAccessToken(string $tokenParam, ?string $scope = null): Ac
115117
throw new OAuthAuthenticateException(Response::HTTP_FORBIDDEN, $tokenType, $realm, ErrorCode::ERROR_INSUFFICIENT_SCOPE, 'The request requires higher privileges than provided by the access token.', $scope);
116118
}
117119

120+
$this->eventDispatcher->dispatch(new VerifyTokenEvent($token));
121+
118122
return $token;
119123
}
120124

@@ -393,6 +397,13 @@ private function createAccessToken(
393397
);
394398
}
395399

400+
$this->eventDispatcher->dispatch(new AfterCreateAccessTokenEvent(
401+
$client,
402+
$user,
403+
$token['access_token'],
404+
$token['refresh_token'] ?? null,
405+
));
406+
396407
return $token;
397408
}
398409

tests/Server/HandlerTest.php

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44

55
namespace OAuth\Tests\Server;
66

7+
use OAuth\Event\AfterCreateAccessTokenEvent;
78
use OAuth\Event\AfterGrantAccessEvent;
9+
use OAuth\Event\VerifyTokenEvent;
810
use OAuth\Exception\OAuthAuthenticateException;
911
use OAuth\Exception\OAuthServerException;
1012
use OAuth\Model\AccessTokenInterface;
@@ -81,7 +83,7 @@ protected function setUp(): void
8183
$this->authCodeStorage,
8284
new AuthCodeGrantExtension($this->authCodeStorage),
8385
new ClientCredentialsGrantExtension(),
84-
new RefreshTokenGrantExtension($this->refreshTokenStorage),
86+
new RefreshTokenGrantExtension($this->eventDispatcher, $this->refreshTokenStorage),
8587
new UserCredentialsGrantExtension($this->userProviderInterface, $this->passwordHasherFactory),
8688
$this->customGrantExtension,
8789
);
@@ -105,6 +107,8 @@ public function testVerifyAccessToken(): void
105107
$token = $this->manager->verifyAccessToken('my_token');
106108
$this->assertNotNull($token);
107109
$this->assertEquals('my_token', $token->getToken());
110+
111+
$this->assertEquals([VerifyTokenEvent::class], $this->eventDispatcher->getOrphanedEvents());
108112
}
109113

110114
public static function provideVerifyAccessTokenException(): iterable
@@ -173,6 +177,8 @@ public function testVerifyAccessTokenException(
173177
$this->expectException(OAuthAuthenticateException::class);
174178

175179
$this->manager->verifyAccessToken($tokenParam, $scope);
180+
181+
$this->assertEquals([], $this->eventDispatcher->getOrphanedEvents());
176182
}
177183

178184
public static function provideGetBearerToken(): iterable
@@ -380,7 +386,7 @@ public function testGrantAccessTokenAuthCode(Request $request, array $expectedRe
380386
$response = $this->manager->grantAccessToken($request);
381387

382388
$this->assertEquals($expectedResponse, json_decode($response->getContent(), true, 512, JSON_THROW_ON_ERROR));
383-
$this->assertEquals([AfterGrantAccessEvent::class], $this->eventDispatcher->getOrphanedEvents());
389+
$this->assertEquals([AfterGrantAccessEvent::class, AfterCreateAccessTokenEvent::class], $this->eventDispatcher->getOrphanedEvents());
384390
}
385391

386392
public static function provideGrantAccessTokenUserCredentials(): iterable
@@ -433,7 +439,7 @@ public function testGrantAccessTokenUserCredentials(Request $request): void
433439
'scope' => null,
434440
'refresh_token' => 'refresh_token',
435441
], json_decode($response->getContent(), true, 512, JSON_THROW_ON_ERROR));
436-
$this->assertEquals([AfterGrantAccessEvent::class], $this->eventDispatcher->getOrphanedEvents());
442+
$this->assertEquals([AfterGrantAccessEvent::class, AfterCreateAccessTokenEvent::class], $this->eventDispatcher->getOrphanedEvents());
437443
}
438444

439445
public static function provideGrantAccessTokenClientCredentials(): iterable
@@ -478,7 +484,7 @@ public function testGrantAccessTokenClientCredentials(Request $request): void
478484
'token_type' => 'bearer',
479485
'scope' => null,
480486
], json_decode($response->getContent(), true, 512, JSON_THROW_ON_ERROR));
481-
$this->assertEquals([AfterGrantAccessEvent::class], $this->eventDispatcher->getOrphanedEvents());
487+
$this->assertEquals([AfterGrantAccessEvent::class, AfterCreateAccessTokenEvent::class], $this->eventDispatcher->getOrphanedEvents());
482488
}
483489

484490
public static function provideGrantAccessTokenRefreshToken(): iterable
@@ -537,7 +543,7 @@ public function testGrantAccessTokenRefreshToken(Request $request): void
537543
'scope' => 'read',
538544
'refresh_token' => 'refresh_token',
539545
], json_decode($response->getContent(), true, 512, JSON_THROW_ON_ERROR));
540-
$this->assertEquals([AfterGrantAccessEvent::class], $this->eventDispatcher->getOrphanedEvents());
546+
$this->assertEquals([VerifyTokenEvent::class, AfterGrantAccessEvent::class, AfterCreateAccessTokenEvent::class], $this->eventDispatcher->getOrphanedEvents());
541547
}
542548

543549
public static function provideGrantAccessTokenCustom(): iterable
@@ -595,7 +601,7 @@ public function checkGrantExtension(ClientInterface $client, Config $config, str
595601
'scope' => null,
596602
'refresh_token' => 'refresh_token',
597603
], json_decode($response->getContent(), true, 512, JSON_THROW_ON_ERROR));
598-
$this->assertEquals([AfterGrantAccessEvent::class], $this->eventDispatcher->getOrphanedEvents());
604+
$this->assertEquals([AfterGrantAccessEvent::class, AfterCreateAccessTokenEvent::class], $this->eventDispatcher->getOrphanedEvents());
599605
}
600606

601607
public static function provideGrantAccessTokenException(): iterable

0 commit comments

Comments
 (0)