diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 43be54264..11a1d1513 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -534,7 +534,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') 'providerUid' => $oauth2ID, 'providerAccessToken' => $accessToken, 'providerRefreshToken' => $refreshToken, - 'providerAccessTokenExpiry' => \time() + $accessTokenExpiry, + 'providerAccessTokenExpiry' => \time() + (int) $accessTokenExpiry, 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak 'expire' => $expiry, 'userAgent' => $request->getUserAgent('UNKNOWN'), diff --git a/app/controllers/mock.php b/app/controllers/mock.php index 526ca4a36..2b667ae7e 100644 --- a/app/controllers/mock.php +++ b/app/controllers/mock.php @@ -10,6 +10,7 @@ use Utopia\Validator\ArrayList; use Utopia\Validator\Integer; use Utopia\Validator\Text; use Utopia\Storage\Validator\File; +use Utopia\Validator\WhiteList; App::get('/v1/mock/tests/foo') ->desc('Get Foo') @@ -478,13 +479,19 @@ App::get('/v1/mock/tests/general/oauth2/token') ->label('docs', false) ->label('sdk.mock', true) ->param('client_id', '', new Text(100), 'OAuth2 Client ID.') - ->param('redirect_uri', '', new Host(['localhost']), 'OAuth2 Redirect URI.') ->param('client_secret', '', new Text(100), 'OAuth2 scope list.') - ->param('code', '', new Text(100), 'OAuth2 state.') + ->param('grant_type', '', new WhiteList(['refresh_token', 'authorization_code']), 'OAuth2 Grant Type.', true) + ->param('redirect_uri', '', new Host(['localhost']), 'OAuth2 Redirect URI.', true) + ->param('code', '', new Text(100), 'OAuth2 state.', true) + ->param('refresh_token', '', new Text(100), 'OAuth2 refresh token.', true) ->inject('response') - ->action(function ($client_id, $redirectURI, $client_secret, $code, $response) { + ->action(function ($client_id, $client_secret, $grantType, $redirectURI, $code, $refreshToken, $response) { /** @var Appwrite\Utopia\Response $response */ + if(empty($grantType)) { + $grantType = 'authorization_code'; + } + if ($client_id != '1') { throw new Exception('Invalid client ID'); } @@ -493,11 +500,27 @@ App::get('/v1/mock/tests/general/oauth2/token') throw new Exception('Invalid client secret'); } - if ($code != 'abcdef') { - throw new Exception('Invalid token'); - } + $responseJson = [ + 'access_token' => '123456', + 'refresh_token' => 'tuvwxyz', + 'expires_in' => 14400 + ]; - $response->json(['access_token' => '123456']); + if($grantType === 'authorization_code') { + if ($code !== 'abcdef') { + throw new Exception('Invalid token'); + } + + $response->json($responseJson); + } else if($grantType === 'refresh_token') { + if ($refreshToken !== 'tuvwxyz') { + throw new Exception('Invalid refresh token'); + } + + $response->json($responseJson); + } else { + throw new Exception('Invalid grant type'); + } }); App::get('/v1/mock/tests/general/oauth2/user') @@ -517,7 +540,7 @@ App::get('/v1/mock/tests/general/oauth2/user') $response->json([ 'id' => 1, 'name' => 'User Name', - 'email' => 'user@localhost.test', + 'email' => 'useroauth@localhost.test', ]); }); diff --git a/tests/e2e/Services/Account/AccountBase.php b/tests/e2e/Services/Account/AccountBase.php index 2b0da9965..41e2150c1 100644 --- a/tests/e2e/Services/Account/AccountBase.php +++ b/tests/e2e/Services/Account/AccountBase.php @@ -3,7 +3,6 @@ namespace Tests\E2E\Services\Account; use Tests\E2E\Client; -use function array_merge; trait AccountBase { diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index 17fb62e95..2b06828a6 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -6,7 +6,7 @@ use Tests\E2E\Client; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\SideClient; -use Utopia\App; +use function sleep; class AccountCustomClientTest extends Scope { @@ -423,7 +423,7 @@ class AccountCustomClientTest extends Scope 'success' => 'http://localhost/v1/mock/tests/general/oauth2/success', 'failure' => 'http://localhost/v1/mock/tests/general/oauth2/failure', ]); - + $session = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']]; $this->assertEquals(200, $response['headers']['status-code']); @@ -439,7 +439,39 @@ class AccountCustomClientTest extends Scope $this->assertEquals($response['headers']['status-code'], 200); $this->assertEquals($response['body']['$id'], $userId); $this->assertEquals($response['body']['name'], 'User Name'); - $this->assertEquals($response['body']['email'], 'user@localhost.test'); + $this->assertEquals($response['body']['email'], 'useroauth@localhost.test'); + + // Since we only support one oauth user, let's also check updateSession here + + $this->assertEquals($response['headers']['status-code'], 200); + + $response = $this->client->call(Client::METHOD_GET, '/account/sessions/current', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + ])); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('123456', $response['body']['providerAccessToken']); + $this->assertEquals('tuvwxyz', $response['body']['providerRefreshToken']); + $this->assertGreaterThan(\time() + 14400 - 5, $response['body']['providerAccessTokenExpiry']); // 5 seconds allowed networking delay + + $initialExpiry = $response['body']['providerAccessTokenExpiry']; + + sleep(3); + + $response = $this->client->call(Client::METHOD_PATCH, '/account/sessions/current', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session, + ])); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('123456', $response['body']['providerAccessToken']); + $this->assertEquals('tuvwxyz', $response['body']['providerRefreshToken']); + $this->assertNotEquals($initialExpiry, $response['body']['providerAccessTokenExpiry']); return []; }