From 711e26c605ea52220dc83594de0300721c5c6a20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Tue, 28 May 2024 10:59:53 +0000 Subject: [PATCH] Relay on lib to verify JWT expiry --- app/controllers/api/account.php | 3 ++- app/controllers/api/functions.php | 6 ++++-- app/controllers/api/messaging.php | 4 ++-- app/controllers/api/storage.php | 9 ++------- app/controllers/api/users.php | 3 ++- app/controllers/shared/api.php | 6 +----- app/init.php | 18 +----------------- src/Appwrite/Platform/Workers/Functions.php | 3 ++- 8 files changed, 16 insertions(+), 36 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 35f8979b25..96b169bbbb 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -2370,11 +2370,12 @@ App::post('/v1/account/jwts') throw new Exception(Exception::USER_SESSION_NOT_FOUND); } - $jwt = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 10); // Instantiate with key, algo, maxAge and leeway. + $jwt = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 0); $response ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic(new Document(['jwt' => $jwt->encode([ + 'iat' => \time(), 'exp' => \intval((new \DateTime())->add(new \DateInterval('PT900S'))->format('U')), 'userId' => $user->getId(), 'sessionId' => $current->getId(), diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index 8787cba8dc..04375a6b71 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -1586,8 +1586,9 @@ App::post('/v1/functions/:functionId/executions') if (!$current->isEmpty()) { $jwtExpiry = $function->getAttribute('timeout', 900); - $jwtObj = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 10); // Instantiate with key, algo, maxAge and leeway. + $jwtObj = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 0); $jwt = $jwtObj->encode([ + 'iat' => \time(), 'exp' => \intval((new \DateTime())->add(new \DateInterval('PT' . $jwtExpiry . 'S'))->format('U')), 'userId' => $user->getId(), 'sessionId' => $current->getId(), @@ -1596,8 +1597,9 @@ App::post('/v1/functions/:functionId/executions') } $jwtExpiry = $function->getAttribute('timeout', 900); - $jwtObj = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 10); + $jwtObj = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 0); $apiKey = $jwtObj->encode([ + 'iat' => \time(), 'exp' => \intval((new \DateTime())->add(new \DateInterval('PT' . $jwtExpiry . 'S'))->format('U')), 'projectId' => $project->getId(), 'scopes' => $function->getAttribute('scopes', []) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index fc8f9292be..5676454abf 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -2939,7 +2939,7 @@ App::post('/v1/messaging/messages/push') $expiry = (new \DateTime())->add(new \DateInterval('P15D'))->format('U'); } - $encoder = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 10); + $encoder = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 0); $jwt = $encoder->encode([ 'iat' => \time(), @@ -3801,7 +3801,7 @@ App::patch('/v1/messaging/messages/push/:messageId') $expiry = (new \DateTime())->add(new \DateInterval('P15D'))->format('U'); } - $encoder = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 10); + $encoder = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 0); $jwt = $encoder->encode([ 'iat' => \time(), diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index cba55b8c87..8ee7386d98 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -1328,7 +1328,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/push') ->action(function (string $bucketId, string $fileId, string $jwt, Response $response, Request $request, Database $dbForProject, Document $project, string $mode, Device $deviceForFiles) { $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $decoder = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 10); + $decoder = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 0); try { $decoded = $decoder->decode($jwt); @@ -1336,15 +1336,10 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/push') throw new Exception(Exception::USER_UNAUTHORIZED); } - if($decoded['exp'] < \time()) { - throw new Exception(Exception::USER_UNAUTHORIZED); - } - if ( $decoded['projectId'] !== $project->getId() || $decoded['bucketId'] !== $bucketId || - $decoded['fileId'] !== $fileId || - $decoded['exp'] < \time() + $decoded['fileId'] !== $fileId ) { throw new Exception(Exception::USER_UNAUTHORIZED); } diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 02a9d45962..5d7865b45b 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -2136,11 +2136,12 @@ App::post('/v1/users/:userId/jwts') throw new Exception(Exception::USER_SESSION_NOT_FOUND); } - $jwt = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 10); // Instantiate with key, algo, maxAge and leeway. + $jwt = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 0); $response ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic(new Document(['jwt' => $jwt->encode([ + 'iat' => \time(), 'exp' => \intval((new \DateTime())->add(new \DateInterval('PT' . $duration . 'S'))->format('U')), 'userId' => $user->getId(), 'sessionId' => $session->getId() diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 3a1bfce7e2..f3351443c9 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -216,7 +216,7 @@ App::init() if($keyType === API_KEY_DYNAMIC) { // Dynamic key - $jwtObj = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 10); + $jwtObj = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 0); try { $payload = $jwtObj->decode($authKey); @@ -224,10 +224,6 @@ App::init() throw new Exception(Exception::API_KEY_EXPIRED); } - if($payload['exp'] < \time()) { - throw new Exception(Exception::API_KEY_EXPIRED); - } - $projectId = $payload['projectId'] ?? ''; $tokenScopes = $payload['scopes'] ?? []; diff --git a/app/init.php b/app/init.php index 7fda855d72..c43e60b5cf 100644 --- a/app/init.php +++ b/app/init.php @@ -1200,7 +1200,7 @@ App::setResource('user', function ($mode, $project, $console, $request, $respons $authJWT = $request->getHeader('x-appwrite-jwt', ''); if (!empty($authJWT) && !$project->isEmpty()) { // JWT authentication - $jwt = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 10); // Instantiate with key, algo, maxAge and leeway. + $jwt = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 0); try { $payload = $jwt->decode($authJWT); @@ -1218,22 +1218,6 @@ App::setResource('user', function ($mode, $project, $console, $request, $respons if (empty($user->find('$id', $jwtSessionId, 'sessions'))) { // Match JWT to active token $user = new Document([]); } - - $exp = $payload['exp'] ?? ''; - - // Fallback to 15m, just in case - if(empty($exp)) { - $jwt = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 900, 10); // Instantiate with key, algo, maxAge and leeway. - try { - $payload = $jwt->decode($authJWT); - } catch (JWTException $error) { - $user = new Document([]); - } - } else { - if($exp < \time()) { - $user = new Document([]); - } - } } $dbForProject->setMetadata('user', $user->getId()); diff --git a/src/Appwrite/Platform/Workers/Functions.php b/src/Appwrite/Platform/Workers/Functions.php index 7b0d45e3c5..c281b10b37 100644 --- a/src/Appwrite/Platform/Workers/Functions.php +++ b/src/Appwrite/Platform/Workers/Functions.php @@ -284,8 +284,9 @@ class Functions extends Action $runtime = $runtimes[$function->getAttribute('runtime')]; $jwtExpiry = $function->getAttribute('timeout', 900); - $jwtObj = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 10); + $jwtObj = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 0); $apiKey = $jwtObj->encode([ + 'iat' => \time(), 'exp' => \intval((new \DateTime())->add(new \DateInterval('PT' . $jwtExpiry . 'S'))->format('U')), 'projectId' => $project->getId(), 'scopes' => $function->getAttribute('scopes', [])