IAM & Identité

Authentification d'API : les bases en 2026

Authentification d'API en 2026 : panorama 7 mécanismes (API keys, JWT, OAuth, OIDC, mTLS, HMAC, SAML), critères de choix, patterns d'implémentation pratiques.

Naim Aouaichia
17 min de lecture
  • Authentification
  • API
  • OAuth
  • JWT
  • mTLS
  • HMAC
  • API Keys
  • SAML

L'authentification d'API est le mécanisme par lequel le serveur vérifie l'identité du caller (humain ou machine) avant de traiter une requête. En 2026, sept mécanismes coexistent dans l'écosystème API selon le contexte d'usage : API Keys (le plus simple), HTTP Basic Auth (legacy), JWT (JSON Web Tokens, stateless dominant), OAuth 2.0 et OIDC (standard utilisateur fédéré), mTLS (cryptographique fort), HMAC signatures (webhooks et machine-to-machine léger), SAML 2.0 (legacy enterprise SSO). Chaque mécanisme a ses cas d'usage, ses forces et ses limites : aucun n'est universellement supérieur. Le choix dépend du type de client (humain vs machine), du niveau de sensibilité, des contraintes opérationnelles (gestion certificats, rotation), et de l'écosystème existant. Cet article cartographie les 7 mécanismes principaux avec patterns d'implémentation, critères de choix par cas d'usage, comparatif synthétique, et pièges fréquents observés. Les standards référencés sont les RFCs IETF (RFC 6749 OAuth 2.0, RFC 7519 JWT, RFC 8705 mTLS) et les spécifications OpenID Foundation (OpenID Connect Core 1.0, FAPI 2.0).

Authentification vs autorisation : la clarification fondamentale

Confusion source de nombreuses vulnérabilités. Distinction non négociable.

ConceptQuestion répondueMécanismesOutputs
Authentification (authn)Qui es-tu ?API key, JWT, OAuth, mTLS, HMAC, SAMLIdentité prouvée (user ID, claims)
Autorisation (authz)As-tu le droit ?RBAC, ABAC, ReBAC, scopes, ACLDécision permit/deny

Une API correctement sécurisée vérifie systématiquement les deux à chaque requête :

# Pattern correct
@app.get("/api/orders/{order_id}")
def get_order(
    order_id: int,
    current_user: User = Depends(authenticate),  # AUTHN : qui es-tu ?
):
    order = db.query(Order).filter(Order.id == order_id).first()
    if not order:
        raise HTTPException(404)
    
    # AUTHZ : as-tu le droit sur cet objet précis ?
    if order.owner_id != current_user.id and "admin" not in current_user.roles:
        raise HTTPException(403)
    
    return order

Confondre les deux mène aux vulnérabilités BOLA (Broken Object Level Authorization, API1:2023 OWASP), BFLA (API5:2023), BOPLA (API3:2023) qui dominent les incidents API documentés en 2024-2026.

Mécanisme 1 — API Keys

Le mécanisme le plus simple. Une chaîne secrète partagée entre le client et le serveur, transmise dans chaque requête.

Pattern d'implémentation

# Header standard (recommandé)
GET /api/v1/products HTTP/1.1
Host: api.example.test
X-API-Key: sk_live_4eC39HqLyjWDarjtT1zdp7dc
 
# Alternative : query parameter (déconseillé : apparaît dans logs URL)
GET /api/v1/products?api_key=sk_live_4eC39HqLyjWDarjtT1zdp7dc HTTP/1.1

Validation côté serveur

from fastapi import FastAPI, Header, HTTPException
import hashlib
import secrets
 
app = FastAPI()
 
# API keys stockées hashées en base (jamais en clair)
API_KEYS_DB = {
    "sha256_hash_de_la_cle_1": {"client_id": "partner_a", "rate_limit": 1000},
    "sha256_hash_de_la_cle_2": {"client_id": "partner_b", "rate_limit": 100},
}
 
def verify_api_key(x_api_key: str = Header(...)):
    if not x_api_key:
        raise HTTPException(401, "Missing API key")
    
    key_hash = hashlib.sha256(x_api_key.encode()).hexdigest()
    if key_hash not in API_KEYS_DB:
        raise HTTPException(401, "Invalid API key")
    
    return API_KEYS_DB[key_hash]
 
@app.get("/api/v1/products")
def list_products(client = Depends(verify_api_key)):
    return {"client_id": client["client_id"], "products": [...]}

Quand utiliser

  • APIs internes faible criticité avec rotation régulière (90 jours).
  • Tier gratuit / démo APIs publiques (avec rate limiting strict).
  • Identification de partenaires B2B sans authentification utilisateur fine.
  • Intégrations webhook simples.

Quand éviter

  • Authentification utilisateur (préférer OAuth + JWT).
  • Accès données sensibles (préférer JWT scoped + courte expiration).
  • Production critique (préférer mTLS).

Bonnes pratiques

  • Génération via PRNG cryptographique (secrets.token_urlsafe(32) Python, crypto.randomBytes(32) Node).
  • Stockage hashé côté serveur (SHA-256 minimum, idéalement Argon2).
  • Préfixe identifiant le tier ou type (sk_live_ pour Stripe production, sk_test_ pour test).
  • Rotation programmée (90 jours typique).
  • Détection de fuite (scan secrets dans repos Git, monitoring usage anormal).

Mécanisme 2 — HTTP Basic Authentication (legacy)

Standardisé dans RFC 7617. Username:password encodés en Base64 dans le header.

GET /api/v1/products HTTP/1.1
Host: api.example.test
Authorization: Basic dXNlcjpwYXNzd29yZA==

Décode dXNlcjpwYXNzd29yZA== = user:password.

Quand utiliser

Quasi jamais en API moderne. Cas restants :

  • Compatibilité avec outils legacy.
  • Pré-prod / debug avec credentials non productifs.
  • HTTP Basic combiné à TLS et IP allowlist pour services internes simples.

Pourquoi éviter

  • Credentials transmis en clair (juste Base64-encodé) à chaque requête.
  • Pas d'expiration ni de scope.
  • Username/password en clair côté client.
  • Aucune protection contre replay si TLS cassé.

Toute API moderne devrait utiliser JWT, OAuth ou API key plutôt que Basic Auth. Si Basic obligatoire pour compatibility, exiger TLS 1.3 + IP allowlist + rotation password trimestrielle.

Mécanisme 3 — JWT (JSON Web Tokens)

Standard RFC 7519. Format de token stateless dominant en 2026 pour API authentication.

Structure

Trois parties séparées par des points : <header>.<payload>.<signature>.

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImtleS0yMDI2In0
.
eyJzdWIiOiJ1c2VyXzEyMyIsImVtYWlsIjoidXNlckBleGFtcGxlLnRlc3QiLCJyb2xlcyI6WyJ1c2VyIl0sImlhdCI6MTcxNDExODQwMCwiZXhwIjoxNzE0MTIyMDAwLCJpc3MiOiJodHRwczovL2lkcC5leGFtcGxlLnRlc3QiLCJhdWQiOiJhcGkuZXhhbXBsZS50ZXN0In0
.
RS256_signature_base64url

Header décodé :

{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "key-2026"
}

Payload décodé (claims) :

{
  "sub": "user_123",
  "email": "user@example.test",
  "roles": ["user"],
  "iat": 1714118400,
  "exp": 1714122000,
  "iss": "https://idp.example.test",
  "aud": "api.example.test"
}

Signature : RS256 du header.payload concaténé avec la clé privée RSA du IdP.

Validation côté API

import jwt
from jwt import PyJWKClient
 
# Récupération des clés publiques via JWKS endpoint (RFC 7517)
jwks_client = PyJWKClient("https://idp.example.test/.well-known/jwks.json")
 
def verify_jwt(token: str) -> dict:
    try:
        # Récupère la clé publique correspondant au kid du header
        signing_key = jwks_client.get_signing_key_from_jwt(token)
        
        # Décode et valide
        payload = jwt.decode(
            token,
            signing_key.key,
            algorithms=["RS256"],  # CRUCIAL : whitelist explicite
            issuer="https://idp.example.test",
            audience="api.example.test",
            options={
                "verify_signature": True,
                "verify_exp": True,
                "verify_iat": True,
                "verify_iss": True,
                "verify_aud": True,
                "require": ["exp", "iat", "iss", "aud", "sub"],
            }
        )
        return payload
    except jwt.ExpiredSignatureError:
        raise HTTPException(401, "Token expired")
    except jwt.InvalidTokenError as e:
        raise HTTPException(401, f"Invalid token: {e}")

Pièges JWT critiques

PiègeProblèmeDéfense
Confiance dans alg du headerAttaquant peut envoyer alg:none ou faire algorithm confusionWhitelist algorithms côté serveur
Pas de validation audienceToken volé d'une autre app peut être réutiliséVérifier aud matche l'API
Pas de validation issuerToken forgé peut être acceptéVérifier iss matche l'IdP attendu
Données sensibles en payloadPayload est juste base64url, pas chiffréPas de password, secret, PII en payload
Expirations longuesToken compromis utilisable longtemps5 à 60 min pour access tokens
Pas de rotation des clésCompromission clé = perte sécuritéRotation annuelle minimum, JWKS endpoint

Quand utiliser JWT

  • API consommée par utilisateurs humains via applications web, mobile, SPA.
  • Microservices internes avec authentification stateless.
  • Federation cross-service avec OIDC.
  • Cas où la performance compte (validation crypto sans appel DB).

Quand éviter

  • Cas requérant révocation immédiate avant expiration sans tooling.
  • APIs avec très haute sensibilité où mTLS est plus approprié.

Mécanisme 4 — OAuth 2.0 et OpenID Connect

Pour utilisateurs humains et federation, OAuth 2.0 (RFC 6749) est le standard. OIDC (OpenID Connect) ajoute la couche d'authentification standardisée par-dessus OAuth.

En bref

  • OAuth 2.0 = framework d'autorisation. Permet à une app d'accéder à des ressources au nom d'un user.
  • OIDC = couche d'authentification au-dessus d'OAuth. Permet de prouver l'identité du user.
  • JWT = format de token souvent utilisé par OAuth/OIDC.

Flow le plus utilisé en 2026 : Authorization Code + PKCE

┌────────────┐                                ┌────────┐                    ┌──────┐
│ User Agent │                                │  IdP   │                    │ App  │
│ (Browser)  │                                │ (Auth0,│                    │ API  │
└────────────┘                                │ Okta,  │                    └──────┘
                                              │ Keycloak)
                                              └────────┘
       │   1. Click login app                      │                          │
       ├──────────────────────────────────────────────────────────────────────►
       │                                            │                          │
       │   2. Redirect to IdP authorize endpoint   │                          │
       │   (avec code_challenge PKCE)              │                          │
       ◄──────────────────────────────────────────────────────────────────────┤
       │                                            │                          │
       │   3. User authentifie + consent            │                          │
       ├───────────────────────────────────────────►│                          │
       │                                            │                          │
       │   4. Redirect avec authorization code      │                          │
       ◄───────────────────────────────────────────┤                          │
       │                                            │                          │
       │   5. Exchange code for tokens              │                          │
       │   (avec code_verifier PKCE)                │                          │
       ├──────────────────────────────────────────────────────────────────────►
       │                                            │                          │
       │   6. Access token + Refresh token + ID    │                          │
       │   token (OIDC)                             │                          │
       ◄──────────────────────────────────────────────────────────────────────┤
       │                                            │                          │
       │   7. API call with Bearer access token    │                          │
       ├──────────────────────────────────────────────────────────────────────►
       │                                            │                          │
       │   8. Validate JWT, return data             │                          │
       ◄──────────────────────────────────────────────────────────────────────┤

L'API ne participe pas au flow d'authentification : elle reçoit juste un access token (souvent JWT) qu'elle valide.

Client Credentials flow (machine-to-machine)

Pour authentification de service à service :

curl -X POST https://idp.example.test/oauth2/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=service-a" \
  -d "client_secret=<secret>" \
  -d "scope=read:orders write:orders"

Ce flow est détaillé en profondeur dans l'article dédié OAuth 2.0.

Mécanisme 5 — mTLS (Mutual TLS)

Standardisé RFC 8705 pour OAuth (OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens). Authentification cryptographique via certificats X.509 côté client ET serveur.

Principe

Le client et le serveur s'authentifient mutuellement pendant le handshake TLS via leurs certificats X.509 respectifs. L'authentification est liée au transport (couche 4-5), inaccessible aux scripts d'application.

Configuration côté serveur (Nginx exemple)

server {
    listen 443 ssl http2;
    server_name api.example.test;
    
    # Certificat serveur classique
    ssl_certificate /etc/nginx/ssl/server.crt;
    ssl_certificate_key /etc/nginx/ssl/server.key;
    
    # Configuration mTLS : exiger client cert
    ssl_client_certificate /etc/nginx/ssl/ca.crt;
    ssl_verify_client on;
    ssl_verify_depth 2;
    
    # Reverse proxy vers backend
    location / {
        proxy_pass http://backend:8080;
        # Transmettre les infos du cert client au backend
        proxy_set_header X-Client-Cert-DN $ssl_client_s_dn;
        proxy_set_header X-Client-Cert-Verify $ssl_client_verify;
        proxy_set_header X-Client-Cert-Fingerprint $ssl_client_fingerprint;
    }
}

Quand utiliser mTLS

  • Microservices internes (service mesh Istio, Linkerd avec auto-mTLS).
  • Partner B2B haute sensibilité (FAPI 2.0 banking, PSD2 open banking).
  • IoT devices avec identité forte requise.
  • Environnements zero-trust où l'authentification au niveau transport est obligatoire.

Compromis

AvantageInconvénient
Authentification cryptographique très forteComplexité opérationnelle (PKI à gérer)
Inaccessible aux scripts (couche transport)Rotation certificats lourde
Résiste au phishingPas adapté aux clients web/mobile end-users
Performant (handshake TLS standard)Difficile à debugger

Mécanisme 6 — HMAC signatures

Pattern dominant pour webhooks. Le sender signe le payload avec une clé secrète partagée.

Implémentation type Stripe

Côté sender (votre service qui envoie le webhook) :

import hmac
import hashlib
import time
import json
 
WEBHOOK_SECRET = "whsec_4eC39HqLyjWDarjtT1zdp7dc"
 
def send_webhook(url: str, event: dict):
    payload = json.dumps(event)
    timestamp = int(time.time())
    
    # Signature : HMAC-SHA256 de "timestamp.payload"
    signed_payload = f"{timestamp}.{payload}"
    signature = hmac.new(
        WEBHOOK_SECRET.encode(),
        signed_payload.encode(),
        hashlib.sha256
    ).hexdigest()
    
    headers = {
        "Content-Type": "application/json",
        "X-Signature-Timestamp": str(timestamp),
        "X-Signature": f"sha256={signature}",
    }
    
    requests.post(url, data=payload, headers=headers)

Côté receiver (le partenaire qui reçoit le webhook) :

def verify_webhook(request, secret: str, max_age: int = 300):
    timestamp = request.headers.get("X-Signature-Timestamp")
    signature_header = request.headers.get("X-Signature")
    
    if not timestamp or not signature_header:
        raise HTTPException(401, "Missing signature headers")
    
    # Anti-replay : refuser les anciens timestamps (> 5 min)
    if abs(time.time() - int(timestamp)) > max_age:
        raise HTTPException(401, "Timestamp too old")
    
    # Reconstruction signature attendue
    payload = request.body.decode()
    signed_payload = f"{timestamp}.{payload}"
    expected_signature = hmac.new(
        secret.encode(),
        signed_payload.encode(),
        hashlib.sha256
    ).hexdigest()
    
    # Comparaison constant-time pour éviter timing attacks
    received_signature = signature_header.replace("sha256=", "")
    if not hmac.compare_digest(expected_signature, received_signature):
        raise HTTPException(401, "Invalid signature")
    
    return json.loads(payload)

Bonnes pratiques HMAC

  • Toujours inclure un timestamp dans le payload signé (anti-replay).
  • Refuser les timestamps trop anciens (5 minutes max).
  • Comparer les signatures en constant-time (hmac.compare_digest) pour éviter les timing attacks.
  • Clé secrète unique par tenant ou par webhook endpoint, rotable indépendamment.
  • SHA-256 minimum (jamais SHA-1).

Patterns observés

  • Stripe : Stripe-Signature header avec HMAC-SHA256 + timestamp.
  • GitHub : X-Hub-Signature-256 header avec HMAC-SHA256.
  • Slack : X-Slack-Signature avec HMAC-SHA256 + timestamp.
  • Twilio : X-Twilio-Signature avec HMAC-SHA1 (legacy, idéalement migration vers SHA-256).

Mécanisme 7 — SAML 2.0 (legacy enterprise)

Standard OASIS 2005. Format XML pour SSO enterprise. Toujours massivement déployé en 2026 dans les contextes corporate legacy.

Cas d'usage 2026

  • SSO enterprise vers applications web (Salesforce, SAP, Microsoft 365, applications internes anciennes).
  • Federation B2B traditionnelle entre grandes entreprises.
  • Compliance dans certains secteurs réglementés qui imposent SAML.

Pourquoi SAML pour API moderne est rare

  • Format XML lourd et verbeux comparé à JWT.
  • Complexité d'implémentation (signatures XML, encryption, assertions).
  • Mauvaise adaptation aux clients mobiles et SPA (redirections POST complexes).
  • OIDC (qui est conceptuellement le successeur SAML pour le mobile/web moderne) plus adapté.

Quand encore utiliser SAML

  • Intégration enterprise legacy où le service distant ne supporte que SAML.
  • Migration progressive SAML vers OIDC (coexistence transitoire).

Pour tout nouveau projet API en 2026, OIDC est préféré à SAML.

Comparaison synthétique : quand utiliser quoi

Tableau de décision rapide.

MécanismeCas d'usage idéalForceLimite
API KeysAPIs internes, partenaires simples, démos publiquesSimplicité maximalePas de scopes ni d'expiration intrinsèque
HTTP BasicPré-prod, debug, cas legacy avec TLS + IP allowlistStandard universelCredentials transmis à chaque requête
JWTAPI utilisateur via SPA/mobile, microservices, OAuth backendsStateless, scopes, expirationsRévocation pré-expiration complexe
OAuth 2.0 + OIDCAuthentification utilisateur fédérée standardStandard universel, fédérationComplexité d'implémentation
mTLSMicroservices service mesh, B2B FAPI, IoTCryptographique fortPKI à gérer
HMACWebhooks, machine-to-machine légerSimple, intégrité prouvéePas de fédération identité
SAML 2.0SSO enterprise legacy, federation B2B traditionnelleMaturité enterpriseLourd, mal adapté mobile/SPA

Décision par scénario

API publique avec utilisateurs humains via SPA / mobile : OAuth 2.0 Authorization Code + PKCE → JWT pour l'API.

API B2B avec partenaires entreprises : OAuth 2.0 Client Credentials → JWT pour l'API. Optionnellement mTLS si haute sensibilité.

Microservices internes : mTLS via service mesh (Istio, Linkerd) + JWT applicatifs si scopes fins requis.

Webhooks vers partenaires : HMAC SHA-256 avec timestamp anti-replay.

API publique simple (tier gratuit, démo, partenaire identification) : API key avec rate limiting et rotation.

Intégration enterprise SSO legacy : SAML 2.0 si imposé par le partenaire, sinon OIDC.

Patterns d'implémentation pratiques

Cinq patterns récurrents en production 2026.

Pattern 1 — JWT avec refresh tokens

Pour SPA et mobile : access token JWT court (15 min) + refresh token long (7 jours). Renewal automatique transparent pour l'utilisateur.

// Renewal automatique en TS
async function callApi(url: string) {
  let accessToken = getStoredAccessToken();
  
  let response = await fetch(url, {
    headers: { Authorization: `Bearer ${accessToken}` }
  });
  
  if (response.status === 401) {
    // Tentative de renewal
    accessToken = await refreshAccessToken();
    storeAccessToken(accessToken);
    
    // Retry
    response = await fetch(url, {
      headers: { Authorization: `Bearer ${accessToken}` }
    });
  }
  
  return response;
}
 
async function refreshAccessToken(): Promise<string> {
  const refreshToken = getStoredRefreshToken();
  const response = await fetch("/api/auth/refresh", {
    method: "POST",
    body: JSON.stringify({ refreshToken }),
  });
  const data = await response.json();
  return data.accessToken;
}

Pattern 2 — Token introspection pour révocation immédiate

Si la révocation immédiate avant expiration est requise (compte compromis, logout), pattern OAuth 2.0 Token Introspection (RFC 7662) :

# API valide chaque token via call à l'IdP au lieu de validation locale JWT
def verify_token_via_introspection(token: str):
    response = requests.post(
        "https://idp.example.test/oauth2/introspect",
        data={"token": token},
        auth=(API_CLIENT_ID, API_CLIENT_SECRET),
    )
    introspection = response.json()
    if not introspection.get("active"):
        raise HTTPException(401, "Token revoked or invalid")
    return introspection

Trade-off : performance (call HTTP par requête) vs révocation immédiate. Compromis usuel : validation JWT locale + cache Redis avec TTL court (1-5 min) + denylist de tokens révoqués.

Pattern 3 — JWT avec scopes pour autorisation

Le payload JWT inclut des scopes qui définissent les permissions :

{
  "sub": "user_123",
  "scope": "read:orders write:orders read:profile",
  "iat": 1714118400,
  "exp": 1714122000
}

Côté API :

def require_scope(*required_scopes):
    def decorator(func):
        @wraps(func)
        async def wrapper(*args, **kwargs):
            token = extract_token()
            payload = verify_jwt(token)
            granted_scopes = set(payload.get("scope", "").split())
            
            for scope in required_scopes:
                if scope not in granted_scopes:
                    raise HTTPException(403, f"Missing scope: {scope}")
            
            return await func(*args, **kwargs)
        return wrapper
    return decorator
 
@app.delete("/api/orders/{order_id}")
@require_scope("write:orders")
async def cancel_order(order_id: int):
    pass

Pattern 4 — Service mesh mTLS automatique

Pour microservices interne sur Kubernetes avec Istio :

# Istio : enforce mTLS strict sur tout le namespace
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default
  namespace: production
spec:
  mtls:
    mode: STRICT

Avec cette policy, tout le trafic entre Pods est automatiquement mTLS, sans modification de code applicatif. Istio gère la PKI interne via ses certificate manager (auto-rotation, distribution sidecars).

Pattern 5 — API gateway centralise l'authentification

L'API gateway (Kong, Apigee, AWS API Gateway, Azure API Management) valide les tokens à l'edge, transmet l'identité au backend via headers signés :

Client → API Gateway → Backend Service
 
API Gateway :
1. Valide JWT (signature, expiration, audience)
2. Extrait user_id depuis sub claim
3. Transmet vers backend :
   - X-User-ID: user_123
   - X-User-Roles: user,manager
   - X-User-Email: user@example.test

Backend service fait confiance aux headers (signés ou via réseau privé). Avantage : validation centralisée, backend simplifié. Risque : si backend exposé en parallèle de la gateway, headers spoofables. Toujours bind backend privé.

Pièges fréquents

Cinq erreurs récurrentes observées dans les implémentations 2024-2026.

Algorithm confusion sur JWT. Acceptation de plusieurs algorithmes de signature, l'attaquant peut forcer un algorithme faible (HS256 au lieu de RS256) et utiliser la clé publique comme HMAC secret. Solution : whitelist algorithm strict côté validation.

JWT en query string. Token apparaît dans les logs serveur, proxy logs, navigateur history. Solution : toujours en header Authorization: Bearer ....

Pas de rotation de clés JWT. Compromission de la clé privée IdP = perte de sécurité tant que pas de rotation. Solution : JWKS endpoint avec rotation au moins annuelle, idéalement automatique.

API keys en clair dans le code source. Commit accidentel dans Git, exposition publique. Solution : secrets scanning (gitleaks) en pre-commit + CI, vault pour stockage prod.

HMAC sans timestamp anti-replay. Webhook capturé peut être rejoué indéfiniment. Solution : timestamp obligatoire dans payload signé, refus si trop ancien.

Points clés à retenir

  • L'authentification d'API en 2026 dispose de 7 mécanismes principaux : API Keys (simple), HTTP Basic (legacy), JWT (stateless dominant), OAuth 2.0 + OIDC (utilisateur fédéré), mTLS (cryptographique fort), HMAC (webhooks), SAML 2.0 (legacy enterprise).
  • Authentification (qui es-tu) et autorisation (as-tu le droit) sont distincts. Une API correctement sécurisée vérifie systématiquement les deux à chaque requête. Confondre = vulnérabilités BOLA, BFLA, BOPLA.
  • JWT est le format dominant 2026 pour API utilisateurs. Pièges critiques : whitelist algorithm, validation aud/iss, expirations courtes, rotation des clés via JWKS.
  • mTLS pour microservices internes (service mesh Istio/Linkerd auto-mTLS) et B2B haute sensibilité (FAPI 2.0). HMAC SHA-256 pour webhooks. OAuth 2.0 Client Credentials pour machine-to-machine partner.
  • API gateway centralise validation tokens à l'edge et simplifie le backend. Mais ne dispense pas des défenses applicatives (autorisation, BOLA, business logic).

Pour aller plus loin

Questions fréquentes

  • Quelle différence entre authentification et autorisation ?
    L'authentification (authn) prouve l'identité du caller : qui es-tu ? Elle répond avec un token, une session, une preuve cryptographique. L'autorisation (authz) détermine ce que le caller a le droit de faire : as-tu le droit d'accéder à cette ressource, exécuter cette action ? Une API correctement sécurisée vérifie systématiquement les deux à chaque requête. Confondre les deux est la source de nombreux bugs : authentifier un utilisateur ne signifie pas qu'il a le droit d'accéder à toutes les ressources. Les vulnérabilités BOLA, BFLA, BOPLA documentées dans OWASP API Top 10 2023 sont toutes des défauts d'autorisation post-authentification.
  • API key ou JWT pour mon API B2B ?
    JWT pour la majorité des cas en 2026. API key reste pertinent pour : APIs internes faible criticité avec rotation régulière, tier gratuit/démo APIs publiques (avec rate limiting strict), identification de partenaires sans authentification utilisateur. JWT permet : claims structurés (user ID, roles, scopes, expiration), validation cryptographique sans appel base de données, expirations courtes obligatoires. Pour API B2B avec partenaires multiples, JWT signé par OAuth 2.0 Client Credentials flow est le pattern standard moderne. Pour API critique haute valeur, mTLS en complément ou substitution.
  • JWT stateless est-il sûr en production ?
    Oui à condition de respecter quelques règles. Premier : valider la signature côté serveur avec algorithme whitelisté (jamais de confiance dans le header alg envoyé par le client, jamais d'acceptation de alg:none). Deuxième : expirations courtes (5 à 60 minutes pour access tokens). Troisième : rotation des clés de signature (au moins annuelle, idéalement automatique via JWKS endpoint). Quatrième : pas de données sensibles dans le payload (le JWT n'est pas chiffré, seulement signé : tout le payload est lisible en base64). Pour révocation immédiate avant expiration, utiliser un mécanisme externe (denylist en cache Redis, ou pattern token introspection avec OAuth).
  • Quand utiliser mTLS plutôt que JWT pour API ?
    mTLS est préférable pour : authentification machine-to-machine entre services internes (microservices service mesh), partner B2B haute sensibilité (FAPI 2.0 banking, PSD2 open banking), IoT devices avec identité forte, environnements zero-trust où l'authentification au niveau transport est requise. JWT reste préférable pour : utilisateurs humains via applications web/mobile, APIs publiques accessibles depuis multiples clients sans gestion certificats, intégrations partner standard sans exigence cryptographique forte. La complexité opérationnelle de mTLS (gestion certificats, rotation, PKI interne) le rend pertinent uniquement quand son niveau de sécurité supérieur est requis.
  • HMAC ou JWT pour les webhooks ?
    HMAC est le pattern standard 2026 pour les webhooks. Le sender (votre service) signe le payload du webhook avec une clé secrète partagée, le receiver (le partenaire) vérifie la signature avant de traiter. Avantages : preuve d'intégrité du payload (pas modifié en transit), preuve d'origine (sender légitime), simplicité d'implémentation. Stripe, GitHub, Slack utilisent tous HMAC SHA-256 pour leurs webhooks. JWT serait sur-engineered pour ce cas d'usage simple. Toujours inclure un timestamp + nonce dans le payload pour empêcher le replay. La clé HMAC doit être unique par tenant et rotable indépendamment.
  • Faut-il encore connaître SAML 2.0 en 2026 ?
    Oui pour les contextes enterprise legacy, mais pas pour les nouveaux développements API. SAML 2.0 reste massivement déployé pour le SSO enterprise vers applications web (Salesforce, SAP, Microsoft 365, applications internes anciennes). Pour les APIs modernes, OIDC remplace SAML : plus léger (JSON vs XML), plus simple à implémenter, mieux adapté aux clients mobiles et SPA. Migration SAML vers OIDC en cours dans la plupart des organisations 2026 mais lente (5 à 10 ans). Pour un développeur d'API B2B 2026, comprendre les bases SAML est utile pour les intégrations enterprise legacy mais nouveaux projets en OIDC exclusivement.

Écrit par

Naim Aouaichia

Expert cybersécurité et fondateur de Zeroday Cyber Academy

Expert cybersécurité avec un master spécialisé et un parcours hybride : développement, DevOps, DevSecOps, SOC, GRC. Fondateur de Hash24Security et Zeroday Cyber Academy. Formateur et créateur de contenu technique sur la cybersécurité appliquée, la sécurité des LLM et le DevSecOps.