MCP-Authentifizierungsmuster: OAuth, Tokens und wann was
MCP definiert ein OAuth-Autorisierungsprofil für HTTP-Transporte. Öffentliche Server mit reinem Lesezugriff können anonym bleiben. Geschützte Tools brauchen Authentifizierung, Autorisierung und einen verifizierten Principal. Eigene Partnertokens benötigen einen ausdrücklich vereinbarten Kompatibilitätsvertrag mit dem MCP-Client.
Dieser Artikel verankert sich am Pillar MCP-Server-Entwicklungsservice.
TL;DR
- Read-only auf öffentlichen Daten mit Rate-Limit ist der einzige legitime Anonym-Fall.
- Scoped API-Tokens mit gehashter Speicherung und kurzer TTL decken B2B und Headless-Flows ab.
- OAuth 2.1 mit PKCE deckt Konsumenten-Assistenten ab, die für eingeloggte Nutzer handeln.
- Rate-Limiting hängt am Principal; mutierende Tools bekommen ein engeres Bucket.
- Jedes Auth-Ereignis wird geloggt: ausgegeben, verwendet, widerrufen, gescheitert.
Welche MCP-Authentifizierung passt zu welchem Fall
Ich gehe vor jeder Auth-Wahl dieselben fünf Fragen durch:
- Verändert irgendein Tool Zustand? Wenn ja, anonym ist vom Tisch.
- Handelt der Agent im Namen eines konkreten menschlichen Endnutzers? Wenn ja, OAuth.
- Handelt der Agent als B2B-Integration ohne menschlichen Endnutzer? Wenn ja, scoped API-Token.
- Ist die Datenoberfläche im öffentlichen Internet erreichbar? Wenn ja, Rate-Limiting ist Pflicht.
- Mischen sich mutierende und Read-only-Tools im selben Server? Wenn ja, Auth pro Tool, nicht pro Server.
Der Entscheidungsbaum mappt auf drei Muster:
| Muster | Wann nutzen | Umsetzung |
|---|---|---|
| Anonym + IP-Rate-Limit | Öffentlicher Katalog, Read-only, begrenzte Last | Worker prüft nur das IP-Bucket |
| Scoped API-Token | B2B-Integration, Headless-Agenten-Runtime, kein menschlicher Endnutzer | Zufälliges opaque Token, gehashte Speicherung, Ablauf und Rotation |
| OAuth 2.1 + PKCE | Konsumenten-Agent für eingeloggten Nutzer | Standard-Authorization-Code-Flow |
Die Muster schließen sich nicht aus. Ein realer Produktionsserver fährt oft alle drei, mit jedem Tool getaggt mit dem nötigen Umfang.
Anonymer Read-only-Zugriff auf MCP mit Rate-Limit
Geben Sie nur ausdrücklich freigegebene öffentliche Katalogfelder aus. Die WooCommerce-Verwaltungs-API wc/v3 benötigt serverseitige Zugangsdaten und ist kein anonymer öffentlicher Ursprung. Nutzen Sie einen geprüften öffentlichen Endpunkt oder einen Adapter, der private Felder ausschließt.
Die Umsetzung:
async function checkAnonymousRateLimit(request: Request, env: Env): Promise<boolean> {
const ip = request.headers.get("CF-Connecting-IP") ?? "unknown";
const { success } = await env.AUTH_RATE_LIMIT.limit({ key: `anonymous:${ip}` });
return success;
}60 Requests pro Minute pro IP ist mein Default. Der KV-basierte Zähler ist approximativ (eventually consistent bei KV-Writes); für engere Limits sind Durable Objects oder Cloudflares natives Rate-Limiting-Binding das richtige Werkzeug.
Was dieses Muster nicht abdeckt: jedes Tool, das nutzerspezifische Daten zurückgibt, jedes Tool, das Zustand verändert, jedes Tool, das Bestand für nicht öffentliche Produkte preisgibt. Diese brauchen einen echten Principal.
Scoped API-Tokens für B2B-Integrationen per MCP
Der B2B-Fall: eine Partner-Integration liefert einen Agenten aus, der Ihren MCP-Server im Namen der Partner-Organisation aufruft, nicht im Namen eines konkreten menschlichen Endnutzers. Beispiele sind ein Inventar-Sync-Agent bei einem Großhändler, eine Marktplatz-Integration bei einem Aggregator, ein Analytik-Agent, der Bestelltrends an ein BI-Tool meldet.
Der Ablauf:
- Eine Admin-Person im WordPress-Backend legt ein Token an, mit Name, Umfang-Set (
catalogue:read,inventory:read,orders:write) und Ablauf (Default 90 Tage). - Das Token wird der Admin-Person einmal angezeigt, dann als SHA-256-Hash plus Umfang-Set plus Ablauf gespeichert.
- Der Partner trägt das Token in seinem MCP-Client als
Authorization: Bearer <token>-Header ein. - Der Worker hasht das eingehende Token und schlägt den Hash in KV nach. Stimmt der Hash, liegt der Ablauf in der Zukunft und ist der für das Tool nötige Umfang im Umfang-Set, läuft der Aufruf weiter.
async function verifyApiToken(authHeader: string | null, env: Env): Promise<TokenContext | null> {
if (!authHeader?.startsWith("Bearer ")) return null;
const token = authHeader.slice(7);
const hash = await sha256(token);
const record = await env.TOKENS.get(`tok:${hash}`, "json") as TokenRecord | null;
if (!record) return null;
if (record.expiresAt < Date.now()) return null;
return { tokenId: record.id, scopes: record.scopes, principal: record.principal };
}
function requireScope(ctx: TokenContext, scope: string): void {
if (!ctx.scopes.includes(scope)) throw new Error("Insufficient scope");
}Zwei operative Gewohnheiten halten dieses Muster sauber:
Rotation, keine Ewigkeit. Ein Token, das nie abläuft, ist ein Token, das in sechs Monaten in einem öffentlichen GitHub-Repo landet. 90 Tage Default mit Renewal-Flow, der altes und neues Token sieben Tage überlappt, ist das Muster, das echte Partner überlebt.
Gehashte Speicherung, kein Klartext. Wird Ihr KV exfiltriert, sind die Hashes ohne Originaltoken nutzlos. Hatten Sie Klartext-Tokens, braucht jede Partner-Integration sofortige Rotation. Der Kostenunterschied bei der Ausgabe ist ein einziger sha256-Aufruf.
OAuth 2.1 mit PKCE in einem MCP-Server
Der Konsumentenfall: ein Nutzer öffnet Claude Desktop, verbindet sein Konto auf Ihrem Shop per OAuth und bittet den Agenten, “zeige meine letzte Bestellung”. Der Agent muss Ihren MCP-Server jetzt mit Credentials anrufen, die “ich handle für Nutzer 4231” sagen.
OAuth 2.1 (draft-ietf-oauth-v2-1) ist das konsolidierte Profil. PKCE (RFC 7636) ist Pflicht für öffentliche Clients (das schließt Desktop-Assistenten ohne vertraulichen serverseitigen Anteil ein).
Der Flow in fünf Etappen:
- Der MCP-Host öffnet einen Browser auf Ihren Authorization-Endpoint mit
response_type=code,code_challenge=<S256-Hash des Verifier>und den geforderten Scopes. - Der Nutzer loggt sich auf Ihrer WordPress-Site (oder bei Ihrem Auth-Provider) ein und genehmigt die Scopes.
- Ihr Authorization-Endpoint redirected zurück an den Host mit einem einmaligen Authorization-Code.
- Der Host tauscht den Code plus den ursprünglichen
code_verifieran Ihrem Token-Endpoint gegen ein Access-Token (kurze TTL, 1 Stunde) und ein Refresh-Token (längere TTL, 30 Tage). - Der Host ruft den MCP-Server mit
Authorization: Bearer <access_token>auf. Der Worker prüft Signatur, Ablauf und Umfang-Set des Tokens gegen das aufgerufene Tool.
Ein OAuth-Token kann opaque oder JWT sein. Dieses Beispiel verwendet einen konfigurierten Aussteller und den gepflegten jose-Verifier für Signatur und Claims:
import { createRemoteJWKSet, jwtVerify } from "jose";
const issuer = "https://identity.example.org";
const audience = "https://mcp.example.org/mcp";
const jwks = createRemoteJWKSet(new URL(issuer + "/.well-known/jwks.json"));
async function verifyJwt(token: string) {
const { payload } = await jwtVerify(token, jwks, {
issuer,
audience,
algorithms: ["RS256"],
requiredClaims: ["sub", "exp"],
});
if (typeof payload.sub !== "string" || typeof payload.scope !== "string") {
throw new Error("Invalid identity or scope claims");
}
return { subject: payload.sub, scopes: payload.scope.split(" ").filter(Boolean) };
}Die Scopes im JWT spiegeln die Scopes aus dem Scoped-Token-Muster: catalogue:read, orders:read, orders:write. Die WordPress-Nutzer-ID reitet im sub-Claim, sodass ein orders:read-Aufruf nur die Bestellungen dieses Nutzers liefert.
Wie man OAuth, Tokens und anonymen Zugriff in einem MCP-Server kombiniert
Ein realer WooCommerce-MCP-Server exponiert in der Regel:
catalogue.listundproduct.detail: anonym + IP-Rate-Limit.inventory.check(für Partner): scoped Token mitinventory:read.order.status(für eingeloggten Nutzer): OAuth mitorders:read.order.intent(für eingeloggten Nutzer): OAuth mitorders:write, plus engerem Rate-Limit.
Die Pre-Dispatch-Logik im Worker geht die Muster durch:
Authentifizieren Sie HTTP vor dem MCP-Dispatch. Prüfen Sie anschließend Tool-Scopes und Eigentum an der Ressource. Lehnen Sie unbekannte Tools oder fehlende Richtlinien ab. Authentifizierungsfehler benötigen HTTP-Bearer-Challenges statt erfundener JSON-RPC-Fehlercodes als Strings.
Die TOOL_AUTH_REQUIREMENTS-Map ist die einzige Wahrheit darüber, welches Tool welchen Auth-Modus braucht. Kein Tool wird ohne expliziten Eintrag hinzugefügt.
MCP-Rate-Limits pro IP, Token und Nutzer
Anonymer Verkehr bekommt ein Bucket pro IP. Token-authentifizierter Verkehr bekommt ein Bucket pro Token. OAuth-Verkehr bekommt ein Bucket pro Nutzer. Mutierende Tools bekommen unabhängig vom Principal eine engere Decke als Lese-Tools.
Die folgenden Werte sind Konfigurationsbeispiele, keine Messungen oder produktiven Standardwerte. Bestimmen Sie tatsächliche Grenzen aus Ursprungskapazität und beobachtetem Verkehr.
| Tool-Kategorie | Anonym | Token | OAuth |
|---|---|---|---|
catalogue.* (Lesen) | 60 / Minute / IP | 600 / Minute / Token | 120 / Minute / Nutzer |
inventory.* (Lesen) | nicht erlaubt | 300 / Minute / Token | nicht erlaubt |
order.status (Lesen) | nicht erlaubt | 60 / Minute / Token | 60 / Minute / Nutzer |
order.intent (Schreiben) | nicht erlaubt | 30 / Minute / Token | 10 / Minute / Nutzer |
Die Zahlen sind Startwerte; die richtigen Werte liefert Beobachtung von echtem Verkehr über zwei Wochen plus Tuning. Die Struktur zählt.
Welche MCP-Auth-Ereignisse man loggen sollte
Jedes auth-relevante Ereignis landet im Log:
- Token ausgegeben. Admin-Nutzer, Ziel-Principal, Scopes, Ablauf.
- Token verwendet. Token-ID, Tool-Name, Principal, Latenz, Erfolg/Fehler.
- Token widerrufen. Token-ID, wer hat widerrufen, warum.
- Token gescheitert. Grund (abgelaufen, Umfang fehlt, Hash-Mismatch), IP, User-Agent.
- OAuth-Code getauscht. Nutzer-ID, gewährte Scopes, ausgegebenes Refresh-Token.
- OAuth-Refresh. Nutzer-ID, neues Access-Token ausgegeben, altes Token verdrängt.
Die Logs gehen via Cloudflare Logpush in einen Langzeit-Store. Eine Dashboard-Abfrage, die “Tokens, die in den letzten 24 Stunden genutzt wurden, aber in den 90 Tagen davor nicht”, überwacht, fängt wahrscheinlichen Token-Diebstahl ab. Eine Abfrage auf “fehlgeschlagene Token-Verifikationen pro IP” fängt Credential-Stuffing-Versuche ab.
Discovery und Identität der geschützten Ressource
Die MCP-Autorisierungsspezifikation vom 2025-11-25 definiert einen OAuth-Ablauf für HTTP-Transporte. Autorisierung bleibt optional. Ein geschützter interoperabler HTTP-Server benötigt jedoch die Discovery- und Validierungsmechanismen dieses Profils. Stdio hat eine andere Bereitstellungsgrenze und bezieht Zugangsdaten aus der Umgebung. Eigene Partnertokens können eine kontrollierte Integration bedienen. Daraus folgt nicht, dass jeder MCP-Host diese Zugangsdaten selbst entdecken oder beschaffen kann. Prüfen Sie den eingesetzten Host und Transport.
Trennen Sie MCP-Ressourcenserver und Autorisierungsserver als Rollen, auch wenn beide in einer Anwendung laufen. Der Ressourcenserver führt Tools aus und kontrolliert Zugriff. Der Autorisierungsserver übernimmt Anmeldung, Zustimmung und Token-Ausgabe. Veröffentlichen Sie Metadaten der geschützten Ressource mit ihrer kanonischen Kennung und ihren Autorisierungsservern. Ein HTTP-401-Challenge kann über WWW-Authenticate auf diese Metadaten verweisen. Die Discovery-Adressen müssen hinter dem Reverse Proxy und mit einem Pfadpräfix korrekt bleiben. Eine sichtbare Login-Seite beweist keine korrekte Discovery durch den MCP-Host.
Der Client fordert ein Access-Token für die MCP-Ressource an. Der Server kontrolliert diese Bindung. Ein Token für eine andere API wird nicht akzeptabel, nur weil ein bekannter Aussteller es gültig signiert hat. Lehnen Sie unerwartete Audience- und Issuer-Werte vor der Tool-Ausführung ab. Verwenden Sie dieselbe kanonische Ressourcen-URI in Metadaten, Autorisierungsanfrage und Token-Prüfung. Leiten Sie die erwartete Audience nicht aus einem untrusted Host-Header oder einem frei gelieferten Query-Parameter ab.
Vollständige Token-Prüfung und nachgelagerte Systeme
OAuth-Access-Tokens können opaque oder JWT sein. Das Protokoll schreibt nicht jedem Aussteller JWT vor. Ein opaque Token benötigt das unterstützte Prüfverfahren seines Ausstellers. Ein JWT-Verifier prüft Signatur, erlaubten Algorithmus, Issuer, Audience und Zeitangaben. Anschließend validiert er die verwendeten Anwendungsclaims. Eine TypeScript-Typassertion führt keine Laufzeitprüfung aus. Ungültiges JSON, ein fehlendes Subject oder ein Scope mit falschem Datentyp muss eine kontrollierte Ablehnung ergeben. Nutzen Sie eine gepflegte Bibliothek und eine konfigurierte Vertrauensquelle statt eines unvollständigen Web-Crypto-Verifiers.
Laden Sie Signaturschlüssel von der konfigurierten JWKS-Adresse des Ausstellers. Eine beliebige URL im Token ist keine vertrauenswürdige Schlüsselquelle. Planen Sie Schlüsselrotation und einen nicht erreichbaren Aussteller. Ein fehlgeschlagener Schlüsselabruf darf keine ungeprüfte Anmeldung ermöglichen. Ein zwischengespeicherter vertrauenswürdiger Schlüssel kann innerhalb der festgelegten Richtlinie weiterarbeiten. Ein unbekannter Schlüssel verlangt trotzdem eine eindeutige Entscheidung. Testen Sie abgelaufene Tokens, zukünftige Gültigkeit, andere Algorithmen und Tokens für die falsche Umgebung. Staging-Zugangsdaten sollen nicht versehentlich auf Produktion funktionieren.
Die MCP-Sicherheitsregeln untersagen Token-Passthrough. Ein an den MCP-Server adressiertes Bearer-Token darf nicht als WooCommerce- oder ERP-Zugang weitergereicht werden. Halten Sie Zugangsdaten nachgelagerter Systeme serverseitig und autorisieren Sie die angeforderte Aktion vor ihrer Verwendung. Wenn das Zielsystem delegierte Identität benötigt, verwenden Sie dessen unterstützte Delegation oder Token-Exchange-Verfahren. Das Kopieren des eingehenden Authorization-Headers ist kein Delegationsmodell.
Tool-Rechte und Eigentum an Bestellungen
Authentifizieren Sie die HTTP-Anfrage und prüfen Sie danach die erforderlichen Scopes der Operation. Eine erfolgreiche Token-Prüfung darf die Tool-Rechte nicht überspringen. Die Tool-Registry enthält für jeden Eintrag die benötigten Berechtigungen. Ein unbekannter Eintrag wird abgewiesen. Änderungen brauchen Tests für erlaubte und verweigerte Aufrufe. Auch die Discovery-Liste benötigt eine Regel für sensible Beschreibungen und Parameter. Die Kenntnis eines Tool-Namens berechtigt nicht zu seiner Ausführung.
orders:read bezeichnet eine Aktionskategorie und keinen Bestellungsbesitzer. Verknüpfen Sie das verifizierte Subject über eine vertrauenswürdige Zuordnung mit einem internen Konto. Prüfen Sie beim Laden der Bestellung das Eigentum. Eine vom Agenten gelieferte Kundennummer beweist keine Berechtigung. Partnerzugriff auf eine gesamte Organisation benötigt eine eigene Freigabe und eine definierte Mandantengrenze. Ein deutscher Warenwirtschaftspartner und ein Kunde, der seinen Lieferstatus liest, haben unterschiedliche Principals, selbst wenn sie denselben MCP-Server verwenden.
Behandeln Sie Bearer-Authentifizierungsfehler auf der HTTP-Ebene. Ein fehlendes oder ungültiges Token führt zu einer Authentifizierungsablehnung. Fehlende Scopes verlangen den passenden Scope-Challenge. Ein abgelaufenes Token darf nicht wie ein Tool-Ergebnis für fehlenden Lagerbestand aussehen. Die Trennung erlaubt dem Host, Tokens zu erneuern oder Zustimmung einzuholen. Ein unveränderter Wiederholungsaufruf der Geschäftsfunktion löst das Authentifizierungsproblem nicht.
Widerruf, Quoten und Freigabetests
Erzeugen Sie opaque Partnertokens mit ausreichender kryptografischer Zufälligkeit. Gehashte Speicherung hilft nur bei schwer erratbaren Geheimnissen. Trennen Sie öffentliche Token-Kennung und Geheimnis und verwenden Sie eine geprüfte Verifikation. Definieren Sie die Widerrufsverzögerung. Workers KV ist eventually consistent. Das Löschen eines Eintrags garantiert keinen sofortigen weltweiten Widerruf. Sensible Operationen können eine Prüfung an der maßgeblichen Quelle oder eine andere Konsistenzgrenze benötigen. Kurze Laufzeiten begrenzen das Risiko, ersetzen den Widerruf aber nicht.
Auch ein Rate-Limiter hat ein Konsistenzmodell. Das Workers-Rate-Limiting-Binding begrenzt Anfragevolumen. Es ist kein globales transaktionales Budget für Bestellungen oder kostenpflichtige Aktionen. Dafür ist ein geeigneter verbindlicher Koordinator erforderlich. Ein KV-Lesezugriff mit anschließendem Schreiben ist kein atomarer Zähler. Parallele Anfragen können Aktualisierungen verlieren. Wiederholungen eines Agenten dürfen keine zusätzlichen Geschäftsoperationen erzeugen.
Prüfen Sie vor der Veröffentlichung Discovery über den produktiven Host, Zustimmung, Ablauf, Erneuerung, Widerruf und fehlende Scopes im vorgesehenen MCP-Host. Ergänzen Sie Zugriffe auf fremde Kundenkonten und Mandanten. Kontrollieren Sie, dass private Tool-Ergebnisse nicht im gemeinsamen Cache landen. Protokollieren Sie Token-Kennung, Principal, Tool und Ergebnis ohne Geheimnisse und Kundenpayloads. Trennen Sie Sicherheitsereignisse von detaillierten Debugging-Daten und legen Sie Aufbewahrungsfristen fest. Eine erfolgreiche Anmeldung ist erst der Anfang des Zugriffstests.
Weitere Artikel zu MCP-Servern
Dieser Artikel deckt die Auth-Oberfläche ab. Für den Implementierungs-Durchstich siehe MCP-Server für WooCommerce aufbauen. Für typisierte Tool-Definitionen siehe typisierte Katalog-Tools mit Zod für MCP. Für die Protokoll-Entscheidung siehe MCP vs REST. Für den Migrationspfad aus einer bestehenden API siehe bestehende WordPress-API auf MCP migrieren. Der Pillar ist MCP-Server-Entwicklung.
Preisgestaltung individuell, weil der Auth-Umfang davon abhängt, welche Muster Ihre Umgebung verlangt; ein Anonym-only-Read-Server ist ein anderer Auftrag als eine vollständige OAuth-Ausgabe-Oberfläche.







