fix(security): refuse OAuth authorize/consent for users without access (audit L1)
mcp-oauth has no filter for this, so AuthorizeGate runs on template_redirect before its router and stops the browser endpoints (authorize, authorize-callback, consent) for logged-in users without lit_mcp_use with "Dein Benutzer hat keinen Zugriff auf LIT MCP." (403). Login redirect, token and revoke stay mcp-oauth's. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
This commit is contained in:
@@ -30,6 +30,7 @@ use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
|
||||
use LIT\MCP\Integrations\WordPress\Schema\RegisteredMetaSource;
|
||||
use LIT\MCP\Integrations\WordPress\Schema\SampledMetaSource;
|
||||
use LIT\MCP\Integrations\WordPress\WordPressIntegration;
|
||||
use LIT\MCP\Server\AuthorizeGate;
|
||||
use LIT\MCP\Server\DiscoveryCanonical;
|
||||
use LIT\MCP\Server\RequestContext;
|
||||
use LIT\MCP\Server\ServerRegistrar;
|
||||
@@ -60,6 +61,7 @@ final class Plugin
|
||||
(new RequestContext())->register();
|
||||
(new VisibilityFilter())->register();
|
||||
(new DiscoveryCanonical())->register();
|
||||
(new AuthorizeGate())->register();
|
||||
|
||||
$limits = new Limits();
|
||||
$changeLog = new ChangeLog();
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Server;
|
||||
|
||||
use LIT\MCP\Access;
|
||||
|
||||
/**
|
||||
* Stops mcp-oauth's browser flow for logged-in users without lit_mcp_use (security audit L1).
|
||||
* mcp-oauth only checks is_user_logged_in() and offers no filter, so this runs on
|
||||
* template_redirect before its router (priority 10): without it any customer or subscriber
|
||||
* could complete the consent and get an application password, tokens and sessions, even
|
||||
* though the tools would refuse them. Not logged in, the login redirect stays mcp-oauth's;
|
||||
* token and revoke have no browser session and are left alone.
|
||||
*/
|
||||
final class AuthorizeGate
|
||||
{
|
||||
/** mcp-oauth's query var (WPMedia\MCP\OAuth\Auth\Rewrite::OAUTH_QUERY_VAR). */
|
||||
private const QUERY_VAR = 'mcp_oauth_endpoint';
|
||||
|
||||
/** Endpoints a user reaches in the browser before a connection exists. */
|
||||
private const USER_FACING = ['authorize', 'authorize-callback', 'consent'];
|
||||
|
||||
public function register(): void
|
||||
{
|
||||
add_action('template_redirect', [$this, 'check'], 1);
|
||||
}
|
||||
|
||||
public function check(): void
|
||||
{
|
||||
$endpoint = (string) get_query_var(self::QUERY_VAR, '');
|
||||
if (! in_array($endpoint, self::USER_FACING, true) || ! is_user_logged_in() || Access::currentUserMayUse()) {
|
||||
return;
|
||||
}
|
||||
|
||||
wp_die(
|
||||
esc_html(__('Dein Benutzer hat keinen Zugriff auf LIT MCP.', 'wp-lit-mcp')),
|
||||
esc_html(__('Kein Zugriff', 'wp-lit-mcp')),
|
||||
['response' => 403]
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user