Sécurité et authentification de MCP
Ajoutez l’authentification à votre serveur MCP à l’aide de jetons OAuth 2.0, mettez en place la validation des entrées pour empêcher les attaques par injection et appliquez le principe du moindre privilège aux autorisations des outils.
Sécurité et authentification de MCP est une leçon AI Engineering Academy gratuite sur CoddyKit. Ceci est la leçon 4 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage AI Engineering Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours AI Engineering Academy comprend 4 leçons au total.
Pourquoi la sécurité de MCP est importante
Un serveur MCP est une passerelle vers vos systèmes. Sans sécurité appropriée, un client IA compromis ou un prompt malveillant pourrait lire des données sensibles, déclencher des opérations destructrices ou exfiltrer des informations par le canal d’appel des outils. La sécurité des serveurs MCP doit reposer sur une défense en profondeur : authentification au niveau du transport, autorisation au niveau des outils et validation des données d’entrée à chaque appel.
Sécurité des serveurs locaux et distants
Le transport stdio (utilisé par Claude Desktop) offre une sécurité inhérente : le serveur s’exécute comme un processus local et n’est accessible qu’à l’utilisateur qui l’a lancé. Les serveurs MCP exposés sur le réseau et utilisant HTTP/SSE sont confrontés à l’ensemble des menaces de sécurité du Web : contournement de l’authentification, attaques par injection et accès non autorisé. Les exigences de sécurité varient considérablement selon le mode de déploiement.
- stdio local : faites confiance à l’utilisateur local et concentrez-vous sur la validation des données d’entrée
- HTTP/SSE distant : authentification complète, TLS, limitation du débit et assainissement des données d’entrée
Authentification par clé d’API pour les serveurs distants
La méthode d’authentification la plus simple pour les serveurs MCP distants consiste à valider une clé d’API transmise dans un en-tête HTTP. Vérifiez l’en-tête Authorization: Bearer <token> pour chaque requête entrante et rejetez les requêtes non authentifiées avec le code HTTP 401. Stockez les clés d’API valides dans une base de données avec les métadonnées de l’utilisateur afin de pouvoir révoquer chaque clé individuellement.
# For HTTP/SSE MCP servers using FastAPI or similar:
from fastapi import FastAPI, HTTPException, Depends, Header
from typing import Optional
import secrets
app_http = FastAPI()
# In production: store in database with user_id, created_at, last_used
VALID_KEYS = {'sk-mcp-abc123': {'user': 'alice', 'scopes': ['read']},
'sk-mcp-def456': {'user': 'bob', 'scopes': ['read', 'write']}}
async def verify_api_key(authorization: Optional[str] = Header(None)) -> dict:
if not authorization or not authorization.startswith('Bearer '):
raise HTTPException(status_code=401, detail='Missing API key')
key = authorization.removeprefix('Bearer ')
if key not in VALID_KEYS:
raise HTTPException(status_code=401, detail='Invalid API key')
return VALID_KEYS[key] # Returns user context
# Use in route handlers:
# @app_http.get('/sse')
# async def sse_endpoint(user=Depends(verify_api_key)):OAuth 2.0 pour les serveurs MCP d’entreprise
Pour les déploiements d’entreprise, utilisez OAuth 2.0 afin que les utilisateurs s’authentifient auprès de leur fournisseur d’identité d’entreprise (Okta, Azure AD, Google Workspace). Le client MCP obtient un jeton d’accès OAuth, qu’il inclut dans les requêtes d’appel d’outil. Votre serveur valide la signature du jeton par rapport aux clés publiques du fournisseur d’identité à l’aide de python-jose ou authlib.
from jose import jwt, JWTError
import httpx
AUTH_DOMAIN = 'your-tenant.auth0.com'
AUDIENCE = 'https://api.your-mcp-server.com'
async def get_jwks():
async with httpx.AsyncClient() as client:
resp = await client.get(f'https://{AUTH_DOMAIN}/.well-known/jwks.json')
return resp.json()
async def verify_oauth_token(token: str) -> dict:
jwks = await get_jwks()
try:
payload = jwt.decode(
token,
jwks,
algorithms=['RS256'],
audience=AUDIENCE,
issuer=f'https://{AUTH_DOMAIN}/'
)
return payload # Contains sub (user ID), scope, exp, etc.
except JWTError as e:
raise ValueError(f'Invalid token: {e}')Autorisation fondée sur les portées
Tous les outils MCP ne doivent pas être accessibles à tous les utilisateurs. Utilisez les portées OAuth ou les revendications de rôle du jeton JWT pour déterminer quels outils l’utilisateur authentifié peut appeler. Vérifiez l’autorisation au début de chaque exécution d’outil, avant tout appel à une base de données ou à une API.
TOOL_REQUIRED_SCOPES = {
'list_products': ['read:products'],
'search_products': ['read:products'],
'create_order': ['write:orders'],
'delete_order': ['admin:orders']
}
def check_authorization(tool_name: str, token_payload: dict):
'''Raise ValueError if user lacks required scope for the tool.'''
required = TOOL_REQUIRED_SCOPES.get(tool_name, [])
if not required:
return # No scope required
user_scopes = set(token_payload.get('scope', '').split())
missing = [s for s in required if s not in user_scopes]
if missing:
raise ValueError(
f'Access denied. Tool "{tool_name}" requires scopes: {missing}. '
f'Your token has: {list(user_scopes)}'
)
# In call_tool handler:
# check_authorization(name, current_user_token)
# ... then execute the toolValidation des données d’entrée et prévention des injections
Toutes les données d’entrée des outils sont en définitive des chaînes générées par un LLM : considérez-les comme non fiables. Validez chaque donnée d’entrée par rapport aux types et aux modèles attendus avant de l’utiliser. Protégez-vous notamment contre les menaces suivantes : injection SQL (utilisez des requêtes paramétrées, jamais du SQL interpolé dans des chaînes), injection de commandes (ne transmettez jamais les données saisies par l’utilisateur à des commandes système) et traversée de chemins (normalisez et validez les chemins de fichiers).
import re
from pathlib import Path
BASE_DATA_DIR = Path('/data/mcp-files')
def safe_file_path(user_input: str) -> Path:
'''Validate and normalize a file path to prevent traversal attacks.'''
# Remove any path traversal sequences
clean = re.sub(r'\.\./', '', user_input)
clean = re.sub(r'\.\.\\\\', '', clean)
path = (BASE_DATA_DIR / clean).resolve()
# Ensure the resolved path is still within the allowed base directory
if not str(path).startswith(str(BASE_DATA_DIR)):
raise ValueError(f'Path traversal detected: {user_input}')
return path
def safe_identifier(value: str) -> str:
'''Validate a database identifier (table/column name).'''
if not re.match(r'^[a-z_][a-z0-9_]{0,63}$', value, re.IGNORECASE):
raise ValueError(f'Invalid identifier: {value}')
return valueLimiter le débit des appels d’outils
Un agent LLM exécuté en boucle pourrait appeler des outils coûteux des centaines de fois par minute, épuisant vos connexions à la base de données, les quotas d’API tierces ou votre budget de calcul. Implémentez des limites de débit par utilisateur à l’aide d’un algorithme de seau à jetons dans Redis. Rejetez les appels d’outils qui dépassent la limite avec une erreur explicite afin que l’agent sache qu’il doit patienter.
import redis
import time
r = redis.Redis.from_url('redis://localhost:6379')
def check_rate_limit(user_id: str, tool_name: str, limit: int = 60, window: int = 60) -> None:
'''Allow at most `limit` calls per `window` seconds per user per tool.'''
key = f'rate:{user_id}:{tool_name}'
pipe = r.pipeline()
pipe.incr(key)
pipe.expire(key, window)
count, _ = pipe.execute()
if count > limit:
retry_after = r.ttl(key)
raise ValueError(
f'Rate limit exceeded for {tool_name}. '
f'Limit: {limit} calls/{window}s. '
f'Retry after {retry_after} seconds.'
)Principe du moindre privilège
Appliquez le principe du moindre privilège à chaque couche de votre serveur MCP. L’utilisateur de la base de données doit disposer d’un accès SELECT uniquement aux tables nécessaires au serveur. Le processus du serveur doit s’exécuter avec un utilisateur OS qui n’est pas root. Les outils ne doivent demander que les autorisations dont ils ont besoin. Les clés d’API doivent disposer de la portée minimale nécessaire à leur usage. Chaque autorisation que vous refusez constitue une attaque potentielle qui ne pourra pas aboutir.
-- PostgreSQL: Create a dedicated read-only database user for your MCP server
CREATE ROLE mcp_reader LOGIN PASSWORD 'strong_random_password';
-- Grant SELECT on only the tables the server needs
GRANT SELECT ON products, categories, public_content TO mcp_reader;
-- Explicitly deny access to sensitive tables
REVOKE ALL ON users, api_keys, payment_methods FROM mcp_reader;
-- Never grant: INSERT, UPDATE, DELETE, TRUNCATE, or DDL permissionsTLS et sécurité du transport
Les serveurs MCP distants doivent utiliser TLS pour protéger les données en transit. Configurez votre serveur pour qu’il n’accepte que les connexions HTTPS. En production, utilisez un proxy inverse (nginx, Caddy) pour gérer la terminaison TLS et maintenir les certificats à jour grâce à un renouvellement automatique (Let’s Encrypt via Certbot ou la prise en charge ACME intégrée de Caddy).
# Example Caddyfile for TLS-terminating MCP server at a subdomain:
#
# mcp.yourcompany.com {
# reverse_proxy localhost:8080
# encode gzip
# tls internal # Use Let's Encrypt in production
# header {
# Strict-Transport-Security 'max-age=31536000; includeSubDomains'
# X-Content-Type-Options nosniff
# X-Frame-Options DENY
# }
# }Injection de prompt via les ressources MCP
Il existe un vecteur d’attaque subtil : si votre serveur MCP lit du contenu provenant de sources externes (pages Web, fichiers importés par les utilisateurs, bases de données non fiables) et le renvoie comme résultat d’outil, un attaquant pourrait intégrer des instructions malveillantes dans ce contenu. Le modèle pourrait suivre des instructions dissimulées dans les données récupérées — il s’agit d’une injection indirecte de prompt. Assainissez le contenu récupéré et ne renvoyez jamais directement du texte brut non fiable comme sortie d’un outil.
import re
def sanitize_for_mcp_output(text: str) -> str:
'''Remove patterns that look like instructions to the LLM.'''
# Remove common injection patterns
dangerous_patterns = [
r'ignore previous instructions',
r'ignore all prior instructions',
r'system:',
r'<\|.*?\|>', # Special tokens
r'\[INST\]',
r'<s>',
]
for pattern in dangerous_patterns:
text = re.sub(pattern, '[FILTERED]', text, flags=re.IGNORECASE)
return text[:10000] # Also cap length to prevent context stuffingAudit et surveillance de la sécurité
Consignez tous les événements pertinents pour la sécurité : les authentifications réussies et échouées, les violations de limitation de débit, les refus d'autorisation, les erreurs de validation et les schémas d'accès inhabituels. Configurez des alertes pour : plusieurs tentatives d'authentification échouées (force brute), un même utilisateur appelant rapidement des outils destructeurs et tout appel d'outil contenant des entrées extrêmement volumineuses. Consultez régulièrement les journaux d'audit et automatisez la détection des anomalies.
Vérification rapide
Testez votre compréhension des concepts de sécurité et d'authentification de MCP.
Récapitulatif de la leçon
Dans cette leçon, vous avez appris que : les serveurs MCP distants nécessitent une authentification OAuth 2.0 ou par clé API pour chaque requête, l'autorisation fondée sur les portées détermine quels outils chaque utilisateur authentifié peut appeler et toutes les entrées des outils doivent être validées afin de prévenir les attaques par injection et la traversée de chemins. Ce module MCP est terminé — nous allons maintenant explorer des stratégies avancées de segmentation pour une récupération RAG de haute précision.
Apprends Python avec un tuteur IA — gratuit
Écris et exécute du vrai code dans ton navigateur, obtiens de l'aide instantanée d'un tuteur IA disponible 24h/24, et reprends là où tu t'es arrêté sur le web ou dans l'app.
- Cours
- 30
- Leçons
- 120
Questions Fréquemment Posées
La leçon « Sécurité et authentification de MCP » est-elle gratuite ?
Oui — le texte complet de « Sécurité et authentification de MCP » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours AI Engineering Academy, passe à CoddyKit PRO. Le cours AI Engineering Academy comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Sécurité et authentification de MCP » ?
Ajoutez l’authentification à votre serveur MCP à l’aide de jetons OAuth 2.0, mettez en place la validation des entrées pour empêcher les attaques par injection et appliquez le principe du moindre pri… Tu pratiques AI Engineering Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer AI Engineering Academy ?
Aucune expérience préalable n'est requise. AI Engineering Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 4 sur 4.
Combien de temps prend la leçon « Sécurité et authentification de MCP » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon AI Engineering Academy ?
Oui. Chaque leçon AI Engineering Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Qu’est-ce que MCP et pourquoi est-ce important
- Créer votre premier serveur MCP
- Exposer des ressources de base de données via MCP
- Sécurité et authentification de MCP