OAuth dla delegowanych agentów, scoped tokeny dla B2B, anonim dla tylko-do-odczytu. Rate limiting, logowanie i drzewo decyzyjne auth dla MCP.
PL

Wzorce uwierzytelniania MCP: OAuth, tokeny i kiedy co

4.60 /5 - (8 głosów )
Ostatnio zweryfikowano: 1 maja 2026
8min czytania
Przewodnik
500+ projektów WP
Integracja AI

#Wzorce uwierzytelniania MCP: OAuth, tokeny i kiedy co

Specyfikacja Model Context Protocol (modelcontextprotocol.io) definiuje transporty i prymitywy. Nie definiuje uwierzytelniania. Słusznie, bo uwierzytelnianie to sprawa transportu i wdrożenia, a nie protokołu. Jest też źródłem najczęstszego błędu produkcyjnego, jaki widuję: serwer MCP wystawiony w Internet bez auth, eksponujący narzędzia mutujące stan. W polskim kontekście dochodzi do tego art. 32 RODO, który nakłada obowiązek odpowiednich środków technicznych, gdy w grze są dane osobowe.

Artykuł osadzony jest w filarze budowa serwera MCP.

#TL;DR

  • Tylko-do-odczytu na publicznych danych z rate limitem to jedyny legalny przypadek anonim.
  • Scoped tokeny API z hashowaniem i krótkim TTL pokrywają B2B i headless.
  • OAuth 2.1 z PKCE pokrywa konsumenckie asystenty działające w imieniu zalogowanego użytkownika.
  • Rate limiting przykleja się do principala; narzędzia mutujące dostają węższy bucket.
  • Każde zdarzenie auth jest logowane: wydane, użyte, cofnięte, nieudane.

#Drzewo decyzyjne

Przed wyborem wzorca auth przepuszczam pięć tych samych pytań:

  1. Czy któreś narzędzie zmienia stan? Jeśli tak, anonim odpada.
  2. Czy agent działa w imieniu konkretnego ludzkiego użytkownika? Jeśli tak, OAuth.
  3. Czy agent działa jako integracja B2B bez ludzkiego użytkownika? Jeśli tak, scoped token API.
  4. Czy powierzchnia danych jest osiągalna w publicznym Internecie? Jeśli tak, rate limiting jest obowiązkowy.
  5. Czy w jednym serwerze mieszają się narzędzia mutujące i tylko-do-odczytu? Jeśli tak, scope auth per narzędzie, a nie per serwer.

Drzewo mapuje się na trzy wzorce:

WzorzecKiedy używaćImplementacja
Anonim + rate limit IPPubliczny katalog, tylko-do-odczytu, ograniczone obciążenieWorker sprawdza tylko bucket IP
Scoped token APIIntegracja B2B, headless’owy runtime agenta, brak ludzkiego użytkownikaJWT z claimami, hashowane przechowywanie, rotacja
OAuth 2.1 + PKCEKonsumencki agent dla zalogowanego użytkownikaStandardowy authorization code flow

Wzorce się nie wykluczają. Realny serwer produkcyjny zwykle uruchamia wszystkie trzy, a każde narzędzie jest otagowane wymaganym scope’em.

#Wzorzec pierwszy: anonimowo tylko-do-odczytu z rate limitem

Narzędzie do przeglądania katalogu opakowujące /wp-json/wc/v3/products?stock_status=instock eksponuje te same dane, które publiczna strona już serwuje. Postawienie auth przed nim nie poprawia postawy bezpieczeństwa; obniża tylko dostępność. Realnym zagrożeniem jest obciążenie: pętla agenta lub scrape konkurencji potrafi zatłuc origin WooCommerce.

Implementacja:

async function checkAnonymousRateLimit(request: Request, env: Env): Promise<boolean> {
  const ip = request.headers.get("CF-Connecting-IP") ?? "unknown";
  const key = `rl:anon:${ip}`;
  const count = Number((await env.RATE_LIMIT.get(key)) ?? "0");
  if (count >= 60) return false;
  await env.RATE_LIMIT.put(key, String(count + 1), { expirationTtl: 60 });
  return true;
}

60 żądań na minutę na IP to mój default. Licznik oparty o KV jest przybliżony (eventually consistent przy zapisach KV); dla ścisłych limitów Durable Objects lub natywne Rate Limiting binding Cloudflare są właściwym narzędziem.

Czego ten wzorzec nie pokrywa: żadnego narzędzia zwracającego dane specyficzne dla użytkownika, żadnego mutującego stan, żadnego ujawniającego stan magazynu produktów niepublicznych. Te wymagają realnego principala.

#Wzorzec drugi: scoped tokeny API dla B2B

Przypadek B2B: integracja partnera dostarcza agenta wołającego twój serwer MCP w imieniu organizacji partnera, nie konkretnego ludzkiego użytkownika. Przykłady to agent synchronizacji magazynu u hurtownika, integracja marketplace’u u agregatora, agent analityczny raportujący trendy zamówień do BI.

Przepływ:

  1. Administrator w backendzie WordPressa tworzy token z nazwą, zestawem scope’ów (catalogue:read, inventory:read, orders:write) i terminem ważności (default 90 dni).
  2. Token jest pokazywany administratorowi raz, potem trzymany jako hash SHA-256 plus zestaw scope’ów plus wygaśnięcie.
  3. Partner konfiguruje swojego klienta MCP z tokenem w nagłówku Authorization: Bearer <token>.
  4. Worker hashuje przychodzący token i sprawdza hash w KV. Jeśli hash się zgadza, wygaśnięcie jest w przyszłości, a wymagany scope narzędzia jest w zestawie tokena, wywołanie idzie dalej.
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 McpError("forbidden", `Tool requires scope ${scope}`);
  }
}

Dwa nawyki operacyjne trzymają wzorzec uczciwie:

Rotacja, nie wieczność. Token, który nigdy nie wygasa, to token, który za sześć miesięcy ląduje w publicznym repo na GitHubie. 90 dni domyślnie z flow odnawiania, który nakłada stary i nowy token na 7 dni, to wzorzec przetrwający realnych partnerów.

Hashowane przechowywanie, nie plaintext. Jeśli twoje KV wycieknie, hashe bez oryginalnego tokena są bezużyteczne. Jeśli trzymałeś tokeny w plaintext, każda integracja partnera potrzebuje natychmiastowej rotacji. Różnica kosztu w momencie wydania to jeden sha256.

#Wzorzec trzeci: OAuth 2.1 z PKCE dla delegowanych agentów

Przypadek konsumencki: użytkownik otwiera Claude Desktop, łączy konto w twoim sklepie po OAuth i prosi agenta “pokaż moje ostatnie zamówienie”. Agent musi teraz zawołać twój serwer MCP z poświadczeniami mówiącymi “działam dla użytkownika 4231”.

OAuth 2.1 (draft-ietf-oauth-v2-1) to skonsolidowany profil. PKCE (RFC 7636) jest obowiązkowy dla klientów publicznych (tu mieszczą się asystenty desktopowe bez poufnej części serwerowej).

Flow w pięciu krokach:

  1. Host MCP otwiera przeglądarkę na twoim endpoincie autoryzacji z response_type=code, code_challenge=<S256 hash verifiera> i żądanymi scope’ami.
  2. Użytkownik loguje się na twojej stronie WordPress (lub u twojego dostawcy auth) i akceptuje scope’y.
  3. Twój endpoint autoryzacji przekierowuje hosta z jednorazowym kodem autoryzacji.
  4. Host wymienia kod plus oryginalny code_verifier na twoim endpoincie tokenów na access token (krótki TTL, 1 godzina) i refresh token (dłuższy TTL, 30 dni).
  5. Host woła serwer MCP z Authorization: Bearer <access_token>. Worker weryfikuje podpis tokena, wygaśnięcie i scope wobec wołanego narzędzia.

Access token to podpisany JWT. Worker weryfikuje go Web Crypto API (dokumentacja Cloudflare Workers) bez biblioteki zewnętrznej:

async function verifyJwt(token: string, env: Env): Promise<JwtClaims | null> {
  const [headerB64, payloadB64, sigB64] = token.split(".");
  const data = new TextEncoder().encode(`${headerB64}.${payloadB64}`);
  const sig = base64UrlDecode(sigB64);
  const valid = await crypto.subtle.verify("RS256", env.PUBLIC_KEY, sig, data);
  if (!valid) return null;
  const payload = JSON.parse(new TextDecoder().decode(base64UrlDecode(payloadB64)));
  if (payload.exp * 1000 < Date.now()) return null;
  return payload as JwtClaims;
}

Scope’y w JWT odzwierciedlają scope’y ze wzorca scoped token: catalogue:read, orders:read, orders:write. ID użytkownika WordPressa siedzi w claimie sub, więc wywołanie orders:read zwraca tylko zamówienia tego użytkownika.

#Mieszanie wzorców w jednym serwerze

Realny serwer MCP dla WooCommerce zwykle wystawia:

  • catalogue.list i product.detail: anonim + rate limit IP.
  • inventory.check (dla partnerów): scoped token z inventory:read.
  • order.status (dla zalogowanego użytkownika): OAuth z orders:read.
  • order.intent (dla zalogowanego użytkownika): OAuth z orders:write, plus węższy rate limit.

Logika pre-dispatch w Workerze przechodzi przez wzorce:

async function authenticate(request: Request, toolName: string, env: Env): Promise<Principal> {
  const requirement = TOOL_AUTH_REQUIREMENTS[toolName];
  if (requirement === "anonymous") {
    if (!await checkAnonymousRateLimit(request, env)) throw new McpError("rate_limit");
    return { kind: "anonymous" };
  }
  const auth = request.headers.get("Authorization");
  if (requirement === "api_token") {
    const ctx = await verifyApiToken(auth, env);
    if (!ctx) throw new McpError("unauthorized");
    return { kind: "api_token", ctx };
  }
  if (requirement === "oauth") {
    const claims = auth?.startsWith("Bearer ") ? await verifyJwt(auth.slice(7), env) : null;
    if (!claims) throw new McpError("unauthorized");
    return { kind: "oauth", claims };
  }
  throw new Error(`Unknown auth requirement for ${toolName}`);
}

Mapa TOOL_AUTH_REQUIREMENTS to jedyne źródło prawdy o tym, które narzędzie potrzebuje którego trybu auth. Żadne narzędzie nie zostaje dodane bez jawnego wpisu.

#Rate limiting per principal

Ruch anonimowy dostaje bucket na IP. Ruch z tokenem dostaje bucket na token. Ruch OAuth dostaje bucket na użytkownika. Narzędzia mutujące dostają węższą półkę niezależnie od principala.

Dla kształtu WooCommerce moje domyślne buckety:

Kategoria narzędziaAnonimTokenOAuth
catalogue.* (odczyt)60 / minutę / IP600 / minutę / token120 / minutę / użytkownika
inventory.* (odczyt)nie wolno300 / minutę / tokennie wolno
order.status (odczyt)nie wolno60 / minutę / token60 / minutę / użytkownika
order.intent (zapis)nie wolno30 / minutę / token10 / minutę / użytkownika

Liczby są punktem startu; właściwe wartości wynikają z obserwacji realnego ruchu przez dwa tygodnie i tuningu. Liczy się struktura.

#Logowanie zdarzeń auth

Każde zdarzenie auth-relewantne ląduje w logu:

  • Token wydany. Administrator, principal docelowy, scope’y, wygaśnięcie.
  • Token użyty. ID tokena, nazwa narzędzia, principal, opóźnienie, sukces/porażka.
  • Token cofnięty. ID tokena, kto cofnął, dlaczego.
  • Token nieudany. Powód (wygasł, brak scope’a, niezgodność hash), IP, user agent.
  • Wymiana kodu OAuth. ID użytkownika, przyznane scope’y, wydany refresh token.
  • Refresh OAuth. ID użytkownika, nowy access token, stary token zastąpiony.

Logi idą przez Cloudflare Logpush do długoterminowego store’u. Zapytanie dashboardu śledzące “tokeny użyte w ostatnich 24 godzinach, których nie używano przez poprzednie 90 dni” łapie prawdopodobną kradzież tokena. Zapytanie o “nieudane weryfikacje tokena na IP” łapie próby credential stuffingu.

#Gdzie to siedzi w klastrze

Ten artykuł pokrywa powierzchnię auth. Po przebieg implementacji sięgnij do budowy serwera MCP dla WooCommerce. Po typowane definicje narzędzi do pisania typowanych narzędzi katalogu z Zod dla MCP. Po decyzję na poziomie protokołu do MCP vs REST. Po ścieżkę migracji z istniejącego API do migracji API WordPress do MCP. Filar to budowa serwera MCP.

Wycena indywidualna, bo zakres auth zależy od wzorców wymaganych w twoim środowisku; serwer tylko-do-odczytu w trybie anonim to inny projekt niż pełna powierzchnia wydająca OAuth.

Następny krok

Przekuj artykuł w realne wdrożenie

Pod tym wpisem dokładam linki, które domykają intencję użytkownika i prowadzą dalej w strukturze serwisu.

Powiązany klaster

Sprawdź inne usługi WordPress i bazę wiedzy

Wzmocnij swój biznes dzięki profesjonalnemu wsparciu technicznemu w kluczowych obszarach ekosystemu WordPress.

FAQ do artykułu

Często zadawane pytania

Najważniejsze odpowiedzi, które pomagają wdrożyć temat w praktyce.

SEO-ready GEO-ready AEO-ready 5 Q&A
Czy specyfikacja MCP wymaga uwierzytelnienia?
Nie. Specyfikacja Model Context Protocol pozostawia uwierzytelnianie warstwie transportu. Transporty stdio bywają zaufane przez sam fakt lokalnego uruchomienia. Transporty HTTP wystawione w Internet wymagają warstwy auth, której SDK nie dostarcza out of the box.
Kiedy anonimowy serwer MCP jest akceptowalny?
Gdy każde wystawione narzędzie jest tylko do odczytu na danych publicznych, a wpływ obciążenia jest ograniczony rate limitem na IP. Narzędzie do przeglądania katalogu opakowujące /wp-json/wc/v3/products?stock_status=instock jest akceptowalne. Narzędzie do podglądu zamówień nie.
Dlaczego akurat OAuth 2.1?
OAuth 2.1 konsoliduje współczesne wytyczne z OAuth 2.0 plus PKCE, usuwa wycofane flow implicit i resource-owner-password i pasuje do tego, co Claude Desktop i inne hosty MCP wspierają natywnie dla delegowanego dostępu agentów.
Gdzie żyją scoped tokeny?
Tokeny są wydawane przez powierzchnię administracyjną po stronie WordPressa, trzymane jako wartość zhashowana plus scope plus wygaśnięcie i weryfikowane przy każdym żądaniu MCP. Trzymanie ich jako plaintext to ten sam błąd co trzymanie haseł w plaintext.
Jak rate limiting wchodzi w auth?
Rate limity przyklejają się do principala: uwierzytelniony token ma własny bucket, ruch anonimowy dzieli bucket per IP. Narzędzia mutujące dostają węższy bucket niezależnie od principala, by skompromitowany token nie mógł zapętlić order.intent.

Potrzebujesz FAQ dopasowanego do branży i rynku? Przygotujemy wersję pod Twoje cele biznesowe.

Porozmawiajmy

Polecane artykuły

Praktyczny przebieg budowy serwera Model Context Protocol przed WooCommerce. Definicje narzędzi, endpointy katalogu i zamówień, zgodność ze schema.org, walidacja Zod oraz wdrożenie na Cloudflare Workers, z którym agent AI potrafi rozmawiać.
wordpress

Budowa serwera MCP dla WooCommerce: przewodnik praktyka

Praktyczny przebieg budowy serwera Model Context Protocol przed WooCommerce. Definicje narzędzi, endpointy katalogu i zamówień, zgodność ze schema.org, walidacja Zod oraz wdrożenie na Cloudflare Workers, z którym agent AI potrafi rozmawiać.

Przewodnik decyzyjny do wyboru pomiędzy Model Context Protocol a REST API, gdy konsumentem jest agent AI. Typowana powierzchnia vs wnioskowanie kształtu JSON, akcje mutujące, uwierzytelnianie i wzorzec hybrydowy bijący oba.
wordpress

MCP vs REST: kiedy co wygrywa dla integracji agentów AI

Przewodnik decyzyjny do wyboru pomiędzy Model Context Protocol a REST API, gdy konsumentem jest agent AI. Typowana powierzchnia vs wnioskowanie kształtu JSON, akcje mutujące, uwierzytelnianie i wzorzec hybrydowy bijący oba.

Czterotygodniowy playbook migracji do postawienia serwera Model Context Protocol przed istniejącym REST API WordPressa. Audyt endpointów, scaffold MCP, parallel-run, cutover i obserwowalność, która czyni przejście bezpiecznym.
wordpress

Migracja istniejącego API WordPress do MCP: 4-tygodniowy playbook

Czterotygodniowy playbook migracji do postawienia serwera Model Context Protocol przed istniejącym REST API WordPressa. Audyt endpointów, scaffold MCP, parallel-run, cutover i obserwowalność, która czyni przejście bezpiecznym.