Wzorce uwierzytelniania MCP: OAuth, tokeny i kiedy co
MCP definiuje profil autoryzacji OAuth dla transportów HTTP. Publiczne serwery tylko do odczytu mogą działać anonimowo. Chronione narzędzia wymagają uwierzytelnienia, kontroli uprawnień i zweryfikowanego podmiotu. Prywatne tokeny partnerów wymagają też jawnego kontraktu zgodności z klientem MCP.
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.
Jak wybrać metodę uwierzytelniania MCP
Przed wyborem wzorca auth przepuszczam pięć tych samych pytań:
- Czy któreś narzędzie zmienia stan? Jeśli tak, anonim odpada.
- Czy agent działa w imieniu konkretnego ludzkiego użytkownika? Jeśli tak, OAuth.
- Czy agent działa jako integracja B2B bez ludzkiego użytkownika? Jeśli tak, scoped token API.
- Czy powierzchnia danych jest osiągalna w publicznym Internecie? Jeśli tak, rate limiting jest obowiązkowy.
- 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:
| Wzorzec | Kiedy używać | Implementacja |
|---|---|---|
| Anonim + rate limit IP | Publiczny katalog, tylko-do-odczytu, ograniczone obciążenie | Worker sprawdza tylko bucket IP |
| Scoped token API | Integracja B2B, headless’owy runtime agenta, brak ludzkiego użytkownika | JWT z claimami, hashowane przechowywanie, rotacja |
| OAuth 2.1 + PKCE | Konsumencki agent dla zalogowanego użytkownika | Standardowy authorization code flow |
Wzorce się nie wykluczają. Realny serwer produkcyjny zwykle uruchamia wszystkie trzy, a każde narzędzie jest otagowane wymaganym scope’em.
Anonimowy dostęp do MCP tylko do odczytu z rate limitem
Udostępniaj wyłącznie wybrane publiczne pola katalogu. Zarządcze API WooCommerce wc/v3 wymaga poświadczeń po stronie serwera i nie jest anonimowym źródłem publicznym. Użyj sprawdzonego publicznego endpointu albo adaptera, który usuwa prywatne pola.
Implementacja:
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 żą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.
Tokeny API ze scope’ami dla integracji B2B z MCP
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:
- 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). - Token jest pokazywany administratorowi raz, potem trzymany jako hash SHA-256 plus zestaw scope’ów plus wygaśnięcie.
- Partner konfiguruje swojego klienta MCP z tokenem w nagłówku
Authorization: Bearer <token>. - 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 Error("Insufficient 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.
OAuth 2.1 z PKCE w serwerze MCP
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:
- Host MCP otwiera przeglądarkę na twoim endpoincie autoryzacji z
response_type=code,code_challenge=<S256 hash verifiera>i żądanymi scope’ami. - Użytkownik loguje się na twojej stronie WordPress (lub u twojego dostawcy auth) i akceptuje scope’y.
- Twój endpoint autoryzacji przekierowuje hosta z jednorazowym kodem autoryzacji.
- Host wymienia kod plus oryginalny
code_verifierna twoim endpoincie tokenów na access token (krótki TTL, 1 godzina) i refresh token (dłuższy TTL, 30 dni). - Host woła serwer MCP z
Authorization: Bearer <access_token>. Worker weryfikuje podpis tokena, wygaśnięcie i scope wobec wołanego narzędzia.
Token OAuth może być nieprzezroczysty albo mieć format JWT. Przykład używa skonfigurowanego wystawcy i utrzymywanej biblioteki jose do weryfikacji podpisu oraz 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) };
}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.
Jak połączyć OAuth, tokeny i dostęp anonimowy w jednym serwerze MCP
Realny serwer MCP dla WooCommerce zwykle wystawia:
catalogue.listiproduct.detail: anonim + rate limit IP.inventory.check(dla partnerów): scoped token zinventory:read.order.status(dla zalogowanego użytkownika): OAuth zorders:read.order.intent(dla zalogowanego użytkownika): OAuth zorders:write, plus węższy rate limit.
Logika pre-dispatch w Workerze przechodzi przez wzorce:
Uwierzytelnij HTTP przed dispatch MCP. Następnie sprawdź scope narzędzia i własność zasobu. Odrzucaj nieznane narzędzia oraz brak polityki. Błędy uwierzytelnienia zwracaj jako wyzwania bearer na HTTP zamiast wymyślać tekstowe kody JSON-RPC.
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.
Limity zapytań MCP na IP, token i użytkownika
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.
Poniższe wartości są przykładami konfiguracji, nie pomiarami ani domyślnymi limitami produkcji. Docelowe limity wynikają z wydajności źródła i obserwowanego ruchu.
| Kategoria narzędzia | Anonim | Token | OAuth |
|---|---|---|---|
catalogue.* (odczyt) | 60 / minutę / IP | 600 / minutę / token | 120 / minutę / użytkownika |
inventory.* (odczyt) | nie wolno | 300 / minutę / token | nie wolno |
order.status (odczyt) | nie wolno | 60 / minutę / token | 60 / minutę / użytkownika |
order.intent (zapis) | nie wolno | 30 / minutę / token | 10 / 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.
Jakie zdarzenia uwierzytelniania MCP logować
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.
Discovery, tożsamość zasobu i odpowiedź HTTP
Specyfikacja autoryzacji MCP z 2025-11-25 definiuje przepływ OAuth dla transportów HTTP. Obsługa autoryzacji jest opcjonalna, ale chroniony, interoperacyjny serwer HTTP potrzebuje mechanizmów discovery i walidacji określonych w tym profilu. Stdio ma inną granicę wdrożenia i pobiera poświadczenia ze środowiska. Własne tokeny partnerów mogą obsługiwać kontrolowaną integrację. Nie zakładaj jednak, że dowolny host MCP potrafi sam je odkryć albo uzyskać. Sprawdź konkretną aplikację kliencką i transport.
Rozdziel role serwera zasobu MCP i serwera autoryzacji, nawet gdy działają w jednej aplikacji. Pierwszy wykonuje narzędzia i weryfikuje dostęp. Drugi obsługuje logowanie, zgodę oraz wydawanie tokenów. Opublikuj metadane chronionego zasobu z jego kanonicznym identyfikatorem i listą serwerów autoryzacji. Odpowiedź HTTP 401 może wskazywać te metadane nagłówkiem WWW-Authenticate. Adresy muszą działać przez reverse proxy i z prefiksem ścieżki endpointu. Samo wyświetlenie formularza logowania nie dowodzi, że host MCP znalazł właściwego wystawcę.
Klient żąda tokenu przeznaczonego dla zasobu MCP za pomocą parametru resource. Serwer sprawdza, czy token rzeczywiście został wydany dla tego zasobu. Poprawny podpis znanego wystawcy nie wystarcza, gdy token jest przeznaczony dla innego API. Odrzuć nieoczekiwane audience i issuer przed wykonaniem narzędzia. Używaj spójnego URI zasobu w metadanych, żądaniu autoryzacji i walidacji. Nie ustalaj oczekiwanego audience na podstawie niezaufanego nagłówka Host ani parametru podanego przez klienta.
Weryfikacja JWT i poświadczenia systemów źródłowych
Token OAuth może być nieprzezroczysty albo mieć format JWT. Protokół nie wymaga JWT od każdego wystawcy. Dla tokenu nieprzezroczystego zastosuj metodę weryfikacji wspieraną przez wystawcę. Dla JWT sprawdzaj podpis, dozwolony algorytm, issuer, audience i daty ważności, a następnie pola aplikacyjne. Rzutowanie typu w TypeScript niczego nie weryfikuje w runtime. Błędny JSON, brak subject albo scope o niewłaściwym typie musi prowadzić do kontrolowanego odrzucenia. Korzystaj z utrzymywanej biblioteki oraz skonfigurowanego źródła zaufania zamiast pisać częściowy weryfikator Web Crypto.
Pobieraj klucze z skonfigurowanego adresu JWKS wystawcy. Nie używaj dowolnego URL umieszczonego wewnątrz tokenu. Przygotuj obsługę rotacji kluczy i niedostępności wystawcy. Awaria pobrania klucza nie może dopuścić nieweryfikowanego tokenu. Wcześniej zapisany zaufany klucz może działać zgodnie z określoną polityką, ale nieznany klucz wymaga jawnej decyzji. Testuj token po terminie, token jeszcze nieważny, zmianę algorytmu i token dla innego środowiska. Poświadczenia stagingu nie powinny działać na produkcji przypadkiem.
Wytyczne bezpieczeństwa MCP zabraniają token passthrough. Token dla serwera MCP nie może być przekazany dalej jako poświadczenie WooCommerce albo ERP. Klucze systemów źródłowych przechowuj po stronie serwera. Przed ich użyciem sprawdzaj uprawnienia do operacji. Jeśli system źródłowy potrzebuje delegowanej tożsamości, zastosuj wspierany przez niego przepływ delegacji albo wymiany tokenu. Kopiowanie przychodzącego Authorization nie tworzy poprawnego modelu delegacji.
Zakres operacji i własność zamówienia
Najpierw uwierzytelnij żądanie HTTP, następnie sprawdź scope wymagany przez wykonywaną operację. Poprawna weryfikacja tokenu nie może pomijać kontroli narzędzia. Rejestr narzędzi powinien zawierać wymagane uprawnienia dla każdej pozycji, a brak wpisu oznacza odmowę. Zmiana rejestru potrzebuje testu dozwolonego oraz niedozwolonego wywołania. Lista narzędzi również wymaga zasad publikowania wrażliwych opisów i parametrów. Znajomość nazwy narzędzia nie przyznaje prawa do uruchomienia.
Scope orders:read określa kategorię operacji, nie właściciela zamówienia. Powiąż zweryfikowany subject z kontem wewnętrznym za pomocą zaufanego mapowania, a następnie sprawdź własność przy odczycie. Identyfikator klienta przekazany przez agenta nie jest dowodem uprawnienia. Partner z dostępem do całej organizacji potrzebuje osobnego nadania praw i określonej granicy tenantów. Hurtownia aktualizująca stan magazynu i klient sprawdzający dostawę mają inne podmioty dostępu, nawet jeśli korzystają z tego samego wdrożenia MCP.
Błędy bearer authentication obsługuj na właściwej warstwie HTTP. Brak albo nieprawidłowy token wymaga odmowy uwierzytelnienia. Brak zakresu wymaga odpowiedniego wyzwania z informacją o scope. Wygasły token nie powinien wyglądać jak odpowiedź narzędzia o braku produktu w magazynie. Rozdzielenie tych sytuacji pozwala hostowi odświeżyć dostęp albo poprosić o zgodę zamiast ponawiać operację biznesową z niezmienionymi poświadczeniami.
Odwołanie dostępu, limity i test wydania
Nieprzezroczyste tokeny partnerów generuj z odpowiednią losowością kryptograficzną. Hash w bazie pomaga tylko wtedy, gdy oryginalny sekret jest trudny do odgadnięcia. Oddziel publiczny identyfikator tokenu od sekretu i korzystaj ze sprawdzonej implementacji weryfikacji. Określ czas propagacji odwołania. Workers KV jest eventually consistent, więc usunięcie rekordu nie gwarantuje natychmiastowego odcięcia dostępu globalnie. Wrażliwe operacje mogą wymagać sprawdzenia w autorytatywnym źródle albo innej granicy spójności. Krótka ważność ogranicza ekspozycję, ale nie zastępuje odwołania.
Limiter również ma model spójności. Binding rate limiting Workers ogranicza ruch, lecz nie stanowi globalnego transakcyjnego budżetu zamówień lub płatnych operacji. Dla limitu biznesowego zastosuj właściwy autorytatywny koordynator. Odczyt KV, a następnie zapis nie jest atomowym zwiększeniem licznika. Równoległe żądania mogą zgubić aktualizacje. Ponowienia agenta nie mogą tworzyć większej liczby zapisów niż zamierzona operacja.
Przed wydaniem sprawdź discovery z docelowej domeny, zgodę, wygaśnięcie, odświeżenie, odwołanie i brak scope w używanym hoście MCP. Dodaj test dostępu do zamówienia innego klienta oraz test granicy tenantów. Potwierdź brak prywatnych odpowiedzi we wspólnym cache. W audycie zapisuj identyfikator tokenu, podmiot, narzędzie i wynik bez sekretów oraz danych zamówienia. Oddziel zdarzenia bezpieczeństwa od szczegółowych śladów diagnostycznych i określ retencję. Udane logowanie dopiero rozpoczyna test kontroli dostępu.
Powiązane tematy
Ten artykuł omawia uwierzytelnianie. Przebieg implementacji opisuje budowa serwera MCP dla WooCommerce. Typowane definicje narzędzi pokazuje tekst o pisaniu typowanych narzędzi katalogu z Zod dla MCP. Decyzję na poziomie protokołu opisuje MCP vs REST. Ścieżkę migracji z istniejącego API opisuje migracja API WordPress do MCP. Strona usługi 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.







