getAttribute('oauth.claims'); $scopes = $request->getAttribute('oauth.scopes') ?? []; if (!is_array($claims)) { // Only reachable if the stack is misordered; never serve anonymously. return $this->deny(500, 'Identity unavailable'); } $username = is_string($claims['preferred_username'] ?? null) ? trim($claims['preferred_username']) : ''; if ($username === '') { return $this->deny(403, 'Access token has no preferred_username claim'); } $groupsClaim = $claims['groups'] ?? []; $groups = implode(',', array_filter( is_array($groupsClaim) ? $groupsClaim : [$groupsClaim], 'is_string' )); if (!\AccessPolicy::hasAppAccess($groups)) { return $this->deny(403, 'Your account is not permitted to use Tinker Tickets'); } $user = (new \UserModel($this->conn))->syncUserFromAuthelia( $username, is_string($claims['name'] ?? null) ? $claims['name'] : '', is_string($claims['email'] ?? null) ? $claims['email'] : '', $groups ); McpIdentity::set($user, array_values(array_filter($scopes, 'is_string'))); return $handler->handle($request); } private function deny(int $status, string $message): ResponseInterface { return $this->responseFactory->createResponse($status) ->withHeader('Content-Type', 'application/json') ->withBody($this->streamFactory->createStream(json_encode([ 'jsonrpc' => '2.0', 'id' => null, 'error' => ['code' => -32001, 'message' => $message], ]))); } }