Padrões de autenticação MCP: OAuth, tokens e quando usar cada um
O MCP define um perfil de autorização OAuth para transportes HTTP. Servidores públicos só de leitura podem permanecer anónimos. Ferramentas protegidas precisam de autenticação, autorização e identidade verificada. Tokens próprios de parceiros também exigem um contrato explícito de compatibilidade com o cliente MCP.
Este artigo faz parte do pilar sobre desenvolvimento de servidores MCP.
TL;DR
- Acesso só de leitura a dados públicos com rate limiting é o único caso legítimo de acesso anónimo.
- Tokens de API com scopes, guardados com hash e com TTL curto, cobrem B2B e headless.
- OAuth 2.1 com PKCE cobre assistentes de consumo que atuam em nome de um utilizador autenticado.
- O rate limiting fica associado ao principal; as ferramentas que alteram estado recebem um bucket mais apertado.
- Cada evento de autenticação é registado: emitido, usado, revogado, rejeitado.
Como escolher o método de autenticação MCP
Antes de escolher um padrão de autenticação, passo sempre pelas mesmas cinco perguntas:
- Alguma ferramenta altera estado? Se sim, o acesso anónimo fica de fora.
- O agente atua em nome de um utilizador humano concreto? Se sim, OAuth.
- O agente atua como integração B2B sem utilizador humano? Se sim, token de API com scopes.
- A superfície de dados é acessível a partir da Internet pública? Se sim, o rate limiting é obrigatório.
- No mesmo servidor misturam-se ferramentas que alteram estado e ferramentas só de leitura? Se sim, scope de autenticação por ferramenta, não por servidor.
A árvore resulta em três padrões:
| Padrão | Quando usar | Implementação |
|---|---|---|
| Anónimo + rate limit por IP | Catálogo público, só de leitura, carga limitada | O Worker verifica apenas o bucket do IP |
| Token de API com scopes | Integração B2B, runtime de agente headless, sem utilizador humano | Token opaco aleatório, armazenamento com hash, expiração e rotação |
| OAuth 2.1 + PKCE | Agente de consumo para um utilizador autenticado | Authorization code flow padrão |
Os padrões não se excluem. Um servidor de produção real costuma correr os três, e cada ferramenta fica marcada com o scope que exige.
Acesso MCP anónimo só de leitura com rate limiting
Expõe apenas campos públicos do catálogo aprovados explicitamente. A API de gestão WooCommerce wc/v3 exige credenciais no servidor e não é uma origem pública anónima. Usa um endpoint público revisto ou um adapter que exclua campos privados.
Implementação:
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 pedidos por minuto por IP é o meu valor por omissão. Um contador baseado em KV é aproximado (as escritas em KV são eventually consistent); para limites estritos, os Durable Objects ou o binding nativo de Rate Limiting da Cloudflare são a ferramenta certa.
O que este padrão não cobre: nenhuma ferramenta que devolva dados específicos de um utilizador, nenhuma que altere estado, nenhuma que revele o stock de produtos não públicos. Essas exigem um principal real.
Tokens de API com scopes para integrações B2B com MCP
O caso B2B: a integração de um parceiro fornece um agente que chama o seu servidor MCP em nome da organização do parceiro, não de um utilizador humano concreto. Exemplos: um agente de sincronização de stock num grossista, uma integração de marketplace num agregador, um agente de análise que reporta tendências de encomendas ao BI.
O fluxo:
- Um administrador no backend do WordPress cria um token com nome, um conjunto de scopes (
catalogue:read,inventory:read,orders:write) e uma data de expiração (por omissão, 90 dias). - O token é mostrado ao administrador uma vez e depois guardado como hash SHA-256 mais o conjunto de scopes mais a expiração.
- O parceiro configura o seu cliente MCP com o token no cabeçalho
Authorization: Bearer <token>. - O Worker calcula o hash do token recebido e procura-o no KV. Se o hash corresponder, a expiração estiver no futuro e o scope exigido pela ferramenta estiver no conjunto do token, a chamada segue.
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");
}Dois hábitos operacionais mantêm o padrão honesto:
Rotação, não eternidade. Um token que nunca expira é um token que daqui a seis meses aparece num repositório público no GitHub. 90 dias por omissão, com um fluxo de renovação em que o token antigo e o novo coexistem durante 7 dias, é o padrão que sobrevive a parceiros reais.
Armazenamento com hash, não em texto simples. Se o seu KV for exposto, os hashes sem o token original são inúteis. Se guardou os tokens em texto simples, todas as integrações de parceiros precisam de rotação imediata. A diferença de custo no momento da emissão é uma chamada a sha256.
OAuth 2.1 com PKCE num servidor MCP
O caso de consumo: o utilizador abre o Claude Desktop, liga a conta da sua loja por OAuth e pede ao agente “mostra a minha última encomenda”. O agente tem agora de chamar o seu servidor MCP com credenciais que dizem “estou a atuar pelo utilizador 4231”.
O OAuth 2.1 (draft-ietf-oauth-v2-1) é o perfil consolidado. O PKCE (RFC 7636) é obrigatório para clientes públicos (onde se incluem os assistentes de desktop sem uma parte de servidor confidencial).
O fluxo em cinco passos:
- O host MCP abre o browser no seu endpoint de autorização com
response_type=code,code_challenge=<hash S256 do verifier>e os scopes pedidos. - O utilizador inicia sessão no seu site WordPress (ou no seu fornecedor de autenticação) e aceita os scopes.
- O seu endpoint de autorização redireciona o host com um código de autorização de utilização única.
- O host troca o código mais o
code_verifieroriginal no seu endpoint de tokens por um access token (TTL curto, 1 hora) e um refresh token (TTL mais longo, 30 dias). - O host chama o servidor MCP com
Authorization: Bearer <access_token>. O Worker verifica a assinatura do token, a expiração e o scope face à ferramenta chamada.
Um token OAuth pode ser opaco ou JWT. O exemplo usa um emissor configurado e a biblioteca jose mantida para validar assinatura e 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) };
}Os scopes no JWT espelham os do padrão de token com scopes: catalogue:read, orders:read, orders:write. O ID do utilizador WordPress fica no claim sub, por isso uma chamada orders:read devolve apenas as encomendas desse utilizador.
Como combinar OAuth, tokens e acesso anónimo num servidor MCP
Um servidor MCP real para WooCommerce costuma expor:
catalogue.listeproduct.detail: anónimo + rate limit por IP.inventory.check(para parceiros): token com scopeinventory:read.order.status(para o utilizador autenticado): OAuth comorders:read.order.intent(para o utilizador autenticado): OAuth comorders:write, mais um rate limit mais apertado.
A lógica de pre-dispatch no Worker percorre os padrões:
Autentica HTTP antes do dispatch MCP. Verifica depois os scopes da ferramenta e a propriedade do recurso. Recusa ferramentas desconhecidas e políticas ausentes. As falhas de autenticação precisam de challenges bearer HTTP, em vez de códigos JSON-RPC inventados como texto.
O mapa TOOL_AUTH_REQUIREMENTS é a única fonte de verdade sobre que ferramenta precisa de que modo de autenticação. Nenhuma ferramenta é adicionada sem uma entrada explícita.
Limites de pedidos MCP por IP, token e utilizador
O tráfego anónimo recebe um bucket por IP. O tráfego com token recebe um bucket por token. O tráfego OAuth recebe um bucket por utilizador. As ferramentas que alteram estado recebem um teto mais baixo independentemente do principal.
Os valores seguintes são exemplos de configuração, não medições nem limites predefinidos de produção. Define os limites efetivos pela capacidade da origem e pelo tráfego observado.
| Categoria de ferramenta | Anónimo | Token | OAuth |
|---|---|---|---|
catalogue.* (leitura) | 60 / minuto / IP | 600 / minuto / token | 120 / minuto / utilizador |
inventory.* (leitura) | não permitido | 300 / minuto / token | não permitido |
order.status (leitura) | não permitido | 60 / minuto / token | 60 / minuto / utilizador |
order.intent (escrita) | não permitido | 30 / minuto / token | 10 / minuto / utilizador |
Os números são um ponto de partida; os valores certos resultam de observar tráfego real durante duas semanas e afinar. O que conta é a estrutura.
Que eventos de autenticação MCP registar
Cada evento relevante para a autenticação vai para o registo:
- Token emitido. Administrador, principal de destino, scopes, expiração.
- Token usado. ID do token, nome da ferramenta, principal, latência, sucesso/falha.
- Token revogado. ID do token, quem revogou, porquê.
- Token rejeitado. Motivo (expirado, scope em falta, hash não corresponde), IP, user agent.
- Troca de código OAuth. ID do utilizador, scopes concedidos, refresh token emitido.
- Refresh OAuth. ID do utilizador, novo access token, token antigo substituído.
Os registos seguem pelo Cloudflare Logpush para armazenamento de longo prazo. Uma consulta de dashboard que acompanha “tokens usados nas últimas 24 horas que não tinham sido usados nos 90 dias anteriores” apanha um provável roubo de token. Uma consulta sobre “verificações de token falhadas por IP” apanha tentativas de credential stuffing.
Discovery e identidade do recurso protegido
A especificação de autorização MCP de 2025-11-25 define um fluxo OAuth para transportes HTTP. A autorização é opcional, mas um servidor HTTP protegido e interoperável precisa dos mecanismos de discovery e validação desse perfil. Stdio tem uma fronteira diferente e obtém credenciais do ambiente. Tokens próprios podem servir uma integração controlada com parceiros. Não pressuponhas que qualquer host MCP consegue descobrir ou obter essas credenciais. Testa o host e o transporte efetivamente usados.
Separa os papéis do servidor de recursos MCP e do servidor de autorização, mesmo quando vivem na mesma aplicação. O primeiro executa ferramentas e valida o acesso. O segundo trata de login, consentimento e emissão de tokens. Publica os metadados do recurso protegido com a sua identidade canónica e os servidores de autorização. Uma resposta HTTP 401 pode apontar para esses metadados através de WWW-Authenticate. Os endereços têm de continuar corretos atrás do reverse proxy e com prefixos de caminho. Ver um formulário de login não prova que o host descobriu o emissor certo.
O cliente pede um access token destinado ao recurso MCP através do parâmetro resource. O servidor valida essa associação. Um token de outra API não se torna aceitável apenas por ter uma assinatura válida de um emissor conhecido. Rejeita audience e issuer inesperados antes da execução. Usa o mesmo URI canónico nos metadados, no pedido de autorização e na verificação. Não calcules a audience esperada a partir de um cabeçalho Host não fiável ou de um parâmetro livre do cliente.
Validação completa e credenciais dos serviços de origem
Os access tokens OAuth podem ser opacos ou JWT. O protocolo não obriga todos os emissores a usar JWT. Um token opaco exige o mecanismo de verificação suportado pelo emissor. Um verificador JWT controla assinatura, algoritmo permitido, issuer, audience e validade temporal. Depois valida os campos da aplicação que utiliza. Uma asserção de tipo TypeScript não verifica valores em runtime. JSON malformado, ausência de subject ou scope com tipo incorreto deve causar uma recusa controlada. Usa uma biblioteca mantida e uma fonte de confiança configurada, em vez de um verificador parcial escrito com Web Crypto.
Obtém as chaves do endereço JWKS configurado para o emissor, não de um URL arbitrário dentro do token. Prepara a rotação de chaves e a indisponibilidade do emissor. Uma falha ao obter a chave não pode permitir um token sem verificação. Uma chave fiável já guardada pode funcionar segundo a política definida, mas uma chave desconhecida continua a exigir uma decisão explícita. Testa tokens expirados, ainda não válidos, algoritmos diferentes e tokens de outro ambiente. As credenciais de staging não devem funcionar na produção por acidente.
As orientações de segurança MCP proíbem token passthrough. Um bearer token destinado ao servidor MCP não pode seguir para WooCommerce ou ERP como credencial desses serviços. Guarda as credenciais de origem no servidor e autoriza a ação antes de as utilizar. Se o serviço precisa de identidade delegada, estabelece o contrato de delegação ou troca de tokens que suporta. Copiar o cabeçalho Authorization recebido não constitui um modelo de delegação.
Scopes e propriedade de encomendas
Autentica o pedido HTTP e verifica depois os scopes da operação. Uma validação de token bem-sucedida não dispensa a autorização da ferramenta. O registo de ferramentas deve indicar as permissões de cada operação. Uma entrada desconhecida é recusada. Cada alteração precisa de testes para chamadas permitidas e rejeitadas. A lista de discovery também necessita de uma política para descrições e parâmetros sensíveis. Conhecer o nome de uma ferramenta não concede o direito de a executar.
orders:read define a categoria da ação, não o proprietário das encomendas. Associa o subject validado a uma conta interna através de um mapeamento fiável e verifica a propriedade ao carregar a encomenda. Um identificador de cliente enviado pelo agente não prova autorização. O parceiro com acesso a toda uma organização necessita de concessão separada e fronteira de tenant definida. Um distribuidor português que importa stock e um cliente que consulta a entrega usam identidades diferentes, mesmo quando acedem ao mesmo servidor MCP.
Trata as falhas de bearer authentication na camada HTTP adequada. Um token ausente ou inválido gera uma recusa de autenticação. Scopes insuficientes exigem o challenge correspondente. Um access token expirado não deve parecer um resultado comercial de falta de stock. Separar os casos permite ao host renovar a autorização ou pedir consentimento, em vez de repetir a operação com credenciais inalteradas.
Revogação, quotas e testes de publicação
Gera tokens opacos com aleatoriedade criptográfica suficiente. Guardar hashes ajuda apenas quando o segredo original é difícil de adivinhar. Separa o identificador público do segredo e usa uma implementação de verificação revista. Define a propagação da revogação. Workers KV é eventually consistent, por isso eliminar um registo não garante revogação global imediata. Operações sensíveis podem precisar de uma consulta à fonte autoritativa ou de outra fronteira de consistência. A validade curta limita exposição, mas não substitui revogação.
O rate limiting também tem um modelo de consistência. O binding de rate limiting Workers limita volume de pedidos, mas não constitui um orçamento transacional global para encomendas ou operações pagas. Usa um coordenador autoritativo adequado para quotas comerciais. Ler e depois escrever em KV não é um incremento atómico. Pedidos concorrentes podem perder atualizações. As repetições do agente não podem gerar mais operações do que a ação pretendida.
Antes de publicar, testa discovery pelo hostname de produção, consentimento, expiração, refresh, revogação e scopes insuficientes com o host MCP escolhido. Inclui acesso à encomenda de outro cliente e a outro tenant. Confirma que resultados privados não entram numa cache partilhada. Regista identificador de token, identidade, ferramenta e resultado sem segredos nem payloads de clientes. Separa eventos de segurança de traces de diagnóstico e define a retenção de cada repositório. O login bem-sucedido é apenas o início do teste de controlo de acesso.
Temas relacionados
Este artigo trata da autenticação. O reforço mais amplo do WordPress está no guia de segurança WordPress. A página do serviço é desenvolvimento de servidores MCP.
Orçamento individual, porque o âmbito da autenticação depende dos padrões que o seu ambiente exige; um servidor só de leitura em modo anónimo é um projeto diferente de uma superfície completa que emite OAuth.







