composer update + update jwt (#1587)

This commit is contained in:
Charles 2025-08-11 16:57:59 -04:00 committed by GitHub
parent 27a8423f55
commit b03d2cf919
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 111 additions and 167 deletions

View File

@ -2,16 +2,16 @@
namespace App\Services\Nodes; namespace App\Services\Nodes;
use App\Extensions\Lcobucci\JWT\Encoding\TimestampDates;
use Carbon\CarbonImmutable; use Carbon\CarbonImmutable;
use DateTimeImmutable; use DateTimeImmutable;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use App\Models\Node; use App\Models\Node;
use App\Models\User; use App\Models\User;
use Lcobucci\JWT\Token\Plain;
use Lcobucci\JWT\Configuration; use Lcobucci\JWT\Configuration;
use Lcobucci\JWT\Signer\Hmac\Sha256; use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Signer\Key\InMemory; use Lcobucci\JWT\Signer\Key\InMemory;
use App\Extensions\Lcobucci\JWT\Encoding\TimestampDates; use Lcobucci\JWT\UnencryptedToken;
class NodeJWTService class NodeJWTService
{ {
@ -64,7 +64,7 @@ class NodeJWTService
/** /**
* Generate a new JWT for a given node. * Generate a new JWT for a given node.
*/ */
public function handle(Node $node, ?string $identifiedBy, string $algo = 'md5'): Plain public function handle(Node $node, ?string $identifiedBy, string $algo = 'sha256'): UnencryptedToken
{ {
$identifier = hash($algo, $identifiedBy); $identifier = hash($algo, $identifiedBy);
$config = Configuration::forSymmetricSigner(new Sha256(), InMemory::plainText($node->daemon_token)); $config = Configuration::forSymmetricSigner(new Sha256(), InMemory::plainText($node->daemon_token));
@ -80,7 +80,9 @@ class NodeJWTService
$builder = $builder->expiresAt($this->expiresAt); $builder = $builder->expiresAt($this->expiresAt);
if (!empty($this->subject)) { if (!empty($this->subject)) {
$builder = $builder->relatedTo($this->subject)->withHeader('sub', $this->subject); $builder = $builder
->relatedTo($this->subject)
->withHeader('sub', $this->subject);
} }
foreach ($this->claims as $key => $value) { foreach ($this->claims as $key => $value) {
@ -88,14 +90,7 @@ class NodeJWTService
} }
if (!is_null($this->user)) { if (!is_null($this->user)) {
$builder = $builder $builder = $builder->withClaim('user_uuid', $this->user->uuid);
->withClaim('user_uuid', $this->user->uuid)
// The "user_id" claim is deprecated and should not be referenced — it remains
// here solely to ensure older versions of daemon are unaffected when the Panel
// is updated.
//
// This claim will be removed in Panel@1.11 or later.
->withClaim('user_id', $this->user->id);
} }
return $builder return $builder

View File

@ -10,7 +10,7 @@ use App\Services\Nodes\NodeJWTService;
use Carbon\CarbonImmutable; use Carbon\CarbonImmutable;
use Illuminate\Database\ConnectionInterface; use Illuminate\Database\ConnectionInterface;
use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Http;
use Lcobucci\JWT\Token\Plain; use Lcobucci\JWT\UnencryptedToken;
class TransferServerService class TransferServerService
{ {
@ -22,7 +22,7 @@ class TransferServerService
private NodeJWTService $nodeJWTService, private NodeJWTService $nodeJWTService,
) {} ) {}
private function notify(ServerTransfer $transfer, Plain $token): void private function notify(ServerTransfer $transfer, UnencryptedToken $token): void
{ {
Http::daemon($transfer->oldNode)->post("/api/servers/{$transfer->server->uuid}/transfer", [ Http::daemon($transfer->oldNode)->post("/api/servers/{$transfer->server->uuid}/transfer", [
'url' => $transfer->newNode->getConnectionAddress() . '/api/transfers', 'url' => $transfer->newNode->getConnectionAddress() . '/api/transfers',

View File

@ -23,7 +23,7 @@
"laravel/socialite": "^5.21", "laravel/socialite": "^5.21",
"laravel/tinker": "^2.10.1", "laravel/tinker": "^2.10.1",
"laravel/ui": "^4.6", "laravel/ui": "^4.6",
"lcobucci/jwt": "~4.3.0", "lcobucci/jwt": "^5.5",
"league/flysystem-aws-s3-v3": "^3.29", "league/flysystem-aws-s3-v3": "^3.29",
"league/flysystem-memory": "^3.29", "league/flysystem-memory": "^3.29",
"phpseclib/phpseclib": "~3.0.18", "phpseclib/phpseclib": "~3.0.18",

192
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "7138d3f3e583251a87fcbf5157c43315", "content-hash": "e5d9f294519edc6e4cca937c579709f8",
"packages": [ "packages": [
{ {
"name": "abdelhamiderrahmouni/filament-monaco-editor", "name": "abdelhamiderrahmouni/filament-monaco-editor",
@ -1020,16 +1020,16 @@
}, },
{ {
"name": "aws/aws-sdk-php", "name": "aws/aws-sdk-php",
"version": "3.352.4", "version": "3.352.5",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/aws/aws-sdk-php.git", "url": "https://github.com/aws/aws-sdk-php.git",
"reference": "d3ce2a85687d55cd67d52682306227bc6aa836d6" "reference": "e226dcc96c0a1165d9c8248ec637d1006b883609"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/d3ce2a85687d55cd67d52682306227bc6aa836d6", "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/e226dcc96c0a1165d9c8248ec637d1006b883609",
"reference": "d3ce2a85687d55cd67d52682306227bc6aa836d6", "reference": "e226dcc96c0a1165d9c8248ec637d1006b883609",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1111,9 +1111,9 @@
"support": { "support": {
"forum": "https://github.com/aws/aws-sdk-php/discussions", "forum": "https://github.com/aws/aws-sdk-php/discussions",
"issues": "https://github.com/aws/aws-sdk-php/issues", "issues": "https://github.com/aws/aws-sdk-php/issues",
"source": "https://github.com/aws/aws-sdk-php/tree/3.352.4" "source": "https://github.com/aws/aws-sdk-php/tree/3.352.5"
}, },
"time": "2025-08-07T18:15:55+00:00" "time": "2025-08-08T18:09:38+00:00"
}, },
{ {
"name": "blade-ui-kit/blade-heroicons", "name": "blade-ui-kit/blade-heroicons",
@ -2258,33 +2258,32 @@
}, },
{ {
"name": "doctrine/inflector", "name": "doctrine/inflector",
"version": "2.0.10", "version": "2.1.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/doctrine/inflector.git", "url": "https://github.com/doctrine/inflector.git",
"reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc" "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/doctrine/inflector/zipball/5817d0659c5b50c9b950feb9af7b9668e2c436bc", "url": "https://api.github.com/repos/doctrine/inflector/zipball/6d6c96277ea252fc1304627204c3d5e6e15faa3b",
"reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc", "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": "^7.2 || ^8.0" "php": "^7.2 || ^8.0"
}, },
"require-dev": { "require-dev": {
"doctrine/coding-standard": "^11.0", "doctrine/coding-standard": "^12.0 || ^13.0",
"phpstan/phpstan": "^1.8", "phpstan/phpstan": "^1.12 || ^2.0",
"phpstan/phpstan-phpunit": "^1.1", "phpstan/phpstan-phpunit": "^1.4 || ^2.0",
"phpstan/phpstan-strict-rules": "^1.3", "phpstan/phpstan-strict-rules": "^1.6 || ^2.0",
"phpunit/phpunit": "^8.5 || ^9.5", "phpunit/phpunit": "^8.5 || ^12.2"
"vimeo/psalm": "^4.25 || ^5.4"
}, },
"type": "library", "type": "library",
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"Doctrine\\Inflector\\": "lib/Doctrine/Inflector" "Doctrine\\Inflector\\": "src"
} }
}, },
"notification-url": "https://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
@ -2329,7 +2328,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/doctrine/inflector/issues", "issues": "https://github.com/doctrine/inflector/issues",
"source": "https://github.com/doctrine/inflector/tree/2.0.10" "source": "https://github.com/doctrine/inflector/tree/2.1.0"
}, },
"funding": [ "funding": [
{ {
@ -2345,7 +2344,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-02-18T20:23:39+00:00" "time": "2025-08-10T19:31:58+00:00"
}, },
{ {
"name": "doctrine/lexer", "name": "doctrine/lexer",
@ -4373,105 +4372,40 @@
}, },
"time": "2025-01-28T15:15:29+00:00" "time": "2025-01-28T15:15:29+00:00"
}, },
{
"name": "lcobucci/clock",
"version": "3.3.1",
"source": {
"type": "git",
"url": "https://github.com/lcobucci/clock.git",
"reference": "db3713a61addfffd615b79bf0bc22f0ccc61b86b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/lcobucci/clock/zipball/db3713a61addfffd615b79bf0bc22f0ccc61b86b",
"reference": "db3713a61addfffd615b79bf0bc22f0ccc61b86b",
"shasum": ""
},
"require": {
"php": "~8.2.0 || ~8.3.0 || ~8.4.0",
"psr/clock": "^1.0"
},
"provide": {
"psr/clock-implementation": "1.0"
},
"require-dev": {
"infection/infection": "^0.29",
"lcobucci/coding-standard": "^11.1.0",
"phpstan/extension-installer": "^1.3.1",
"phpstan/phpstan": "^1.10.25",
"phpstan/phpstan-deprecation-rules": "^1.1.3",
"phpstan/phpstan-phpunit": "^1.3.13",
"phpstan/phpstan-strict-rules": "^1.5.1",
"phpunit/phpunit": "^11.3.6"
},
"type": "library",
"autoload": {
"psr-4": {
"Lcobucci\\Clock\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Luís Cobucci",
"email": "lcobucci@gmail.com"
}
],
"description": "Yet another clock abstraction",
"support": {
"issues": "https://github.com/lcobucci/clock/issues",
"source": "https://github.com/lcobucci/clock/tree/3.3.1"
},
"funding": [
{
"url": "https://github.com/lcobucci",
"type": "github"
},
{
"url": "https://www.patreon.com/lcobucci",
"type": "patreon"
}
],
"time": "2024-09-24T20:45:14+00:00"
},
{ {
"name": "lcobucci/jwt", "name": "lcobucci/jwt",
"version": "4.3.0", "version": "5.5.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/lcobucci/jwt.git", "url": "https://github.com/lcobucci/jwt.git",
"reference": "4d7de2fe0d51a96418c0d04004986e410e87f6b4" "reference": "a835af59b030d3f2967725697cf88300f579088e"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/lcobucci/jwt/zipball/4d7de2fe0d51a96418c0d04004986e410e87f6b4", "url": "https://api.github.com/repos/lcobucci/jwt/zipball/a835af59b030d3f2967725697cf88300f579088e",
"reference": "4d7de2fe0d51a96418c0d04004986e410e87f6b4", "reference": "a835af59b030d3f2967725697cf88300f579088e",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-hash": "*",
"ext-json": "*",
"ext-mbstring": "*",
"ext-openssl": "*", "ext-openssl": "*",
"ext-sodium": "*", "ext-sodium": "*",
"lcobucci/clock": "^2.0 || ^3.0", "php": "~8.2.0 || ~8.3.0 || ~8.4.0",
"php": "^7.4 || ^8.0" "psr/clock": "^1.0"
}, },
"require-dev": { "require-dev": {
"infection/infection": "^0.21", "infection/infection": "^0.29",
"lcobucci/coding-standard": "^6.0", "lcobucci/clock": "^3.2",
"mikey179/vfsstream": "^1.6.7", "lcobucci/coding-standard": "^11.0",
"phpbench/phpbench": "^1.2", "phpbench/phpbench": "^1.2",
"phpstan/extension-installer": "^1.0", "phpstan/extension-installer": "^1.2",
"phpstan/phpstan": "^1.4", "phpstan/phpstan": "^1.10.7",
"phpstan/phpstan-deprecation-rules": "^1.0", "phpstan/phpstan-deprecation-rules": "^1.1.3",
"phpstan/phpstan-phpunit": "^1.0", "phpstan/phpstan-phpunit": "^1.3.10",
"phpstan/phpstan-strict-rules": "^1.0", "phpstan/phpstan-strict-rules": "^1.5.0",
"phpunit/php-invoker": "^3.1", "phpunit/phpunit": "^11.1"
"phpunit/phpunit": "^9.5" },
"suggest": {
"lcobucci/clock": ">= 3.2"
}, },
"type": "library", "type": "library",
"autoload": { "autoload": {
@ -4497,7 +4431,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/lcobucci/jwt/issues", "issues": "https://github.com/lcobucci/jwt/issues",
"source": "https://github.com/lcobucci/jwt/tree/4.3.0" "source": "https://github.com/lcobucci/jwt/tree/5.5.0"
}, },
"funding": [ "funding": [
{ {
@ -4509,7 +4443,7 @@
"type": "patreon" "type": "patreon"
} }
], ],
"time": "2023-01-02T13:28:00+00:00" "time": "2025-01-26T21:29:45+00:00"
}, },
{ {
"name": "league/commonmark", "name": "league/commonmark",
@ -14666,16 +14600,16 @@
}, },
{ {
"name": "sebastian/comparator", "name": "sebastian/comparator",
"version": "6.3.1", "version": "6.3.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git", "url": "https://github.com/sebastianbergmann/comparator.git",
"reference": "24b8fbc2c8e201bb1308e7b05148d6ab393b6959" "reference": "85c77556683e6eee4323e4c5468641ca0237e2e8"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/24b8fbc2c8e201bb1308e7b05148d6ab393b6959", "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/85c77556683e6eee4323e4c5468641ca0237e2e8",
"reference": "24b8fbc2c8e201bb1308e7b05148d6ab393b6959", "reference": "85c77556683e6eee4323e4c5468641ca0237e2e8",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -14734,15 +14668,27 @@
"support": { "support": {
"issues": "https://github.com/sebastianbergmann/comparator/issues", "issues": "https://github.com/sebastianbergmann/comparator/issues",
"security": "https://github.com/sebastianbergmann/comparator/security/policy", "security": "https://github.com/sebastianbergmann/comparator/security/policy",
"source": "https://github.com/sebastianbergmann/comparator/tree/6.3.1" "source": "https://github.com/sebastianbergmann/comparator/tree/6.3.2"
}, },
"funding": [ "funding": [
{ {
"url": "https://github.com/sebastianbergmann", "url": "https://github.com/sebastianbergmann",
"type": "github" "type": "github"
},
{
"url": "https://liberapay.com/sebastianbergmann",
"type": "liberapay"
},
{
"url": "https://thanks.dev/u/gh/sebastianbergmann",
"type": "thanks_dev"
},
{
"url": "https://tidelift.com/funding/github/packagist/sebastian/comparator",
"type": "tidelift"
} }
], ],
"time": "2025-03-07T06:57:01+00:00" "time": "2025-08-10T08:07:46+00:00"
}, },
{ {
"name": "sebastian/complexity", "name": "sebastian/complexity",
@ -15323,16 +15269,16 @@
}, },
{ {
"name": "sebastian/type", "name": "sebastian/type",
"version": "5.1.2", "version": "5.1.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/type.git", "url": "https://github.com/sebastianbergmann/type.git",
"reference": "a8a7e30534b0eb0c77cd9d07e82de1a114389f5e" "reference": "f77d2d4e78738c98d9a68d2596fe5e8fa380f449"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/type/zipball/a8a7e30534b0eb0c77cd9d07e82de1a114389f5e", "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/f77d2d4e78738c98d9a68d2596fe5e8fa380f449",
"reference": "a8a7e30534b0eb0c77cd9d07e82de1a114389f5e", "reference": "f77d2d4e78738c98d9a68d2596fe5e8fa380f449",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -15368,15 +15314,27 @@
"support": { "support": {
"issues": "https://github.com/sebastianbergmann/type/issues", "issues": "https://github.com/sebastianbergmann/type/issues",
"security": "https://github.com/sebastianbergmann/type/security/policy", "security": "https://github.com/sebastianbergmann/type/security/policy",
"source": "https://github.com/sebastianbergmann/type/tree/5.1.2" "source": "https://github.com/sebastianbergmann/type/tree/5.1.3"
}, },
"funding": [ "funding": [
{ {
"url": "https://github.com/sebastianbergmann", "url": "https://github.com/sebastianbergmann",
"type": "github" "type": "github"
},
{
"url": "https://liberapay.com/sebastianbergmann",
"type": "liberapay"
},
{
"url": "https://thanks.dev/u/gh/sebastianbergmann",
"type": "thanks_dev"
},
{
"url": "https://tidelift.com/funding/github/packagist/sebastian/type",
"type": "tidelift"
} }
], ],
"time": "2025-03-18T13:35:50+00:00" "time": "2025-08-09T06:55:48+00:00"
}, },
{ {
"name": "sebastian/version", "name": "sebastian/version",

View File

@ -8,15 +8,12 @@ use Lcobucci\JWT\Configuration;
use App\Models\Permission; use App\Models\Permission;
use Lcobucci\JWT\Signer\Hmac\Sha256; use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Signer\Key\InMemory; use Lcobucci\JWT\Signer\Key\InMemory;
use Lcobucci\JWT\UnencryptedToken;
use Lcobucci\JWT\Validation\Constraint\SignedWith; use Lcobucci\JWT\Validation\Constraint\SignedWith;
use App\Tests\Integration\Api\Client\ClientApiIntegrationTestCase; use App\Tests\Integration\Api\Client\ClientApiIntegrationTestCase;
class WebsocketControllerTest extends ClientApiIntegrationTestCase class WebsocketControllerTest extends ClientApiIntegrationTestCase
{ {
/**
* Test that a subuser attempting to connect to the websocket receives an error if they
* do not explicitly have the permission.
*/
public function test_subuser_without_websocket_permission_receives_error(): void public function test_subuser_without_websocket_permission_receives_error(): void
{ {
[$user, $server] = $this->generateTestAccount([Permission::ACTION_CONTROL_RESTART]); [$user, $server] = $this->generateTestAccount([Permission::ACTION_CONTROL_RESTART]);
@ -59,41 +56,34 @@ class WebsocketControllerTest extends ClientApiIntegrationTestCase
$response->assertJsonStructure(['data' => ['token', 'socket']]); $response->assertJsonStructure(['data' => ['token', 'socket']]);
$connection = $response->json('data.socket'); $connection = $response->json('data.socket');
$this->assertStringStartsWith('wss://', $connection, 'Failed asserting that websocket connection address has expected "wss://" prefix.'); $this->assertStringStartsWith('wss://', $connection);
$this->assertStringEndsWith("/api/servers/$server->uuid/ws", $connection, 'Failed asserting that websocket connection address uses expected Daemon endpoint.'); $this->assertStringEndsWith("/api/servers/$server->uuid/ws", $connection);
$key = InMemory::plainText($server->node->daemon_token);
$config = Configuration::forSymmetricSigner(new Sha256(), $key);
$config = Configuration::forSymmetricSigner(new Sha256(), $key = InMemory::plainText($server->node->daemon_token));
$config->setValidationConstraints(new SignedWith(new Sha256(), $key));
/** @var \Lcobucci\JWT\Token\Plain $token */
$token = $config->parser()->parse($response->json('data.token')); $token = $config->parser()->parse($response->json('data.token'));
$this->assertInstanceOf(UnencryptedToken::class, $token);
$constraints = [new SignedWith(new Sha256(), $key)];
$this->assertTrue( $this->assertTrue(
$config->validator()->validate($token, ...$config->validationConstraints()), $config->validator()->validate($token, ...$constraints),
'Failed to validate that the JWT data returned was signed using the Node\'s secret key.' 'Failed to validate that the JWT data returned was signed using the Node\'s secret key.'
); );
// The way we generate times for the JWT will truncate the microseconds from the $expect = CarbonImmutable::createFromTimestamp(CarbonImmutable::now()->getTimestamp())->timezone('UTC')->setMicroseconds(0);
// time, but CarbonImmutable::now() will include them, thus causing test failures.
//
// This little chunk of logic just strips those out by generating a new CarbonImmutable
// instance from the current timestamp, which is how the JWT works. We also need to
// switch to UTC here for consistency.
$expect = CarbonImmutable::createFromTimestamp(CarbonImmutable::now()->getTimestamp())->timezone('UTC');
// Check that the claims are generated correctly. $claims = $token->claims();
$this->assertTrue($token->hasBeenIssuedBy(config('app.url'))); $this->assertSame(config('app.url'), $claims->get('iss'));
$this->assertTrue($token->isPermittedFor($server->node->getConnectionAddress())); $this->assertSame($server->node->getConnectionAddress(), $claims->get('aud')[0] ?? null);
$this->assertEquals($expect, $token->claims()->get('iat')); $this->assertEquals($expect, CarbonImmutable::instance($claims->get('iat'))->setMicroseconds(0));
$this->assertEquals($expect->subMinutes(5), $token->claims()->get('nbf')); $this->assertEquals($expect->subMinutes(5), CarbonImmutable::instance($claims->get('nbf'))->setMicroseconds(0));
$this->assertEquals($expect->addMinutes(10), $token->claims()->get('exp')); $this->assertEquals($expect->addMinutes(10), CarbonImmutable::instance($claims->get('exp'))->setMicroseconds(0));
$this->assertSame($user->id, $token->claims()->get('user_id')); $this->assertSame($user->uuid, $claims->get('user_uuid'));
$this->assertSame($server->uuid, $token->claims()->get('server_uuid')); $this->assertSame($server->uuid, $claims->get('server_uuid'));
$this->assertSame(['*'], $token->claims()->get('permissions')); $this->assertSame(['*'], $claims->get('permissions'));
} }
/**
* Test that the subuser's permissions are passed along correctly in the generated JWT.
*/
public function test_jwt_is_configured_correctly_for_server_subuser(): void public function test_jwt_is_configured_correctly_for_server_subuser(): void
{ {
$permissions = [Permission::ACTION_WEBSOCKET_CONNECT, Permission::ACTION_CONTROL_CONSOLE]; $permissions = [Permission::ACTION_WEBSOCKET_CONNECT, Permission::ACTION_CONTROL_CONSOLE];
@ -107,17 +97,18 @@ class WebsocketControllerTest extends ClientApiIntegrationTestCase
$response->assertOk(); $response->assertOk();
$response->assertJsonStructure(['data' => ['token', 'socket']]); $response->assertJsonStructure(['data' => ['token', 'socket']]);
$config = Configuration::forSymmetricSigner(new Sha256(), $key = InMemory::plainText($server->node->daemon_token)); $key = InMemory::plainText($server->node->daemon_token);
$config->setValidationConstraints(new SignedWith(new Sha256(), $key)); $config = Configuration::forSymmetricSigner(new Sha256(), $key);
/** @var \Lcobucci\JWT\Token\Plain $token */
$token = $config->parser()->parse($response->json('data.token'));
$token = $config->parser()->parse($response->json('data.token'));
$this->assertInstanceOf(UnencryptedToken::class, $token);
$constraints = [new SignedWith(new Sha256(), $key)];
$this->assertTrue( $this->assertTrue(
$config->validator()->validate($token, ...$config->validationConstraints()), $config->validator()->validate($token, ...$constraints),
'Failed to validate that the JWT data returned was signed using the Node\'s secret key.' '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->claims()->get('permissions')); $this->assertSame($permissions, $token->claims()->get('permissions'));
} }
} }