60 lines
1.8 KiB
PHP
60 lines
1.8 KiB
PHP
<?php
|
|||
|
|
|
||
|
|
namespace TinkerTickets\Mcp\Auth;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* The Tinker Tickets user an MCP request runs as, plus the token's scopes.
|
||
|
|
*
|
||
|
|
* Set once per HTTP request by IdentityMiddleware from the *validated* access
|
||
|
|
* token, which is held as server-side PSR-7 request attributes. It is
|
||
|
|
* deliberately NOT read from the JSON-RPC `_meta` field: clients can write
|
||
|
|
* to `_meta`, and the SDK's OAuthRequestMetaMiddleware only overwrites the
|
||
|
|
* keys the validator happens to set.
|
||
|
|
*
|
||
|
|
* Static state is request-scoped here: PHP-FPM serves one HTTP request per
|
||
|
|
* process lifecycle, and the whole MCP call (including SDK fibers) runs
|
||
|
|
* inside it.
|
||
|
|
*/
|
||
|
|
final class McpIdentity
|
||
|
|
{
|
||
|
|
public const SCOPE_READ = 'tickets:read';
|
||
|
|
public const SCOPE_WRITE = 'tickets:write';
|
||
|
|
|
||
|
|
private static ?array $user = null;
|
||
|
|
/** @var list<string> */
|
||
|
|
private static array $scopes = [];
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @param array<string, mixed> $user
|
||
|
|
* @param list<string> $scopes
|
||
|
|
*/
|
||
|
|
public static function set(array $user, array $scopes): void
|
||
|
|
{
|
||
|
|
self::$user = $user;
|
||
|
|
self::$scopes = $scopes;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @return array<string, mixed>
|
||
|
|
*/
|
||
|
|
public static function user(): array
|
||
|
|
{
|
||
|
|
if (self::$user === null) {
|
||
|
|
// Unreachable if the middleware stack is intact; fail closed.
|
||
|
|
throw new \LogicException('MCP identity requested before IdentityMiddleware ran');
|
||
|
|
}
|
||
|
|
return self::$user;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** tickets:write implies tickets:read (scope hierarchy, MCP spec §Scope Challenge Handling). */
|
||
|
|
public static function canRead(array $scopes): bool
|
||
|
|
{
|
||
|
|
return in_array(self::SCOPE_READ, $scopes, true) || in_array(self::SCOPE_WRITE, $scopes, true);
|
||
|
|
}
|
||
|
|
|
||
|
|
public static function canWrite(array $scopes): bool
|
||
|
|
{
|
||
|
|
return in_array(self::SCOPE_WRITE, $scopes, true);
|
||
|
|
}
|
||
|
|
}
|