Autentiseringsmønstre for MCP: OAuth, tokens og når du bruker hva

Autentiseringsmønstre for MCP: OAuth, tokens og når du bruker hva

Sist verifisert: 22. september 2026
8 min lesetid
Guide
500+ WP-prosjekter
AI-integrasjon

#Autentiseringsmønstre for MCP: OAuth, tokens og når du bruker hva

Model Context Protocol-spesifikasjonen (modelcontextprotocol.io) definerer transporter og primitiver. Den definerer ikke autentisering. Det er riktig, for autentisering hører til transport og utrulling, ikke til protokollen. Det er også kilden til den vanligste produksjonsfeilen jeg ser: en MCP-server eksponert mot Internett uten autentisering, med verktøy som endrer tilstand. Når personopplysninger er involvert, kommer i tillegg artikkel 32 i GDPR, som krever egnede tekniske tiltak.

Artikkelen hører til pilarsiden om utvikling av MCP-servere.

#TL;DR

  • Skrivebeskyttet tilgang til offentlige data med rate limiting er det eneste legitime tilfellet for anonym tilgang.
  • Scoped API-tokens med hashing og kort TTL dekker B2B og headless.
  • OAuth 2.1 med PKCE dekker forbrukerassistenter som handler på vegne av en innlogget bruker.
  • Rate limiting knyttes til principal; verktøy som endrer tilstand, får en smalere bucket.
  • Hver autentiseringshendelse logges: utstedt, brukt, tilbakekalt, avvist.

#Slik velger du autentiseringsmetode for MCP

Før jeg velger et autentiseringsmønster, går jeg gjennom de samme fem spørsmålene:

  1. Endrer noe verktøy tilstand? Hvis ja, er anonym tilgang utelukket.
  2. Handler agenten på vegne av en bestemt menneskelig bruker? Hvis ja, OAuth.
  3. Handler agenten som en B2B-integrasjon uten menneskelig bruker? Hvis ja, scoped API-token.
  4. Er dataflaten tilgjengelig fra det offentlige Internett? Hvis ja, er rate limiting obligatorisk.
  5. Blandes verktøy som endrer tilstand og skrivebeskyttede verktøy i samme server? Hvis ja, autentiseringsscope per verktøy, ikke per server.

Treet gir tre mønstre:

MønsterNår det brukesImplementering
Anonym + rate limit per IPOffentlig katalog, skrivebeskyttet, begrenset belastningWorkeren sjekker bare IP-bucketen
Scoped API-tokenB2B-integrasjon, headless agentkjøring, ingen menneskelig brukerJWT med claims, hashet lagring, rotasjon
OAuth 2.1 + PKCEForbrukeragent for en innlogget brukerStandard authorization code flow

Mønstrene utelukker ikke hverandre. En ekte produksjonsserver kjører som regel alle tre, og hvert verktøy er merket med scopet det krever.

#Anonym, skrivebeskyttet MCP-tilgang med rate limiting

Et verktøy for katalogvisning som pakker inn /wp-json/wc/v3/products?stock_status=instock, eksponerer de samme dataene som den offentlige nettsiden allerede viser. Å sette autentisering foran det forbedrer ikke sikkerhetsnivået; det reduserer bare tilgjengeligheten. Den reelle trusselen er belastning: en agentløkke eller en konkurrent som skraper, kan banke WooCommerce-originen i stykker.

Implementering:

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 forespørsler per minutt per IP er standardverdien min. En teller basert på KV er omtrentlig (KV-skriving er eventually consistent); for strenge grenser er Durable Objects eller Cloudflares innebygde Rate Limiting binding riktig verktøy.

Hva mønsteret ikke dekker: verktøy som returnerer brukerspesifikke data, verktøy som endrer tilstand, eller verktøy som avslører lagerstatus for ikke-offentlige produkter. De krever en ekte principal.

#API-tokens med scopes for B2B-integrasjoner med MCP

B2B-tilfellet: en partnerintegrasjon leverer en agent som kaller MCP-serveren din på vegne av partnerens organisasjon, ikke på vegne av en bestemt menneskelig bruker. Eksempler er en agent for lagersynkronisering hos en grossist, en markedsplassintegrasjon hos en aggregator, eller en analyseagent som rapporterer ordretrender til BI.

Flyten:

  1. En administrator i WordPress-backend oppretter et token med navn, et sett scopes (catalogue:read, inventory:read, orders:write) og en utløpstid (standard 90 dager).
  2. Tokenet vises for administratoren én gang og lagres deretter som SHA-256-hash pluss scope-sett pluss utløpstid.
  3. Partneren konfigurerer MCP-klienten sin med tokenet i headeren Authorization: Bearer <token>.
  4. Workeren hasher det innkommende tokenet og slår opp hashen i KV. Hvis hashen stemmer, utløpstiden ligger i fremtiden og verktøyets påkrevde scope finnes i tokenets sett, går kallet videre.
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}`);
  }
}

To driftsvaner holder mønsteret ærlig:

Rotasjon, ikke evighet. Et token som aldri utløper, er et token som om seks måneder havner i et offentlig repo på GitHub. 90 dager som standard, med en fornyelsesflyt der gammelt og nytt token overlapper i 7 dager, er mønsteret som overlever ekte partnere.

Hashet lagring, ikke klartekst. Hvis KV-en din lekker, er hasher uten det opprinnelige tokenet ubrukelige. Hvis du lagret tokens i klartekst, må hver partnerintegrasjon roteres umiddelbart. Kostnadsforskjellen ved utstedelse er ett sha256-kall.

#OAuth 2.1 med PKCE i en MCP-server

Forbrukertilfellet: brukeren åpner Claude Desktop, kobler kontoen i butikken din via OAuth og ber agenten “vis min siste ordre”. Agenten må nå kalle MCP-serveren din med legitimasjon som sier “jeg handler for bruker 4231”.

OAuth 2.1 (draft-ietf-oauth-v2-1) er den konsoliderte profilen. PKCE (RFC 7636) er obligatorisk for offentlige klienter (her hører skrivebordsassistenter uten en konfidensiell serverdel hjemme).

Flyten i fem trinn:

  1. MCP-verten åpner nettleseren på autorisasjonsendepunktet ditt med response_type=code, code_challenge=<S256-hash av verifieren> og de ønskede scopene.
  2. Brukeren logger inn på WordPress-nettstedet ditt (eller hos autentiseringsleverandøren din) og godtar scopene.
  3. Autorisasjonsendepunktet ditt omdirigerer verten med en engangs autorisasjonskode.
  4. Verten bytter koden pluss den opprinnelige code_verifier på tokenendepunktet ditt mot et access token (kort TTL, 1 time) og et refresh token (lengre TTL, 30 dager).
  5. Verten kaller MCP-serveren med Authorization: Bearer <access_token>. Workeren verifiserer tokenets signatur, utløpstid og scope mot verktøyet som kalles.

Access tokenet er en signert JWT. Workeren verifiserer den med Web Crypto API (Cloudflare Workers-dokumentasjonen) uten eksternt bibliotek:

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;
}

Scopene i JWT-en speiler scopene fra scoped token-mønsteret: catalogue:read, orders:read, orders:write. WordPress-brukerens ID ligger i claimet sub, så et orders:read-kall returnerer bare ordrene til denne brukeren.

#Slik kombinerer du OAuth, tokens og anonym tilgang i én MCP-server

En ekte MCP-server for WooCommerce eksponerer som regel:

  • catalogue.list og product.detail: anonym + rate limit per IP.
  • inventory.check (for partnere): scoped token med inventory:read.
  • order.status (for innlogget bruker): OAuth med orders:read.
  • order.intent (for innlogget bruker): OAuth med orders:write, pluss smalere rate limit.

Pre-dispatch-logikken i Workeren går gjennom mønstrene:

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}`);
}

Mappingen TOOL_AUTH_REQUIREMENTS er den eneste sannhetskilden for hvilket verktøy som trenger hvilken autentiseringsmodus. Ingen verktøy legges til uten en eksplisitt oppføring.

#MCP-forespørselsgrenser per IP, token og bruker

Anonym trafikk får en bucket per IP. Tokentrafikk får en bucket per token. OAuth-trafikk får en bucket per bruker. Verktøy som endrer tilstand, får et lavere tak uansett principal.

For et typisk WooCommerce-oppsett er standard-bucketene mine:

VerktøykategoriAnonymTokenOAuth
catalogue.* (lesing)60 / minutt / IP600 / minutt / token120 / minutt / bruker
inventory.* (lesing)ikke tillatt300 / minutt / tokenikke tillatt
order.status (lesing)ikke tillatt60 / minutt / token60 / minutt / bruker
order.intent (skriving)ikke tillatt30 / minutt / token10 / minutt / bruker

Tallene er et utgangspunkt; de riktige verdiene kommer fra å observere ekte trafikk i to uker og justere. Det er strukturen som teller.

#Hvilke MCP-autentiseringshendelser du bør logge

Hver hendelse som er relevant for autentisering, havner i loggen:

  • Token utstedt. Administrator, målprincipal, scopes, utløpstid.
  • Token brukt. Token-ID, verktøynavn, principal, forsinkelse, suksess/feil.
  • Token tilbakekalt. Token-ID, hvem som tilbakekalte, hvorfor.
  • Token avvist. Årsak (utløpt, manglende scope, hash stemmer ikke), IP, user agent.
  • OAuth-kodeutveksling. Bruker-ID, tildelte scopes, utstedt refresh token.
  • OAuth-fornyelse. Bruker-ID, nytt access token, gammelt token erstattet.

Loggene sendes via Cloudflare Logpush til langtidslagring. En dashbordspørring som sporer “tokens brukt de siste 24 timene som ikke var brukt de foregående 90 dagene”, fanger sannsynlig tokentyveri. En spørring på “mislykkede tokenverifiseringer per IP” fanger forsøk på credential stuffing.

#Relaterte temaer

Denne artikkelen handler om autentisering. Bredere herding av WordPress beskrives i veiledningen om WordPress-sikkerhet. Tjenestesiden er utvikling av MCP-servere.

Prisen er individuell, fordi autentiseringsomfanget avhenger av hvilke mønstre miljøet ditt krever; en skrivebeskyttet server i anonym modus er et annet prosjekt enn en full flate som utsteder OAuth.

Neste steg

Gjør artikkelen om til faktisk implementering

Denne blokken styrker intern lenking og sender leseren videre til de mest relevante tjenestene og innholdet.

Vil du få dette implementert på nettstedet ditt?

Hvis du planlegger headless WordPress, frikoblet frontend eller migrering til Astro, kan jeg bygge arkitektur, API og frontend.

Artikkel-FAQ

Ofte stilte spørsmål

Praktiske svar for å bruke temaet i faktisk arbeid.

SEO-readyGEO-readyAEO-ready5 Q&A
Krever MCP-spesifikasjonen autentisering?#
Nei. Model Context Protocol-spesifikasjonen overlater autentisering til transportlaget. Stdio-transporter kan være betrodd bare fordi de kjører lokalt. HTTP-transporter som er eksponert mot Internett, trenger et autentiseringslag som SDK-en ikke leverer som standard.
Når er en anonym MCP-server akseptabel?#
Når hvert eksponerte verktøy kun leser offentlige data, og belastningen er begrenset med rate limiting per IP. Et verktøy for katalogvisning som pakker inn /wp-json/wc/v3/products?stock_status=instock, er akseptabelt. Et verktøy for å se ordrer er det ikke.
Hvorfor akkurat OAuth 2.1?#
OAuth 2.1 samler moderne veiledning fra OAuth 2.0 pluss PKCE, fjerner de utfasede flytene implicit og resource-owner-password og passer med det Claude Desktop og andre MCP-verter støtter innebygd for delegert agenttilgang.
Hvor lagres scoped tokens?#
Tokens utstedes fra en administrasjonsflate på WordPress-siden, lagres som hash-verdi pluss scope pluss utløpstid og verifiseres ved hver MCP-forespørsel. Å lagre dem i klartekst er samme feil som å lagre passord i klartekst.
Hvordan henger rate limiting sammen med autentisering?#
Rate limits knyttes til principal: et autentisert token har sin egen bucket, anonym trafikk deler en bucket per IP. Verktøy som endrer tilstand, får en smalere bucket uansett principal, slik at et kompromittert token ikke kan kjøre order.intent i løkke.

Trenger du FAQ tilpasset bransje og marked? Vi lager en versjon som støtter dine forretningsmål.

Ta kontakt

Relaterte artikler