Update JWT library to support PHP 8; bumps minimum PHP version for Pterodactyl to 7.4

This commit is contained in:
Dane Everitt
2021-01-20 21:21:28 -08:00
parent 988b711ea2
commit 8dbf60de2c
4 changed files with 134 additions and 66 deletions

View File

@@ -3,12 +3,12 @@
namespace Pterodactyl\Services\Nodes;
use DateTimeImmutable;
use Lcobucci\JWT\Builder;
use Carbon\CarbonImmutable;
use Illuminate\Support\Str;
use Lcobucci\JWT\Signer\Key;
use Pterodactyl\Models\Node;
use Lcobucci\JWT\Configuration;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Signer\Key\InMemory;
class NodeJWTService
{
@@ -68,15 +68,15 @@ class NodeJWTService
* @param \Pterodactyl\Models\Node $node
* @param string|null $identifiedBy
* @param string $algo
* @return \Lcobucci\JWT\Token
* @return \Lcobucci\JWT\Token\Plain
*/
public function handle(Node $node, string $identifiedBy, string $algo = 'md5')
{
$signer = new Sha256;
$identifier = hash($algo, $identifiedBy);
$config = Configuration::forSymmetricSigner(new Sha256, InMemory::plainText($node->getDecryptedKey()));
$builder = (new Builder)->issuedBy(config('app.url'))
$builder = $config->builder()
->issuedBy(config('app.url'))
->permittedFor($node->getConnectionAddress())
->identifiedBy($identifier)
->withHeader('jti', $identifier)
@@ -97,6 +97,6 @@ class NodeJWTService
return $builder
->withClaim('unique_id', Str::random(16))
->getToken($signer, new Key($node->getDecryptedKey()));
->getToken($config->signer(), $config->signingKey());
}
}

View File

@@ -11,7 +11,7 @@
}
],
"require": {
"php": "^7.3|^8.0",
"php": "^7.4 | ^8.0",
"ext-json": "*",
"ext-mbstring": "*",
"ext-pdo_mysql": "*",
@@ -28,7 +28,7 @@
"laravel/helpers": "^1.4",
"laravel/tinker": "^2.5",
"laravel/ui": "^3.0",
"lcobucci/jwt": "^3.4",
"lcobucci/jwt": "^4.0",
"league/flysystem-aws-s3-v3": "^1.0",
"league/flysystem-memory": "^1.0",
"matriphe/iso-639": "^1.2",

144
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "f12494defb79b412566ee0f5104e3986",
"content-hash": "47ce788551352ef0f38290c53bce29dd",
"packages": [
{
"name": "appstract/laravel-blade-directives",
@@ -1754,69 +1754,53 @@
"time": "2021-01-06T19:20:22+00:00"
},
{
"name": "lcobucci/jwt",
"version": "3.4.2",
"name": "lcobucci/clock",
"version": "2.0.0",
"source": {
"type": "git",
"url": "https://github.com/lcobucci/jwt.git",
"reference": "17cb82dd625ccb17c74bf8f38563d3b260306483"
"url": "https://github.com/lcobucci/clock.git",
"reference": "353d83fe2e6ae95745b16b3d911813df6a05bfb3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/lcobucci/jwt/zipball/17cb82dd625ccb17c74bf8f38563d3b260306483",
"reference": "17cb82dd625ccb17c74bf8f38563d3b260306483",
"url": "https://api.github.com/repos/lcobucci/clock/zipball/353d83fe2e6ae95745b16b3d911813df6a05bfb3",
"reference": "353d83fe2e6ae95745b16b3d911813df6a05bfb3",
"shasum": ""
},
"require": {
"ext-mbstring": "*",
"ext-openssl": "*",
"php": "^5.6 || ^7.0"
"php": "^7.4 || ^8.0"
},
"require-dev": {
"mikey179/vfsstream": "~1.5",
"phpmd/phpmd": "~2.2",
"phpunit/php-invoker": "~1.1",
"phpunit/phpunit": "^5.7 || ^7.3",
"squizlabs/php_codesniffer": "~2.3"
},
"suggest": {
"lcobucci/clock": "*"
"infection/infection": "^0.17",
"lcobucci/coding-standard": "^6.0",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^0.12",
"phpstan/phpstan-deprecation-rules": "^0.12",
"phpstan/phpstan-phpunit": "^0.12",
"phpstan/phpstan-strict-rules": "^0.12",
"phpunit/php-code-coverage": "9.1.4",
"phpunit/phpunit": "9.3.7"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.1-dev"
}
},
"autoload": {
"psr-4": {
"Lcobucci\\JWT\\": "src"
},
"files": [
"compat/class-aliases.php",
"compat/json-exception-polyfill.php",
"compat/lcobucci-clock-polyfill.php"
]
"Lcobucci\\Clock\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
"MIT"
],
"authors": [
{
"name": "Luís Otávio Cobucci Oblonczyk",
"email": "lcobucci@gmail.com",
"role": "Developer"
"name": "Luís Cobucci",
"email": "lcobucci@gmail.com"
}
],
"description": "A simple library to work with JSON Web Token and JSON Web Signature",
"keywords": [
"JWS",
"jwt"
],
"description": "Yet another clock abstraction",
"support": {
"issues": "https://github.com/lcobucci/jwt/issues",
"source": "https://github.com/lcobucci/jwt/tree/3.4.2"
"issues": "https://github.com/lcobucci/clock/issues",
"source": "https://github.com/lcobucci/clock/tree/2.0.x"
},
"funding": [
{
@@ -1828,7 +1812,83 @@
"type": "patreon"
}
],
"time": "2020-12-03T13:43:45+00:00"
"time": "2020-08-27T18:56:02+00:00"
},
{
"name": "lcobucci/jwt",
"version": "4.0.0",
"source": {
"type": "git",
"url": "https://github.com/lcobucci/jwt.git",
"reference": "6d8665ccd924dc076a9b65d1ea8abe21d68f6958"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/lcobucci/jwt/zipball/6d8665ccd924dc076a9b65d1ea8abe21d68f6958",
"reference": "6d8665ccd924dc076a9b65d1ea8abe21d68f6958",
"shasum": ""
},
"require": {
"ext-mbstring": "*",
"ext-openssl": "*",
"lcobucci/clock": "^2.0",
"php": "^7.4 || ^8.0"
},
"require-dev": {
"infection/infection": "^0.20",
"lcobucci/coding-standard": "^6.0",
"mikey179/vfsstream": "^1.6",
"phpbench/phpbench": "^0.17",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^0.12",
"phpstan/phpstan-deprecation-rules": "^0.12",
"phpstan/phpstan-phpunit": "^0.12",
"phpstan/phpstan-strict-rules": "^0.12",
"phpunit/php-invoker": "^3.1",
"phpunit/phpunit": "^9.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"psr-4": {
"Lcobucci\\JWT\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Luís Cobucci",
"email": "lcobucci@gmail.com",
"role": "Developer"
}
],
"description": "A simple library to work with JSON Web Token and JSON Web Signature",
"keywords": [
"JWS",
"jwt"
],
"support": {
"issues": "https://github.com/lcobucci/jwt/issues",
"source": "https://github.com/lcobucci/jwt/tree/4.0.0"
},
"funding": [
{
"url": "https://github.com/lcobucci",
"type": "github"
},
{
"url": "https://www.patreon.com/lcobucci",
"type": "patreon"
}
],
"time": "2020-11-25T02:06:12+00:00"
},
{
"name": "league/commonmark",

View File

@@ -3,12 +3,13 @@
namespace Pterodactyl\Tests\Integration\Api\Client\Server;
use Carbon\Carbon;
use Lcobucci\JWT\Parser;
use Carbon\CarbonImmutable;
use Lcobucci\JWT\Signer\Key;
use Illuminate\Http\Response;
use Lcobucci\JWT\Configuration;
use Pterodactyl\Models\Permission;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Signer\Key\InMemory;
use Lcobucci\JWT\Validation\Constraint\SignedWith;
use Pterodactyl\Tests\Integration\Api\Client\ClientApiIntegrationTestCase;
class WebsocketControllerTest extends ClientApiIntegrationTestCase
@@ -52,22 +53,25 @@ class WebsocketControllerTest extends ClientApiIntegrationTestCase
$this->assertStringStartsWith('wss://', $connection, 'Failed asserting that websocket connection address has expected "wss://" prefix.');
$this->assertStringEndsWith("/api/servers/{$server->uuid}/ws", $connection, 'Failed asserting that websocket connection address uses expected Wings endpoint.');
$token = (new Parser)->parse($response->json('data.token'));
$config = Configuration::forSymmetricSigner(new Sha256, $key = InMemory::plainText($server->node->getDecryptedKey()));
$config->setValidationConstraints(new SignedWith(new Sha256, $key));
/** @var \Lcobucci\JWT\Token\Plain $token */
$token = $config->parser()->parse($response->json('data.token'));
$this->assertTrue(
$token->verify(new Sha256, new Key($server->node->getDecryptedKey())),
$config->validator()->validate($token, ...$config->validationConstraints()),
'Failed to validate that the JWT data returned was signed using the Node\'s secret key.'
);
// Check that the claims are generated correctly.
$this->assertSame(config('app.url'), $token->getClaim('iss'));
$this->assertSame($server->node->getConnectionAddress(), $token->getClaim('aud'));
$this->assertSame(CarbonImmutable::now()->getTimestamp(), $token->getClaim('iat'));
$this->assertSame(CarbonImmutable::now()->subMinutes(5)->getTimestamp(), $token->getClaim('nbf'));
$this->assertSame(CarbonImmutable::now()->addMinutes(10)->getTimestamp(), $token->getClaim('exp'));
$this->assertSame($user->id, $token->getClaim('user_id'));
$this->assertSame($server->uuid, $token->getClaim('server_uuid'));
$this->assertSame(['*'], $token->getClaim('permissions'));
$this->assertTrue($token->hasBeenIssuedBy(config('app.url')));
$this->assertTrue($token->isPermittedFor($server->node->getConnectionAddress()));
$this->assertEquals(CarbonImmutable::now()->toDateTimeImmutable(), $token->claims()->get('iat'));
$this->assertEquals(CarbonImmutable::now()->subMinutes(5)->toDateTimeImmutable(), $token->claims()->get('nbf'));
$this->assertEquals(CarbonImmutable::now()->addMinutes(10)->toDateTimeImmutable(), $token->claims()->get('exp'));
$this->assertSame($user->id, $token->claims()->get('user_id'));
$this->assertSame($server->uuid, $token->claims()->get('server_uuid'));
$this->assertSame(['*'], $token->claims()->get('permissions'));
}
/**
@@ -86,14 +90,18 @@ class WebsocketControllerTest extends ClientApiIntegrationTestCase
$response->assertOk();
$response->assertJsonStructure(['data' => ['token', 'socket']]);
$token = (new Parser)->parse($response->json('data.token'));
$config = Configuration::forSymmetricSigner(new Sha256, $key = InMemory::plainText($server->node->getDecryptedKey()));
$config->setValidationConstraints(new SignedWith(new Sha256, $key));
/** @var \Lcobucci\JWT\Token\Plain $token */
$token = $config->parser()->parse($response->json('data.token'));
$this->assertTrue(
$token->verify(new Sha256, new Key($server->node->getDecryptedKey())),
$config->validator()->validate($token, ...$config->validationConstraints()),
'Failed to validate that the JWT data returned was signed using the Node\'s secret key.'
);
// Check that the claims are generated correctly.
$this->assertSame($permissions, $token->getClaim('permissions'));
$this->assertSame($permissions, $token->claims()->get('permissions'));
}
}