diff --git a/composer.json b/composer.json index 9699116ee..c5649cb00 100644 --- a/composer.json +++ b/composer.json @@ -6,9 +6,9 @@ "require": { "php": "^8.0", "ext-openssl": "*", - "league/event": "^2.2", "league/uri": "^6.7", "lcobucci/jwt": "^4.3 || ^5.0", + "psr/event-dispatcher": "^1.0", "psr/http-message": "^1.0.1", "defuse/php-encryption": "^2.3", "ext-json": "*", diff --git a/src/AuthorizationServer.php b/src/AuthorizationServer.php index 4d6862157..89248d0a3 100644 --- a/src/AuthorizationServer.php +++ b/src/AuthorizationServer.php @@ -11,8 +11,6 @@ use DateInterval; use Defuse\Crypto\Key; -use League\Event\EmitterAwareInterface; -use League\Event\EmitterAwareTrait; use League\OAuth2\Server\Exception\OAuthServerException; use League\OAuth2\Server\Grant\GrantTypeInterface; use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface; @@ -22,13 +20,12 @@ use League\OAuth2\Server\ResponseTypes\AbstractResponseType; use League\OAuth2\Server\ResponseTypes\BearerTokenResponse; use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface; +use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; -class AuthorizationServer implements EmitterAwareInterface +class AuthorizationServer { - use EmitterAwareTrait; - /** * @var GrantTypeInterface[] */ @@ -84,6 +81,11 @@ class AuthorizationServer implements EmitterAwareInterface */ private $revokeRefreshTokens = true; + /** + * @var EventDispatcherInterface + */ + private $eventDispatcher; + /** * New server instance. * @@ -139,10 +141,13 @@ public function enableGrantType(GrantTypeInterface $grantType, DateInterval $acc $grantType->setScopeRepository($this->scopeRepository); $grantType->setDefaultScope($this->defaultScope); $grantType->setPrivateKey($this->privateKey); - $grantType->setEmitter($this->getEmitter()); $grantType->setEncryptionKey($this->encryptionKey); $grantType->revokeRefreshTokens($this->revokeRefreshTokens); + if ($this->eventDispatcher !== null) { + $grantType->setEventDispatcher($this->eventDispatcher); + } + $this->enabledGrantTypes[$grantType->getIdentifier()] = $grantType; $this->grantTypeAccessTokenTTL[$grantType->getIdentifier()] = $accessTokenTTL; } @@ -249,4 +254,14 @@ public function revokeRefreshTokens(bool $revokeRefreshTokens): void { $this->revokeRefreshTokens = $revokeRefreshTokens; } + + /** + * Set the event dispatcher + * + * @param EventDispatcherInterface $eventDispatcher + */ + public function setEventDispatcher(EventDispatcherInterface $eventDispatcher): void + { + $this->eventDispatcher = $eventDispatcher; + } } diff --git a/src/Grant/AbstractGrant.php b/src/Grant/AbstractGrant.php index c8eb6b813..626c9b542 100644 --- a/src/Grant/AbstractGrant.php +++ b/src/Grant/AbstractGrant.php @@ -14,7 +14,6 @@ use DateTimeImmutable; use Error; use Exception; -use League\Event\EmitterAwareTrait; use League\OAuth2\Server\CryptKey; use League\OAuth2\Server\CryptTrait; use League\OAuth2\Server\Entities\AccessTokenEntityInterface; @@ -34,6 +33,7 @@ use League\OAuth2\Server\RequestEvent; use League\OAuth2\Server\RequestTypes\AuthorizationRequest; use LogicException; +use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Http\Message\ServerRequestInterface; use TypeError; @@ -42,7 +42,7 @@ */ abstract class AbstractGrant implements GrantTypeInterface { - use EmitterAwareTrait, CryptTrait; + use CryptTrait; const SCOPE_DELIMITER_STRING = ' '; @@ -98,6 +98,11 @@ abstract class AbstractGrant implements GrantTypeInterface */ protected $revokeRefreshTokens; + /** + * @var EventDispatcherInterface + */ + protected $eventDispatcher; + /** * @param ClientRepositoryInterface $clientRepository */ @@ -194,7 +199,9 @@ protected function validateClient(ServerRequestInterface $request) [$clientId, $clientSecret] = $this->getClientCredentials($request); if ($this->clientRepository->validateClient($clientId, $clientSecret, $this->getIdentifier()) === false) { - $this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request)); + if ($this->eventDispatcher !== null) { + $this->eventDispatcher->dispatch(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request)); + } throw OAuthServerException::invalidClient($request); } @@ -235,7 +242,10 @@ protected function getClientEntityOrFail($clientId, ServerRequestInterface $requ $client = $this->clientRepository->getClientEntity($clientId); if ($client instanceof ClientEntityInterface === false) { - $this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request)); + if ($this->eventDispatcher !== null ) { + $this->eventDispatcher->dispatch(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request)); + } + throw OAuthServerException::invalidClient($request); } @@ -286,7 +296,10 @@ protected function validateRedirectUri( ) { $validator = new RedirectUriValidator($client->getRedirectUri()); if (!$validator->validateRedirectUri($redirectUri)) { - $this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request)); + if ($this->eventDispatcher !== null ) { + $this->eventDispatcher->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request)); + } + throw OAuthServerException::invalidClient($request); } } @@ -618,4 +631,16 @@ public function completeAuthorizationRequest(AuthorizationRequest $authorization { throw new LogicException('This grant cannot complete an authorization request'); } + + /** + * Set the event dispatcher + * + * @param EventDispatcherInterface $eventDispatcher + * + * @return void + */ + public function setEventDispatcher(EventDispatcherInterface $eventDispatcher) + { + $this->eventDispatcher = $eventDispatcher; + } } diff --git a/src/Grant/AuthCodeGrant.php b/src/Grant/AuthCodeGrant.php index 8336cf649..5ec20d078 100644 --- a/src/Grant/AuthCodeGrant.php +++ b/src/Grant/AuthCodeGrant.php @@ -143,14 +143,23 @@ public function respondToAccessTokenRequest( // Issue and persist new access token $accessToken = $this->issueAccessToken($accessTokenTTL, $client, $authCodePayload->user_id, $scopes); - $this->getEmitter()->emit(new RequestAccessTokenEvent(RequestEvent::ACCESS_TOKEN_ISSUED, $request, $accessToken)); + + if ($this->eventDispatcher !== null) { + $this->eventDispatcher->dispatch(new RequestAccessTokenEvent(RequestEvent::ACCESS_TOKEN_ISSUED, $request, + $accessToken)); + } $responseType->setAccessToken($accessToken); // Issue and persist new refresh token if given $refreshToken = $this->issueRefreshToken($accessToken); if ($refreshToken !== null) { - $this->getEmitter()->emit(new RequestRefreshTokenEvent(RequestEvent::REFRESH_TOKEN_ISSUED, $request, $refreshToken)); + if ($this->eventDispatcher !== null) { + $this->eventDispatcher->dispatch( + new RequestRefreshTokenEvent(RequestEvent::REFRESH_TOKEN_ISSUED, $request, $refreshToken), + ); + } + $responseType->setRefreshToken($refreshToken); } @@ -281,7 +290,10 @@ public function validateAuthorizationRequest(ServerRequestInterface $request) $this->validateRedirectUri($redirectUri, $client, $request); } elseif (empty($client->getRedirectUri()) || (\is_array($client->getRedirectUri()) && \count($client->getRedirectUri()) !== 1)) { - $this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request)); + if ($this->eventDispatcher !== null) { + $this->eventDispatcher->dispatch(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, + $request)); + } throw OAuthServerException::invalidClient($request); } diff --git a/src/Grant/ClientCredentialsGrant.php b/src/Grant/ClientCredentialsGrant.php index d342b269f..75fd810b6 100644 --- a/src/Grant/ClientCredentialsGrant.php +++ b/src/Grant/ClientCredentialsGrant.php @@ -52,8 +52,10 @@ public function respondToAccessTokenRequest( // Issue and persist access token $accessToken = $this->issueAccessToken($accessTokenTTL, $client, null, $finalizedScopes); - // Send event to emitter - $this->getEmitter()->emit(new RequestAccessTokenEvent(RequestEvent::ACCESS_TOKEN_ISSUED, $request, $accessToken)); + // Send event to eventDispatcher + if ($this->eventDispatcher !== null) { + $this->eventDispatcher->dispatch(new RequestAccessTokenEvent(RequestEvent::ACCESS_TOKEN_ISSUED, $request, $accessToken)); + } // Inject access token into response type $responseType->setAccessToken($accessToken); diff --git a/src/Grant/GrantTypeInterface.php b/src/Grant/GrantTypeInterface.php index 41ebeb5ff..2561538e9 100644 --- a/src/Grant/GrantTypeInterface.php +++ b/src/Grant/GrantTypeInterface.php @@ -13,7 +13,6 @@ use DateInterval; use Defuse\Crypto\Key; -use League\Event\EmitterAwareInterface; use League\OAuth2\Server\CryptKey; use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface; use League\OAuth2\Server\Repositories\ClientRepositoryInterface; @@ -25,7 +24,7 @@ /** * Grant type interface. */ -interface GrantTypeInterface extends EmitterAwareInterface +interface GrantTypeInterface { /** * Set refresh token TTL. diff --git a/src/Grant/PasswordGrant.php b/src/Grant/PasswordGrant.php index fd32d2688..28e88154e 100644 --- a/src/Grant/PasswordGrant.php +++ b/src/Grant/PasswordGrant.php @@ -60,14 +60,21 @@ public function respondToAccessTokenRequest( // Issue and persist new access token $accessToken = $this->issueAccessToken($accessTokenTTL, $client, $user->getIdentifier(), $finalizedScopes); - $this->getEmitter()->emit(new RequestAccessTokenEvent(RequestEvent::ACCESS_TOKEN_ISSUED, $request, $accessToken)); + + if ($this->eventDispatcher !== null ) { + $this->eventDispatcher->dispatch(new RequestAccessTokenEvent(RequestEvent::ACCESS_TOKEN_ISSUED, $request, $accessToken)); + } + $responseType->setAccessToken($accessToken); // Issue and persist new refresh token if given $refreshToken = $this->issueRefreshToken($accessToken); if ($refreshToken !== null) { - $this->getEmitter()->emit(new RequestRefreshTokenEvent(RequestEvent::REFRESH_TOKEN_ISSUED, $request, $refreshToken)); + if ($this->eventDispatcher !== null ) { + $this->eventDispatcher->dispatch(new RequestRefreshTokenEvent(RequestEvent::REFRESH_TOKEN_ISSUED, $request, $refreshToken)); + } + $responseType->setRefreshToken($refreshToken); } @@ -104,7 +111,9 @@ protected function validateUser(ServerRequestInterface $request, ClientEntityInt ); if ($user instanceof UserEntityInterface === false) { - $this->getEmitter()->emit(new RequestEvent(RequestEvent::USER_AUTHENTICATION_FAILED, $request)); + if ($this->eventDispatcher !== null ) { + $this->eventDispatcher->dispatch(new RequestEvent(RequestEvent::USER_AUTHENTICATION_FAILED, $request)); + } throw OAuthServerException::invalidCredentials(); } diff --git a/src/Grant/RefreshTokenGrant.php b/src/Grant/RefreshTokenGrant.php index 2dedf15c3..bcceddc06 100644 --- a/src/Grant/RefreshTokenGrant.php +++ b/src/Grant/RefreshTokenGrant.php @@ -71,7 +71,10 @@ public function respondToAccessTokenRequest( // Issue and persist new access token $accessToken = $this->issueAccessToken($accessTokenTTL, $client, $oldRefreshToken['user_id'], $scopes); - $this->getEmitter()->emit(new RequestAccessTokenEvent(RequestEvent::ACCESS_TOKEN_ISSUED, $request, $accessToken)); + + if ($this->eventDispatcher !== null) { + $this->eventDispatcher->dispatch(new RequestAccessTokenEvent(RequestEvent::ACCESS_TOKEN_ISSUED, $request, $accessToken)); + } $responseType->setAccessToken($accessToken); // Issue and persist new refresh token if given @@ -79,7 +82,10 @@ public function respondToAccessTokenRequest( $refreshToken = $this->issueRefreshToken($accessToken); if ($refreshToken !== null) { - $this->getEmitter()->emit(new RequestRefreshTokenEvent(RequestEvent::REFRESH_TOKEN_ISSUED, $request, $refreshToken)); + if ($this->eventDispatcher !== null) { + $this->eventDispatcher->dispatch(new RequestRefreshTokenEvent(RequestEvent::REFRESH_TOKEN_ISSUED, $request, $refreshToken)); + } + $responseType->setRefreshToken($refreshToken); } } @@ -111,7 +117,9 @@ protected function validateOldRefreshToken(ServerRequestInterface $request, $cli $refreshTokenData = \json_decode($refreshToken, true); if ($refreshTokenData['client_id'] !== $clientId) { - $this->getEmitter()->emit(new RequestEvent(RequestEvent::REFRESH_TOKEN_CLIENT_FAILED, $request)); + if ($this->eventDispatcher !== null ) { + $this->eventDispatcher->dispatch(new RequestEvent(RequestEvent::REFRESH_TOKEN_CLIENT_FAILED, $request)); + } throw OAuthServerException::invalidRefreshToken('Token is not linked to client'); } diff --git a/src/RequestEvent.php b/src/RequestEvent.php index 4f7dad097..f9149aef7 100644 --- a/src/RequestEvent.php +++ b/src/RequestEvent.php @@ -9,10 +9,9 @@ namespace League\OAuth2\Server; -use League\Event\Event; use Psr\Http\Message\ServerRequestInterface; -class RequestEvent extends Event +class RequestEvent { const CLIENT_AUTHENTICATION_FAILED = 'client.authentication.failed'; const USER_AUTHENTICATION_FAILED = 'user.authentication.failed';