|
4 | 4 |
|
5 | 5 | namespace Longman\LaravelLodash\Auth\Passport\Grants;
|
6 | 6 |
|
| 7 | +use DateInterval; |
7 | 8 | use League\OAuth2\Server\Entities\ClientEntityInterface;
|
8 | 9 | use League\OAuth2\Server\Exception\OAuthServerException;
|
9 | 10 | use League\OAuth2\Server\Grant\RefreshTokenGrant;
|
| 11 | +use League\OAuth2\Server\RequestAccessTokenEvent; |
10 | 12 | use League\OAuth2\Server\RequestEvent;
|
| 13 | +use League\OAuth2\Server\RequestRefreshTokenEvent; |
| 14 | +use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface; |
| 15 | +use Longman\LaravelLodash\Auth\Contracts\AuthServiceContract; |
| 16 | +use Longman\LaravelLodash\Auth\Contracts\RefreshTokenBridgeRepositoryContract; |
| 17 | +use Longman\LaravelLodash\Auth\Contracts\TokenRepositoryContract; |
11 | 18 | use Psr\Http\Message\ServerRequestInterface;
|
12 | 19 |
|
| 20 | +use function implode; |
| 21 | +use function in_array; |
13 | 22 | use function is_null;
|
14 | 23 |
|
15 | 24 | class InternalRefreshTokenGrant extends RefreshTokenGrant
|
16 | 25 | {
|
| 26 | + private readonly TokenRepositoryContract $tokenRepository; |
| 27 | + private readonly AuthServiceContract $authService; |
| 28 | + |
| 29 | + public function __construct( |
| 30 | + RefreshTokenBridgeRepositoryContract $refreshTokenRepository, |
| 31 | + TokenRepositoryContract $tokenRepository, |
| 32 | + AuthServiceContract $authService, |
| 33 | + ) { |
| 34 | + parent::__construct($refreshTokenRepository); |
| 35 | + |
| 36 | + $this->tokenRepository = $tokenRepository; |
| 37 | + $this->authService = $authService; |
| 38 | + } |
| 39 | + |
17 | 40 | public function getIdentifier(): string
|
18 | 41 | {
|
19 | 42 | return 'internal_refresh_token';
|
20 | 43 | }
|
21 | 44 |
|
| 45 | + /** |
| 46 | + * {@inheritdoc} |
| 47 | + */ |
| 48 | + public function respondToAccessTokenRequest( |
| 49 | + ServerRequestInterface $request, |
| 50 | + ResponseTypeInterface $responseType, |
| 51 | + DateInterval $accessTokenTTL, |
| 52 | + ) { |
| 53 | + // Validate request |
| 54 | + $client = $this->validateClient($request); |
| 55 | + $oldRefreshToken = $this->validateOldRefreshToken($request, $client->getIdentifier()); |
| 56 | + $scopes = $this->validateScopes( |
| 57 | + $this->getRequestParameter( |
| 58 | + 'scope', |
| 59 | + $request, |
| 60 | + implode(self::SCOPE_DELIMITER_STRING, $oldRefreshToken['scopes']), |
| 61 | + ), |
| 62 | + ); |
| 63 | + |
| 64 | + // The OAuth spec says that a refreshed access token can have the original scopes or fewer so ensure |
| 65 | + // the request doesn't include any new scopes |
| 66 | + foreach ($scopes as $scope) { |
| 67 | + if (in_array($scope->getIdentifier(), $oldRefreshToken['scopes'], true) === false) { |
| 68 | + throw OAuthServerException::invalidScope($scope->getIdentifier()); |
| 69 | + } |
| 70 | + } |
| 71 | + |
| 72 | + // Expire old tokens |
| 73 | + $this->accessTokenRepository->revokeAccessToken($oldRefreshToken['access_token_id']); |
| 74 | + if ($this->revokeRefreshTokens) { |
| 75 | + $this->refreshTokenRepository->revokeRefreshToken($oldRefreshToken['refresh_token_id']); |
| 76 | + } |
| 77 | + |
| 78 | + // Issue and persist new access token |
| 79 | + $accessToken = $this->issueAccessToken($accessTokenTTL, $client, $oldRefreshToken['user_id'], $scopes); |
| 80 | + $this->getEmitter()->emit(new RequestAccessTokenEvent(RequestEvent::ACCESS_TOKEN_ISSUED, $request, $accessToken)); |
| 81 | + $responseType->setAccessToken($accessToken); |
| 82 | + |
| 83 | + // Issue and persist new refresh token if given |
| 84 | + if ($this->revokeRefreshTokens) { |
| 85 | + $refreshToken = $this->issueRefreshToken($accessToken); |
| 86 | + |
| 87 | + if ($refreshToken !== null) { |
| 88 | + $this->getEmitter()->emit(new RequestRefreshTokenEvent(RequestEvent::REFRESH_TOKEN_ISSUED, $request, $refreshToken)); |
| 89 | + $responseType->setRefreshToken($refreshToken); |
| 90 | + } |
| 91 | + } |
| 92 | + |
| 93 | + // when emulated user requests new access token. set emulator user id. |
| 94 | + $oldAccessToken = $this->tokenRepository->find($oldRefreshToken['access_token_id']); |
| 95 | + if ($oldAccessToken->emulator_user_id) { |
| 96 | + $this->authService->updateAccessToken($accessToken->getIdentifier(), $oldAccessToken->emulator_user_id); |
| 97 | + } |
| 98 | + |
| 99 | + return $responseType; |
| 100 | + } |
| 101 | + |
22 | 102 | protected function validateClient(ServerRequestInterface $request): ClientEntityInterface
|
23 | 103 | {
|
24 | 104 | [$basicAuthUser,] = $this->getBasicAuthCredentials($request);
|
|
0 commit comments