Protegendo Servidores MCP: OAuth, Vinculação de Audiência e o Delegado Confuso
- Entender por que um servidor MCP remoto (HTTP) é um servidor de recursos OAuth 2.1, e não apenas um endpoint com chave de API
- Rastrear o handshake de descoberta: 401 → Protected Resource Metadata → Authorization Server Metadata → token
- Explicar a vinculação de audiência do token (RFC 8707) e por que ela impede que o token de um serviço funcione em outro
- Nomear a armadilha do delegado confuso e a única regra que a fecha: nunca repasse o token de um cliente para uma API upstream
- Aplicar uma breve checklist de hardening antes de expor um servidor MCP à internet
MCP deixou de ser novidade para se tornar a forma padrão de os agentes acessarem ferramentas — o que significa que os servidores MCP agora ficam na frente de dados reais e ações reais. Um servidor local que você inicia via STDIO confia em seu ambiente: ele lê credenciais de variáveis de ambiente e não há fronteira de rede a defender. No momento em que você torna esse mesmo servidor remoto (HTTP), qualquer um que consiga alcançar a URL pode tentar chamá-lo. Isso o transforma em um problema de autorização, e a especificação MCP responde com OAuth 2.1 — e não com um esquema de chave de API improvisado.
Esta página trata do caso remoto. Se o seu servidor for apenas STDIO, a especificação diz explicitamente para não seguir o fluxo OAuth — obtenha as credenciais do ambiente e siga em frente.
Os três papéis
O OAuth divide o problema entre três partes. O MCP se mapeia nelas de forma limpa:
A mudança mental principal: o servidor MCP nunca lida com o login em si. Ele apenas valida tokens que outra pessoa emitiu. Essa separação é o que permite colocar um provedor de identidade pronto na frente de um servidor que você escreveu.
O handshake de descoberta
Um cliente não deveria precisar ser pré-configurado com o local onde se autenticar. O MCP torna a descoberta automática, guiada por um 401:
- A primeira requisição sai sem nada. O servidor a rejeita com HTTP 401 Unauthorized e um cabeçalho WWW-Authenticate apontando para sua URL de resource-metadata.
- Ele faz um GET em /.well-known/oauth-protected-resource no servidor. O campo authorization_servers do documento nomeia pelo menos um Servidor de Autorização que o cliente pode usar.
- Ele faz um GET no /.well-known/oauth-authorization-server do AS para descobrir os endpoints authorize e token e as capacidades suportadas.
- Se o cliente não tiver um client ID para esse AS, ele pode fazer um POST em /register para obter um sem intervenção humana — crucial porque um cliente não pode conhecer todos os servidores MCP de antemão.
- O cliente gera um verifier/challenge PKCE, abre o navegador na URL authorize incluindo o parâmetro resource, o usuário consente, e o cliente troca o código retornado (com o verifier) por um token de acesso.
- Agora cada requisição carrega Authorization: Bearer <token>. O servidor o valida e responde.
Repare que não há nenhuma configuração de autenticação hardcoded do lado do cliente — o 401 inicializa tudo. Esse é justamente o objetivo: um agente pode se conectar a um servidor que nunca viu e descobrir como se autenticar.
Vinculação de audiência: a regra que sustenta tudo
Aqui está o modo de falha que a vinculação de audiência existe para evitar. Digamos que um usuário tenha um token emitido para calendar.example.com. Um servidor MCP malicioso (ou apenas desleixado) em evil.example.com engana o cliente para que envie aquele token a ele. Se evil o aceitar, ele agora pode se virar e chamar a API do calendário como se fosse o usuário. O token de um serviço funcionou em outro. A fronteira de segurança do OAuth acabou de desmoronar.
A correção são os Resource Indicators (RFC 8707):
- Tanto na requisição de autorização quanto na requisição de token, o cliente DEVE incluir um parâmetro resource definido com a URI canônica do servidor MCP que ele pretende chamar — por exemplo, resource=https://mcp.example.com. Ele envia isso mesmo sem ter certeza de que o AS o suporta.
- Quando suportado, o AS carimba o token de modo que ele só seja válido para aquele servidor de recursos específico.
- Antes de fazer qualquer trabalho, o servidor MCP DEVE verificar que o token foi emitido para ELE — checando a claim de audiência (RFC 9068). Um token gerado para qualquer outro recebe um 401, ponto final.
Parâmetro resource na requisição de autorização (URL-encoded)
&resource=https%3A%2F%2Fmcp.example.com
As URIs canônicas são rígidas: https://mcp.example.com e https://mcp.example.com:8443/mcp são válidas; mcp.example.com (sem esquema) e https://mcp.example.com#frag (fragmento) não são. Prefira a forma sem barra final para interoperabilidade.
O delegado confuso: nunca repasse o token
Este é o erro que transforma um servidor MCP bem-intencionado no proxy de um atacante. É o mesmo problema do delegado confuso da segurança de agentes, afiado em uma única regra concreta.
Um servidor MCP muitas vezes precisa chamar uma API upstream (GitHub, um serviço de banco de dados, outro SaaS). A tentação é pegar o token que o cliente lhe entregou e encaminhá-lo para o upstream. Não faça isso. A especificação é direta: o servidor MCP NÃO DEVE repassar o token que recebeu do cliente.
Por que é perigoso: o token do cliente foi emitido tendo o seu servidor como audiência. Se você o encaminha, a API upstream pode confiar nele como se tivesse vindo de você, ou presumir que você já o validou — e agora um token com escopo para um salto está fazendo trabalho a dois saltos de distância, fora do modelo de consentimento de qualquer um.
- Se o seu servidor MCP chama uma API upstream, ele age como um cliente OAuth SEPARADO para essa API e obtém seu PRÓPRIO token do servidor de autorização upstream. Dois tokens independentes, duas audiências independentes. O token do cliente para na sua porta.
Uma checklist de hardening de pré-voo
Antes que um servidor MCP remoto toque a internet pública:
- Todos os endpoints do AS DEVEM ser HTTPS. As redirect URIs DEVEM ser HTTPS ou localhost — nada mais.
- Rejeite qualquer token que não tenha sido emitido especificamente para este servidor. Essa é a única checagem que impede a reutilização de tokens entre serviços.
- Os clientes DEVEM usar PKCE para que um código de autorização interceptado seja inútil sem o verifier correspondente.
- O AS DEVE fazer a correspondência das redirect URIs de forma exata com valores pré-registrados, e os clientes DEVERIAM usar e verificar o parâmetro state — ambos defendem contra phishing por open-redirect.
- Emita tokens de acesso de curta duração para limitar o dano de um vazamento; para clientes públicos, faça a rotação dos refresh tokens. Armazene os tokens com segurança e nunca os registre em log.
- Os tokens vão no cabeçalho Authorization, nunca na query string, onde acabariam em logs e referrers.
- A vinculação de audiência é o portão de transporte; ainda assim, aplique menor privilégio, sandboxing e human-in-the-loop de /docs/security/securing-agents. A autenticação diz QUEM — ela não diz que a requisição é segura.
Teste você mesmo
Teste você mesmo
0/4Fontes e leitura adicional
- Especificação de autorização do MCP (2025-06-18) — o fluxo normativo, os papéis e os requisitos MUST/SHOULD que esta página resume.
- MCP Security Best Practices — repasse de token, delegado confuso e por que são proibidos.
- RFC 8707 — Resource Indicators for OAuth 2.0 — o parâmetro
resourcee a vinculação de audiência. - RFC 9728 — OAuth 2.0 Protected Resource Metadata — como um servidor de recursos anuncia seus servidores de autorização.
- RFC 8414 — OAuth 2.0 Authorization Server Metadata e RFC 7591 — Dynamic Client Registration.
- OAuth 2.1 draft — PKCE, segurança de comunicação e requisitos de tratamento de tokens.
- Relacionado no AILmanac: Protegendo Agentes e Ferramentas · Prompt Injection · MCP no Claude Code.