diff --git a/examples/src/Repositories/AccessTokenRepository.php b/examples/src/Repositories/AccessTokenRepository.php index affd9be8a..1e6da86a4 100644 --- a/examples/src/Repositories/AccessTokenRepository.php +++ b/examples/src/Repositories/AccessTokenRepository.php @@ -49,11 +49,16 @@ public function isAccessTokenRevoked($tokenId): bool public function getNewToken(ClientEntityInterface $clientEntity, array $scopes, $userIdentifier = null): AccessTokenEntityInterface { $accessToken = new AccessTokenEntity(); + $accessToken->setClient($clientEntity); + foreach ($scopes as $scope) { $accessToken->addScope($scope); } - $accessToken->setUserIdentifier($userIdentifier); + + if ($userIdentifier !== null) { + $accessToken->setUserIdentifier($userIdentifier); + } return $accessToken; } diff --git a/src/Entities/Traits/AccessTokenTrait.php b/src/Entities/Traits/AccessTokenTrait.php index 015002069..99f3cbc9e 100644 --- a/src/Entities/Traits/AccessTokenTrait.php +++ b/src/Entities/Traits/AccessTokenTrait.php @@ -59,12 +59,6 @@ public function initJwtConfiguration(): void */ private function convertToJWT(): Token { - $userIdentifier = $this->getUserIdentifier(); - - if ($userIdentifier === null) { - throw new RuntimeException('JWT access tokens MUST contain a subject identifier'); - } - $this->initJwtConfiguration(); return $this->jwtConfiguration->builder() @@ -73,7 +67,7 @@ private function convertToJWT(): Token ->issuedAt(new DateTimeImmutable()) ->canOnlyBeUsedAfter(new DateTimeImmutable()) ->expiresAt($this->getExpiryDateTime()) - ->relatedTo($userIdentifier) + ->relatedTo($this->getSubjectIdentifier()) ->withClaim('scopes', $this->getScopes()) ->getToken($this->jwtConfiguration->signer(), $this->jwtConfiguration->signingKey()); } @@ -104,4 +98,15 @@ abstract public function getScopes(): array; * @return non-empty-string */ abstract public function getIdentifier(): string; + + private function getSubjectIdentifier(): string + { + $subjectId = $this->getUserIdentifier() ?? $this->getClient()->getIdentifier(); + + if ($subjectId === null) { + throw new RuntimeException('JWT access tokens MUST contain a subject identifier'); + } + + return $subjectId; + } } diff --git a/src/ResponseTypes/BearerTokenResponse.php b/src/ResponseTypes/BearerTokenResponse.php index 0c6107b9e..24ddc8c8e 100644 --- a/src/ResponseTypes/BearerTokenResponse.php +++ b/src/ResponseTypes/BearerTokenResponse.php @@ -34,21 +34,23 @@ public function generateHttpResponse(ResponseInterface $response): ResponseInter 'access_token' => $this->accessToken->toString(), ]; - $refreshTokenPayload = json_encode([ - 'client_id' => $this->accessToken->getClient()->getIdentifier(), - 'refresh_token_id' => $this->refreshToken->getIdentifier(), - 'access_token_id' => $this->accessToken->getIdentifier(), - 'scopes' => $this->accessToken->getScopes(), - 'user_id' => $this->accessToken->getUserIdentifier(), - 'expire_time' => $this->refreshToken->getExpiryDateTime()->getTimestamp(), - ]); - - if ($refreshTokenPayload === false) { - throw new LogicException('Error encountered JSON encoding the refresh token payload'); + if (isset($this->refreshToken)) { + $refreshTokenPayload = json_encode([ + 'client_id' => $this->accessToken->getClient()->getIdentifier(), + 'refresh_token_id' => $this->refreshToken->getIdentifier(), + 'access_token_id' => $this->accessToken->getIdentifier(), + 'scopes' => $this->accessToken->getScopes(), + 'user_id' => $this->accessToken->getUserIdentifier(), + 'expire_time' => $this->refreshToken->getExpiryDateTime()->getTimestamp(), + ]); + + if ($refreshTokenPayload === false) { + throw new LogicException('Error encountered JSON encoding the refresh token payload'); + } + + $responseParams['refresh_token'] = $this->encrypt($refreshTokenPayload); } - - $responseParams['refresh_token'] = $this->encrypt($refreshTokenPayload); - + $responseParams = json_encode(array_merge($this->getExtraParams($this->accessToken), $responseParams)); if ($responseParams === false) {