Files
myep/tests/Security/McpAccessTokenHandlerTest.php
T

71 lines
2.2 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Tests\Security;
use App\Security\McpAccessTokenHandler;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
class McpAccessTokenHandlerTest extends TestCase
{
public function testEachTokenAuthenticatesItsOwnClient(): void
{
$handler = new McpAccessTokenHandler('n8n:token-a, claude-desktop:token-b');
$badge = $handler->getUserBadgeFrom('token-b');
self::assertSame('claude-desktop', $badge->getUserIdentifier());
self::assertSame(['ROLE_CHATBOT_MCP'], $badge->getUser()->getRoles());
self::assertSame('n8n', $handler->getUserBadgeFrom('token-a')->getUserIdentifier());
}
public function testATokenMayContainColons(): void
{
self::assertSame('n8n', (new McpAccessTokenHandler('n8n:a:b:c'))->getUserBadgeFrom('a:b:c')->getUserIdentifier());
}
public function testAnUnknownTokenIsRejected(): void
{
$this->expectException(BadCredentialsException::class);
(new McpAccessTokenHandler('n8n:token-a'))->getUserBadgeFrom('token-b');
}
public function testAClientNameIsNotAToken(): void
{
$this->expectException(BadCredentialsException::class);
(new McpAccessTokenHandler('n8n:token-a'))->getUserBadgeFrom('n8n');
}
public function testAnEmptyListRejectsEverything(): void
{
$this->expectException(BadCredentialsException::class);
(new McpAccessTokenHandler(' '))->getUserBadgeFrom('');
}
/**
* @return iterable<string, array{string}>
*/
public static function malformedLists(): iterable
{
yield 'token without name' => ['token-a'];
yield 'empty token' => ['n8n:'];
yield 'invalid name' => ['n 8 n:token-a'];
yield 'duplicate name' => ['n8n:token-a,n8n:token-b'];
yield 'shared token' => ['n8n:token-a,claude-desktop:token-a'];
}
#[DataProvider('malformedLists')]
public function testAMalformedListFailsLoudly(string $tokens): void
{
$this->expectException(\InvalidArgumentException::class);
new McpAccessTokenHandler($tokens);
}
}