diff --git a/config/packages/knpu_oauth2_client.yaml b/config/packages/knpu_oauth2_client.yaml index e7e312d3..b43e0bc0 100644 --- a/config/packages/knpu_oauth2_client.yaml +++ b/config/packages/knpu_oauth2_client.yaml @@ -11,7 +11,7 @@ knpu_oauth2_client: type: gitlab client_id: '%env(OAUTH_GITLAB_CLIENT_ID)%' client_secret: '%env(OAUTH_GITLAB_CLIENT_SECRET)%' - redirect_route: register_gitlab_check + redirect_route: package_gitlab_check redirect_params: {} use_state: true domain: '%env(APP_GITLAB_API_URL)%' diff --git a/src/Controller/OAuth/GitLabController.php b/src/Controller/OAuth/GitLabController.php index 1d6bf769..89831420 100644 --- a/src/Controller/OAuth/GitLabController.php +++ b/src/Controller/OAuth/GitLabController.php @@ -25,7 +25,7 @@ public function register(): Response { $this->ensureOAuthRegistrationIsEnabled(); - return $this->oauth->getClient('gitlab')->redirect(['read_user'], []); + return $this->oauth->getClient('gitlab')->redirect(['read_user'], ['redirect_uri' => $this->generateUrl('register_gitlab_check', [], UrlGeneratorInterface::ABSOLUTE_URL)]); } /** diff --git a/src/Entity/User/OAuthToken.php b/src/Entity/User/OAuthToken.php index 40535aca..b874805d 100644 --- a/src/Entity/User/OAuthToken.php +++ b/src/Entity/User/OAuthToken.php @@ -97,6 +97,9 @@ public function accessToken(UserOAuthTokenRefresher $tokenRefresher): string try { $newToken = $tokenRefresher->refresh($this->type, $this->refreshToken); $this->accessToken = $newToken->token(); + if ($newToken->getRefreshToken() !== null) { + $this->refreshToken = $newToken->getRefreshToken(); + } $this->expiresAt = $newToken->expiresAt(); } catch (\Throwable $exception) { throw new \RuntimeException('An error occurred while refreshing the access token: '.$exception->getMessage()); diff --git a/src/Service/User/UserOAuthTokenRefresher.php b/src/Service/User/UserOAuthTokenRefresher.php index ea0277eb..ac9c9cc3 100644 --- a/src/Service/User/UserOAuthTokenRefresher.php +++ b/src/Service/User/UserOAuthTokenRefresher.php @@ -24,6 +24,7 @@ public function refresh(string $type, string $refreshToken): AccessToken return new AccessToken( $accessToken->getToken(), + $accessToken->getRefreshToken(), $accessToken->getExpires() !== null ? (new \DateTimeImmutable())->setTimestamp($accessToken->getExpires()) : null ); } diff --git a/src/Service/User/UserOAuthTokenRefresher/AccessToken.php b/src/Service/User/UserOAuthTokenRefresher/AccessToken.php index 35e4114c..6972d493 100644 --- a/src/Service/User/UserOAuthTokenRefresher/AccessToken.php +++ b/src/Service/User/UserOAuthTokenRefresher/AccessToken.php @@ -8,11 +8,14 @@ class AccessToken { private string $token; + private ?string $refreshToken; + private ?\DateTimeImmutable $expiresAt; - public function __construct(string $token, ?\DateTimeImmutable $expiresAt = null) + public function __construct(string $token, ?string $refreshToken = null, ?\DateTimeImmutable $expiresAt = null) { $this->token = $token; + $this->refreshToken = $refreshToken; $this->expiresAt = $expiresAt; } @@ -21,6 +24,11 @@ public function token(): string return $this->token; } + public function getRefreshToken(): ?string + { + return $this->refreshToken; + } + public function expiresAt(): ?\DateTimeImmutable { return $this->expiresAt; diff --git a/tests/Unit/Entity/User/OAuthTokenTest.php b/tests/Unit/Entity/User/OAuthTokenTest.php index 64eb6bda..a7d98c9e 100644 --- a/tests/Unit/Entity/User/OAuthTokenTest.php +++ b/tests/Unit/Entity/User/OAuthTokenTest.php @@ -33,6 +33,27 @@ public function testExpiredAccessToken(string $modifyTime): void self::assertEquals('new-token', $token->accessToken($this->refresher)); } + public function testAccessTokenDoesUpdateRefreshToken(): void + { + $nowMinusOneDay = (new \DateTimeImmutable())->modify('-1 day'); + $token = OAuthTokenMother::withExpireTime($nowMinusOneDay); + $this->refresher->method('refresh')->withConsecutive( + ['github', 'refresh'], + ['github', 'new-refresh-token1'], + ['github', 'new-refresh-token1'] + )->willReturnOnConsecutiveCalls( + // On second call, "new-refresh-token1" should be used to refresh the token + new AccessToken('new-token1', 'new-refresh-token1', $nowMinusOneDay), + // Do not update the refresh token if its not provided by the oauth refresh endpoint + new AccessToken('new-token2', null, $nowMinusOneDay), + new AccessToken('new-token3') + ); + + self::assertEquals('new-token1', $token->accessToken($this->refresher)); + self::assertEquals('new-token2', $token->accessToken($this->refresher)); + self::assertEquals('new-token3', $token->accessToken($this->refresher)); + } + public function testAccessTokenWithFutureExpirationDate(): void { $token = OAuthTokenMother::withExpireTime((new \DateTimeImmutable())->modify('61 sec')); diff --git a/tests/Unit/Service/User/UserOAuthTokenRefresherTest.php b/tests/Unit/Service/User/UserOAuthTokenRefresherTest.php index eecfe9f0..02d27f84 100644 --- a/tests/Unit/Service/User/UserOAuthTokenRefresherTest.php +++ b/tests/Unit/Service/User/UserOAuthTokenRefresherTest.php @@ -23,13 +23,15 @@ public function testRefreshToken(): void $oauth->method('getClient')->willReturn($client); $provider->method('getAccessToken')->willReturnOnConsecutiveCalls( - new LeagueAccessToken(['access_token' => 'new-token']), - new LeagueAccessToken(['access_token' => 'new-token', 'expires_in' => 3600]) + new LeagueAccessToken(['access_token' => 'new-token-1', 'refresh_token' => 'new-refresh-token-1']), + new LeagueAccessToken(['access_token' => 'new-token-2']), + new LeagueAccessToken(['access_token' => 'new-token-3', 'refresh_token' => 'new-refresh-token-3', 'expires_in' => 3600]) ); $refresher = new UserOAuthTokenRefresher($oauth); - self::assertEquals(new AccessToken('new-token'), $refresher->refresh('github', 'refresh-token')); - self::assertEquals(new AccessToken('new-token', (new \DateTimeImmutable())->setTimestamp(time() + 3600)), $refresher->refresh('github', 'refresh-token')); + self::assertEquals(new AccessToken('new-token-1', 'new-refresh-token-1'), $refresher->refresh('github', 'refresh-token')); + self::assertEquals(new AccessToken('new-token-2'), $refresher->refresh('github', 'refresh-token')); + self::assertEquals(new AccessToken('new-token-3', 'new-refresh-token-3', (new \DateTimeImmutable())->setTimestamp(time() + 3600)), $refresher->refresh('github', 'refresh-token')); } }