1
0
Fork 0
mirror of synced 2024-06-26 18:20:43 +12:00

Implemented refresh token endpoint

This commit is contained in:
Matej Baco 2022-02-01 16:54:20 +01:00
parent 89834af47d
commit 3aa62b439b
32 changed files with 439 additions and 3 deletions

View file

@ -82,6 +82,11 @@ return [
'model' => Response::MODEL_SESSION,
'note' => '',
],
'account.sessions.udpdate' => [
'description' => 'This event triggers when the account session is updated.',
'model' => Response::MODEL_SESSION,
'note' => '',
],
'database.collections.create' => [
'description' => 'This event triggers when a database collection is created.',
'model' => Response::MODEL_COLLECTION,

View file

@ -23,6 +23,7 @@ use Utopia\Database\Validator\UID;
use Utopia\Exception;
use Utopia\Validator\ArrayList;
use Utopia\Validator\Assoc;
use Utopia\Validator\Boolean;
use Utopia\Validator\Range;
use Utopia\Validator\Text;
use Utopia\Validator\WhiteList;
@ -533,7 +534,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
'providerUid' => $oauth2ID,
'providerAccessToken' => $accessToken,
'providerRefreshToken' => $refreshToken,
'providerAccessTokenExpiry' => $accessTokenExpiry,
'providerAccessTokenExpiry' => \time() + $accessTokenExpiry - 5, // 5 seconds time-sync and networking gap, to be safe
'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak
'expire' => $expiry,
'userAgent' => $request->getUserAgent('UNKNOWN'),
@ -1203,6 +1204,7 @@ App::get('/v1/account/logs')
'account.update.password',
'account.update.prefs',
'account.sessions.create',
'account.sessions.update',
'account.sessions.delete',
'account.recovery.create',
'account.recovery.update',
@ -1598,8 +1600,8 @@ App::delete('/v1/account/sessions/:sessionId')
$protocol = $request->getProtocol();
$sessionId = ($sessionId === 'current')
? Auth::sessionVerify($user->getAttribute('sessions'), Auth::$secret)
: $sessionId;
? Auth::sessionVerify($user->getAttribute('sessions'), Auth::$secret)
: $sessionId;
$sessions = $user->getAttribute('sessions', []);
@ -1652,6 +1654,94 @@ App::delete('/v1/account/sessions/:sessionId')
throw new Exception('Session not found', 404);
});
App::patch('/v1/account/sessions/:sessionId/oauth2-tokens')
->desc('Update OAUth2 Tokens')
->groups(['api', 'account'])
->label('scope', 'account')
->label('event', 'account.sessions.update')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'account')
->label('sdk.method', 'updateOAuth2Tokens')
->label('sdk.description', '/docs/references/account/update-oauth2-tokens.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_SESSION)
->label('abuse-limit', 10)
->param('sessionId', null, new UID(), 'Session ID. Use the string \'current\' to update the current device session.')
->param('force', true, new Boolean(), 'Should generate new token even if current one is still valid?', true)
->inject('request')
->inject('response')
->inject('user')
->inject('dbForProject')
->inject('project')
->inject('locale')
->inject('audits')
->inject('events')
->inject('usage')
->action(function ($sessionId, $force, $request, $response, $user, $dbForProject, $project, $locale, $audits, $events, $usage) {
/** @var Appwrite\Utopia\Request $request */
/** @var boolean $force */
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $user */
/** @var Utopia\Database\Database $dbForProject */
/** @var Utopia\Database\Document $project */
/** @var Utopia\Locale\Locale $locale */
/** @var Appwrite\Event\Event $audits */
/** @var Appwrite\Event\Event $events */
/** @var Appwrite\Stats\Stats $usage */
$sessionId = ($sessionId === 'current')
? Auth::sessionVerify($user->getAttribute('sessions'), Auth::$secret)
: $sessionId;
$sessions = $user->getAttribute('sessions', []);
foreach ($sessions as $key => $session) {/** @var Document $session */
if ($sessionId == $session->getId()) {
$provider = $session->getAttribute('provider');
$refreshToken = $session->getAttribute('providerRefreshToken');
$appId = $project->getAttribute('providers', [])[$provider.'Appid'] ?? '';
$appSecret = $project->getAttribute('providers', [])[$provider.'Secret'] ?? '{}';
$className = 'Appwrite\\Auth\\OAuth2\\'.\ucfirst($provider);
$oauth2 = new $className($appId, $appSecret, '', [], []);
$oauth2->refreshTokens($refreshToken);
\var_dump($oauth2->getAccessToken(''));
\var_dump($oauth2->getRefreshToken(''));
$session
->setAttribute('providerAccessToken', $oauth2->getAccessToken(''))
->setAttribute('providerRefreshToken', $oauth2->getRefreshToken(''))
->setAttribute('providerAccessTokenExpiry', \time() + $oauth2->getAccessTokenExpiry('') - 5) // 5 seconds time-sync and networking gap, to be safe
;
$session = $dbForProject->updateDocument('sessions', $sessionId, $session);
$audits
->setParam('userId', $user->getId())
->setParam('event', 'account.sessions.update')
->setParam('resource', 'user/' . $user->getId())
;
$events
->setParam('eventData', $response->output($session, Response::MODEL_SESSION))
;
$usage
->setParam('users.sessions.update', 1)
->setParam('users.update', 1)
;
$response->dynamic($session, Response::MODEL_SESSION);
}
}
throw new Exception('Session not found', 404);
});
App::delete('/v1/account/sessions')
->desc('Delete All Account Sessions')
->groups(['api', 'account'])

View file

@ -289,6 +289,7 @@ App::get('/v1/users/:userId/logs')
'account.update.password',
'account.update.prefs',
'account.sessions.create',
'account.sessions.update',
'account.sessions.delete',
'account.recovery.create',
'account.recovery.update',

View file

@ -66,6 +66,13 @@ abstract class OAuth2
*/
abstract public function getTokens(string $code):array;
/**
* @param string $refreshToken
*
* @return array
*/
abstract public function refreshTokens(string $refreshToken):array;
/**
* @param $accessToken
*

View file

@ -87,6 +87,18 @@ class Amazon extends OAuth2
return $this->tokens;
}
/**
* @param string $refreshToken
*
* @return array
*/
public function refreshTokens(string $refreshToken):array
{
// TODO: Implement (Twitch as example)
return $this->tokens;
}
/**
* @param string $accessToken
*

View file

@ -85,6 +85,18 @@ class Apple extends OAuth2
return $this->tokens;
}
/**
* @param string $refreshToken
*
* @return array
*/
public function refreshTokens(string $refreshToken):array
{
// TODO: Implement (Twitch as example)
return $this->tokens;
}
/**
* @param string $accessToken
*

View file

@ -71,6 +71,18 @@ class Bitbucket extends OAuth2
return $this->tokens;
}
/**
* @param string $refreshToken
*
* @return array
*/
public function refreshTokens(string $refreshToken):array
{
// TODO: Implement (Twitch as example)
return $this->tokens;
}
/**
* @param string $accessToken
*

View file

@ -81,6 +81,18 @@ class Bitly extends OAuth2
return $this->tokens;
}
/**
* @param string $refreshToken
*
* @return array
*/
public function refreshTokens(string $refreshToken):array
{
// TODO: Implement (Twitch as example)
return $this->tokens;
}
/**
* @param $accessToken
*

View file

@ -88,6 +88,18 @@ class Box extends OAuth2
return $this->tokens;
}
/**
* @param string $refreshToken
*
* @return array
*/
public function refreshTokens(string $refreshToken):array
{
// TODO: Implement (Twitch as example)
return $this->tokens;
}
/**
* @param string $accessToken
*

View file

@ -83,6 +83,18 @@ class Discord extends OAuth2
return $this->tokens;
}
/**
* @param string $refreshToken
*
* @return array
*/
public function refreshTokens(string $refreshToken):array
{
// TODO: Implement (Twitch as example)
return $this->tokens;
}
/**
* @param string $accessToken
*

View file

@ -72,6 +72,18 @@ class Dropbox extends OAuth2
return $this->tokens;
}
/**
* @param string $refreshToken
*
* @return array
*/
public function refreshTokens(string $refreshToken):array
{
// TODO: Implement (Twitch as example)
return $this->tokens;
}
/**
* @param string $accessToken
*

View file

@ -71,6 +71,18 @@ class Facebook extends OAuth2
return $this->tokens;
}
/**
* @param string $refreshToken
*
* @return array
*/
public function refreshTokens(string $refreshToken):array
{
// TODO: Implement (Twitch as example)
return $this->tokens;
}
/**
* @param string $accessToken
*

View file

@ -68,6 +68,18 @@ class Github extends OAuth2
return $this->tokens;
}
/**
* @param string $refreshToken
*
* @return array
*/
public function refreshTokens(string $refreshToken):array
{
// TODO: Implement (Twitch as example)
return $this->tokens;
}
/**
* @param $accessToken
*

View file

@ -71,6 +71,18 @@ class Gitlab extends OAuth2
return $this->tokens;
}
/**
* @param string $refreshToken
*
* @return array
*/
public function refreshTokens(string $refreshToken):array
{
// TODO: Implement (Twitch as example)
return $this->tokens;
}
/**
* @param string $accessToken
*

View file

@ -81,6 +81,18 @@ class Google extends OAuth2
return $this->tokens;
}
/**
* @param string $refreshToken
*
* @return array
*/
public function refreshTokens(string $refreshToken):array
{
// TODO: Implement (Twitch as example)
return $this->tokens;
}
/**
* @param string $accessToken
*

View file

@ -84,6 +84,18 @@ class Linkedin extends OAuth2
return $this->tokens;
}
/**
* @param string $refreshToken
*
* @return array
*/
public function refreshTokens(string $refreshToken):array
{
// TODO: Implement (Twitch as example)
return $this->tokens;
}
/**
* @param $accessToken
*

View file

@ -78,6 +78,18 @@ class Microsoft extends OAuth2
return $this->tokens;
}
/**
* @param string $refreshToken
*
* @return array
*/
public function refreshTokens(string $refreshToken):array
{
// TODO: Implement (Twitch as example)
return $this->tokens;
}
/**
* @param string $accessToken
*

View file

@ -72,6 +72,18 @@ class Mock extends OAuth2
return $this->tokens;
}
/**
* @param string $refreshToken
*
* @return array
*/
public function refreshTokens(string $refreshToken):array
{
// TODO: Implement (Twitch as example)
return $this->tokens;
}
/**
* @param string $accessToken
*

View file

@ -77,6 +77,18 @@ class Notion extends OAuth2
return $this->tokens;
}
/**
* @param string $refreshToken
*
* @return array
*/
public function refreshTokens(string $refreshToken):array
{
// TODO: Implement (Twitch as example)
return $this->tokens;
}
/**
* @param $accessToken
*

View file

@ -98,6 +98,18 @@ class Paypal extends OAuth2
return $this->tokens;
}
/**
* @param string $refreshToken
*
* @return array
*/
public function refreshTokens(string $refreshToken):array
{
// TODO: Implement (Twitch as example)
return $this->tokens;
}
/**
* @param string $accessToken
*

View file

@ -88,6 +88,18 @@ class Salesforce extends OAuth2
return $this->tokens;
}
/**
* @param string $refreshToken
*
* @return array
*/
public function refreshTokens(string $refreshToken):array
{
// TODO: Implement (Twitch as example)
return $this->tokens;
}
/**
* @param string $accessToken
*

View file

@ -71,6 +71,18 @@ class Slack extends OAuth2
return $this->tokens;
}
/**
* @param string $refreshToken
*
* @return array
*/
public function refreshTokens(string $refreshToken):array
{
// TODO: Implement (Twitch as example)
return $this->tokens;
}
/**
* @param string $accessToken
*

View file

@ -84,6 +84,18 @@ class Spotify extends OAuth2
return $this->tokens;
}
/**
* @param string $refreshToken
*
* @return array
*/
public function refreshTokens(string $refreshToken):array
{
// TODO: Implement (Twitch as example)
return $this->tokens;
}
/**
* @param $accessToken
*

View file

@ -83,6 +83,18 @@ class Stripe extends OAuth2
return $this->tokens;
}
/**
* @param string $refreshToken
*
* @return array
*/
public function refreshTokens(string $refreshToken):array
{
// TODO: Implement (Twitch as example)
return $this->tokens;
}
/**
* @param $accessToken
*

View file

@ -93,6 +93,18 @@ class Tradeshift extends OAuth2
return $this->tokens;
}
/**
* @param string $refreshToken
*
* @return array
*/
public function refreshTokens(string $refreshToken):array
{
// TODO: Implement (Twitch as example)
return $this->tokens;
}
/**
* @param string $accessToken
*

View file

@ -84,6 +84,26 @@ class Twitch extends OAuth2
return $this->tokens;
}
/**
* @param string $refreshToken
*
* @return array
*/
public function refreshTokens(string $refreshToken):array
{
$this->tokens = \json_decode($this->request(
'POST',
$this->endpoint . 'token?' . \http_build_query([
"client_id" => $this->appID,
"client_secret" => $this->appSecret,
"refresh_token" => $refreshToken,
"grant_type" => "refresh_token",
])
), true);
return $this->tokens;
}
/**
* @param $accessToken
*

View file

@ -87,6 +87,18 @@ class Vk extends OAuth2
return $this->tokens;
}
/**
* @param string $refreshToken
*
* @return array
*/
public function refreshTokens(string $refreshToken):array
{
// TODO: Implement (Twitch as example)
return $this->tokens;
}
/**
* @param string $accessToken
*

View file

@ -73,6 +73,18 @@ class WordPress extends OAuth2
return $this->tokens;
}
/**
* @param string $refreshToken
*
* @return array
*/
public function refreshTokens(string $refreshToken):array
{
// TODO: Implement (Twitch as example)
return $this->tokens;
}
/**
* @param $accessToken
*

View file

@ -100,6 +100,18 @@ class Yahoo extends OAuth2
return $this->tokens;
}
/**
* @param string $refreshToken
*
* @return array
*/
public function refreshTokens(string $refreshToken):array
{
// TODO: Implement (Twitch as example)
return $this->tokens;
}
/**
* @param $accessToken
*

View file

@ -71,6 +71,18 @@ class Yammer extends OAuth2
return $this->tokens;
}
/**
* @param string $refreshToken
*
* @return array
*/
public function refreshTokens(string $refreshToken):array
{
// TODO: Implement (Twitch as example)
return $this->tokens;
}
/**
* @param string $accessToken
*

View file

@ -84,6 +84,18 @@ class Yandex extends OAuth2
return $this->tokens;
}
/**
* @param string $refreshToken
*
* @return array
*/
public function refreshTokens(string $refreshToken):array
{
// TODO: Implement (Twitch as example)
return $this->tokens;
}
/**
* @param string $accessToken
*

View file

@ -107,6 +107,7 @@ trait ProjectCustom
'account.verification.update',
'account.delete',
'account.sessions.create',
'account.sessions.update',
'account.sessions.delete',
'database.collections.create',
'database.collections.update',