Skip to content

Commit 73b74b7

Browse files
committed
[Server] Stop a claim that is not UTF-8 from failing the session principal
1 parent 05be8cf commit 73b74b7

3 files changed

Lines changed: 19 additions & 14 deletions

File tree

‎src/Server/Authorization/AccessToken.php‎

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111

1212
namespace Mcp\Server\Authorization;
1313

14-
use Mcp\Exception\RuntimeException;
15-
1614
/**
1715
* The validated access token a request was authorized with.
1816
*
@@ -85,18 +83,12 @@ public function getClientId(): ?string
8583

8684
/**
8785
* Who the token identifies: its issuer, client and subject, which outlive a token refresh.
88-
*
89-
* @throws RuntimeException when a claim cannot be encoded
9086
*/
9187
public function getPrincipal(): string
9288
{
9389
$issuer = $this->getClaim('iss');
9490

95-
try {
96-
return json_encode([\is_string($issuer) ? $issuer : null, $this->getClientId(), $this->getSubject()], \JSON_THROW_ON_ERROR);
97-
} catch (\JsonException $e) {
98-
throw new RuntimeException(\sprintf('Failed to encode the principal of an access token as JSON: %s', $e->getMessage()), previous: $e);
99-
}
91+
return serialize([\is_string($issuer) ? $issuer : null, $this->getClientId(), $this->getSubject()]);
10092
}
10193

10294
/**

‎tests/Unit/Server/Authorization/AccessTokenTest.php‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
namespace Mcp\Tests\Unit\Server\Authorization;
1313

14-
use Mcp\Exception\RuntimeException;
1514
use Mcp\Server\Authorization\AccessToken;
1615
use PHPUnit\Framework\TestCase;
1716

@@ -60,11 +59,12 @@ public function testPrincipalKeepsClaimsApart(): void
6059
);
6160
}
6261

63-
public function testPrincipalOfAClaimThatCannotBeEncodedFails(): void
62+
public function testPrincipalKeepsClaimsThatAreNotUtf8Apart(): void
6463
{
65-
$this->expectException(RuntimeException::class);
66-
67-
(new AccessToken([], ['sub' => "\xB1"]))->getPrincipal();
64+
$this->assertNotSame(
65+
(new AccessToken([], ['sub' => "\xB1"]))->getPrincipal(),
66+
(new AccessToken([], ['sub' => "\xB2"]))->getPrincipal(),
67+
);
6868
}
6969

7070
public function testIsNeverSerialized(): void

‎tests/Unit/Server/Transport/SessionBindingTest.php‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,19 @@ public function testTokensWithoutSubjectOfAnotherClientAreRefused(): void
198198
$this->assertSame(404, $this->callWith($session, [AccessToken::class => new AccessToken([], ['client_id' => 'b'])])->getStatusCode());
199199
}
200200

201+
public function testTokenWithAClaimThatIsNotUtf8BindsTheSession(): void
202+
{
203+
$owner = [AccessToken::class => new AccessToken([], ['sub' => "\xB1"])];
204+
$other = [AccessToken::class => new AccessToken([], ['sub' => "\xB2"])];
205+
$ping = '{"jsonrpc":"2.0","id":2,"method":"ping"}';
206+
$session = $this->openWith($owner);
207+
208+
$this->assertSame(200, $this->serveWith($this->request('POST', $ping, null, $session), $owner)->getStatusCode());
209+
$this->assertSame(404, $this->serveWith($this->request('POST', $ping, null, $session), $other)->getStatusCode());
210+
$this->assertSame(404, $this->serveWith($this->request('DELETE', '', null, $session), $other)->getStatusCode());
211+
$this->assertSame(200, $this->serveWith($this->request('DELETE', '', null, $session), $owner)->getStatusCode());
212+
}
213+
201214
public function testTokenWithoutClaimsDoesNotShareSessionsWithRequestsWithoutToken(): void
202215
{
203216
$session = $this->openWith([AccessToken::class => new AccessToken()]);

0 commit comments

Comments
 (0)