Skip to main content

Cyber AI România

Server MCP securizat de la zero: OAuth 2.1, permisiuni granulare și controlul accesului la tool-uri

Un server MCP poate expune operațiuni mult mai sensibile decât un API obișnuit: citirea documentelor, interogarea bazelor de date, trimiterea emailurilor sau modificarea unor sisteme externe. Autentificarea utilizatorului nu este suficientă. Serverul trebuie să verifice și ce tool-uri are voie să folosească, asupra căror resurse și în ce condiții.

Pentru un server MCP remote, transmis prin Streamable HTTP, specificația MCP folosește arhitectura OAuth 2.1. Serverul MCP este Resource Server, clientul MCP este client OAuth, iar un Authorization Server separat autentifică utilizatorul și emite access tokenurile. Pentru serverele locale care comunică prin STDIO, pot fi folosite alte metode de furnizare a credențialelor.

Separă autentificarea de serverul MCP

Nu construi propriul sistem de parole în serverul MCP. Folosește un Authorization Server verificat, precum Keycloak, Microsoft Entra ID, Okta sau o infrastructură OAuth administrată intern.

Arhitectura trebuie să arate astfel:

Client MCP
   ↓ autentificare și consimțământ
Authorization Server
   ↓ access token
Server MCP
   ↓ verificare token, scope și politică
Tool autorizat

Serverul MCP validează tokenul, dar nu îl emite. SDK-ul oficial Python implementează această separare printr-un TokenVerifier, iar setările de autentificare publică metadatele necesare descoperirii Authorization Server-ului.

Un schelet minimal poate porni astfel:

from pydantic import AnyHttpUrl
from mcp.server.auth.provider import AccessToken, TokenVerifier
from mcp.server.auth.settings import AuthSettings
from mcp.server.fastmcp import FastMCP


class JWTVerifier(TokenVerifier):
    async def verify_token(self, token: str) -> AccessToken | None:
        # Verifică semnătura, issuer, audience, expirarea și scopes.
        return validate_access_token(token)


mcp = FastMCP(
    "Company MCP",
    token_verifier=JWTVerifier(),
    auth=AuthSettings(
        issuer_url=AnyHttpUrl("https://auth.example.ro"),
        resource_server_url=AnyHttpUrl("https://mcp.example.ro"),
        required_scopes=["mcp:connect"],
    ),
)

În producție, validate_access_token() trebuie să valideze criptografic tokenul și să respingă tokenurile expirate, emise de alt issuer sau destinate altui serviciu.

Publică metadatele OAuth corect

Serverul trebuie să implementeze OAuth Protected Resource Metadata, conform RFC 9728, astfel încât clientul MCP să poată descoperi Authorization Server-ul și scope-urile disponibile. La o cerere fără token, serverul răspunde cu 401 Unauthorized și poate indica URL-ul metadatelor și scope-ul minim necesar.

Clientul trebuie să folosească Authorization Code Flow cu PKCE. Specificația MCP cere PKCE și metoda S256, iar endpointurile de autorizare trebuie servite prin HTTPS. Redirect URI-urile trebuie să fie HTTPS sau localhost pentru aplicațiile locale.

Definește scopes pentru acțiuni, nu pentru aplicația întreagă

Nu crea un singur scope numit mcp:full-access. Separă citirea de modificare și operațiunile obișnuite de cele periculoase:

mcp:connect
files:read
files:write
crm:read
crm:update
email:draft
email:send
users:read
users:admin

Construiește apoi o politică explicită:

TOOL_SCOPES = {
    "search_documents": {"files:read"},
    "create_document": {"files:write"},
    "find_customer": {"crm:read"},
    "update_customer": {"crm:update"},
    "draft_email": {"email:draft"},
    "send_email": {"email:send"},
}

Înainte de fiecare apel, handlerul trebuie să compare scope-urile tokenului cu cele cerute de tool:

def authorize(tool_name: str, granted_scopes: set[str]) -> None:
    required = TOOL_SCOPES[tool_name]

    if not required.issubset(granted_scopes):
        raise InsufficientScope(required)

Dacă tokenul este invalid sau lipsește, răspunsul corect este 401. Dacă utilizatorul este autentificat, dar nu are permisiunea necesară, serverul trebuie să răspundă cu 403 Forbidden și insufficient_scope. Clientul poate iniția apoi un flux de autorizare suplimentară, numit step-up authorization.

Verifică obligatoriu audience-ul tokenului

Clientul trebuie să includă parametrul resource în cererea de autorizare și în cererea de token. Serverul MCP acceptă numai tokenuri emise special pentru URI-ul său canonic.

Nu primi un token emis pentru Google, Microsoft Graph sau alt API și nu îl transmite mai departe. Token passthrough este interzis deoarece poate ocoli controalele, poate produce probleme de audit și poate transforma serverul într-un confused deputy. Pentru un API extern, serverul MCP trebuie să obțină un token separat, emis pentru acel API.

Protejează tool-urile cu impact ridicat

Operațiunile precum send_email, delete_file, create_payment sau disable_user trebuie să combine:

scope dedicat;
rol sau grup autorizat;
validarea parametrilor;
limită de volum;
confirmare umană;
jurnal de audit.

MCP recomandă ca utilizatorul să vadă ce tool este invocat și să poată refuza operațiunile. Annotations descriu comportamentul unui tool, dar nu trebuie tratate drept mecanism de securitate; clientul trebuie să le considere neverificate dacă nu provin de la un server de încredere.

Înregistrează pentru fiecare apel identitatea stabilă a utilizatorului, clientul MCP, tool-ul, scope-urile, resursa, rezultatul și ora. Nu salva access tokenul integral, parole, chei API sau conținut confidențial inutil.

Un server MCP securizat aplică aceeași regulă la fiecare nivel: tokenul confirmă identitatea și delegarea, scope-ul limitează capabilitatea, politica decide dacă operațiunea este permisă, iar omul aprobă acțiunile cu impact major.

Surse folosite

Model Context Protocol – Authorization Specification 2025-11-25
Model Context Protocol – Understanding Authorization in MCP
Model Context Protocol – Security Best Practices
Model Context Protocol – Tools Specification
MCP Python SDK – Server-Side Authentication și TokenVerifier
IETF – RFC 9728, OAuth Protected Resource Metadata
IETF – RFC 9700, OAuth 2.0 Security Best Current Practice
IETF – RFC 8707, Resource Indicators for OAuth 2.0

Facebook
X
WhatsApp

Te-ar putea interesa si: