Table des matières :
- Pourquoi l’authentification Strapi 5 n’est pas “juste un login”
- JWT dans Strapi 5 : mécanique, risques, durcissement (sans magie noire)
- OAuth 2.0 / OIDC avec Strapi 5 : déléguer l’identité sans déléguer le cerveau
- API tokens Strapi 5 : le M2M propre, pas le “token de prod collé dans Postman”
- Patterns d’architecture : Strapi 5 dans le monde réel (proxy, gateway, Zero Trust)
- DevSecOps et observabilité : sécuriser l’auth, c’est aussi la surveiller
- Check-list pragmatique : JWT, OAuth et API tokens Strapi 5 en production
Pourquoi l’authentification Strapi 5 n’est pas “juste un login”
Strapi 5 est souvent posé au milieu d’architectures headless où tout devient API : front Next/Nuxt, apps mobiles, back-office, connecteurs ERP/CRM, webhooks, jobs serverless… Donc l’authentification n’est plus un bouton « se connecter » ; c’est une surface d’attaque et un contrat d’API à maintenir. Et si votre stratégie se résume à “un JWT et roule ma poule”, vous n’êtes pas en train de sécuriser : vous êtes en train de distribuer des passe-partout.
Dans Strapi, il faut distinguer trois mondes : 1) Auth “Content API” (plugin Users & Permissions) pour vos utilisateurs applicatifs (clients, partenaires, etc.). 2) OAuth/OIDC quand vous déléguez l’identité à un IdP (Google, Azure AD, Keycloak…). 3) API tokens (machine-to-machine) quand un service appelle l’API sans utilisateur humain derrière.
Ce découpage évite un piège courant : utiliser le même mécanisme pour des menaces différentes. Un utilisateur final s’expose à du phishing et au vol de session ; un connecteur M2M s’expose surtout à la fuite de secrets (CI mal configurée, logs, dépôt Git, poste admin), et à des permissions trop larges.
Et oui, l’autorisation (qui a le droit de faire quoi) est aussi importante que l’authentification (qui est-ce). Pour un rappel très “terrain”, gardez sous le coude votre article maison : Sécurité des API : authentification, autorisations et logique métier. Spoiler : une grosse partie des incidents vient de permissions mal modélisées, pas d’un algorithme de signature exotique.
Un test simple à faire en équipe (et qui révèle souvent des surprises) : listez vos endpoints Strapi et répondez “qui peut appeler ça ?” pour chacun.
POST /api/auth/local: qui, depuis où, avec quel rate-limit ?GET /api/<collection>: public ? authentifié ? filtrage serveur obligatoire ?POST/PUT/DELETE: quels rôles Strapi, quelles policies, quels contrôles métier ?
Si vous n’avez pas de réponse précise, vous n’avez pas un “problème Strapi”, vous avez un problème de modèle d’accès.
JWT dans Strapi 5 : mécanique, risques, durcissement (sans magie noire)
Un JWT n’est pas un sésame “crypté” (non, vraiment). C’est une enveloppe signée qui transporte des claims (identité, rôle, expiration…). La définition la plus propre reste celle du standard : “JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties.” — RFC 7519. En clair : si ça fuit, c’est exploitable. Et en HTTP, les fuites sont une tradition (logs, referers, proxies, erreurs de config, extensions navigateur…).
Côté Strapi 5 (Users & Permissions), le parcours classique ressemble à :
POST /api/auth/local(email/username + password)- réponse avec un
jwt+ l’objetuser - puis
Authorization: Bearer <jwt>sur les requêtes Content API
Risque très concret (mini-scenario)
Vous activez un niveau de logs “debug” sur un reverse-proxy pendant un incident, ou vous faites transiter les en-têtes vers un outil APM mal filtré. Résultat : l’en-tête Authorization se retrouve dans un log consultable par trop de monde (ou exporté dans un bucket). Comme un JWT est un bearer token, l’impact est immédiat : usurpation tant que le token est valide.
Le durcissement commence par les basics :
- TTL court (minutes/heures, pas “30 jours parce que c’est pratique”).
- Rotation : si vous implémentez des refresh tokens, faites de la rotation + révocation côté serveur (sinon vous venez d’inventer “session illimitée”).
- Claims
iss,aud,sub: évitez le token “valable partout pour toujours”. - Algorithmes : verrouillez l’algo côté validation (pas de “alg:none” surprise, même si c’est moins à la mode qu’en 2015).
Et puisqu’on parle de Bearer : “A bearer token is a security token with the property that any party in possession of the token (a ‘bearer’) can use the token in any way that any other party in possession of it can.” — RFC 6750. Traduction pour les pressés : un JWT volé = un compte compromis, point.
Stockage côté navigateur : choisissez vos compromis (et documentez-les)
Sur le stockage client, vous avez un dilemme classique :
- LocalStorage : facile, mais exposition élevée au XSS (et le XSS arrive toujours “chez les autres”… jusqu’au jour où).
- Cookie HttpOnly + SameSite : protège du XSS, mais introduit des enjeux CSRF (à traiter correctement) et des subtilités cross-domain.
Une grille pratique pour éviter les décisions “au feeling” :
| Option | Principal avantage | Principal risque | À prévoir absolument |
|---|---|---|---|
localStorage |
Implémentation simple, pas de CSRF | Vol de token via XSS | CSP stricte, audit XSS, pas de JWT long-lived |
Cookie HttpOnly |
Token non lisible en JS (réduit l’impact XSS) | CSRF + complexité cross-site | SameSite, jeton anti-CSRF, CORS propre, validation Origin/Referer selon contexte |
| Session via BFF | Réduit l’exposition du token au navigateur | Plus d’infra + complexité | Observabilité, scalabilité, rotation de session, rate-limit |
Si vous voulez un guide très concret sur les erreurs classiques JWT (validation, stockage, en-têtes, etc.), une ressource utile est l’OWASP Cheat Sheet : OWASP JSON Web Token Cheat Sheet (même si l’exemple est orienté Java, les pièges et principes sont transposables).
Pour une architecture e-commerce headless (front séparé), un pattern raisonnable consiste à introduire un BFF (Backend For Frontend) : le front ne parle pas directement à Strapi avec un JWT long-lived, il parle à votre BFF qui gère sessions/refresh, applique de la rate-limit, normalise les erreurs, et filtre les endpoints. Si vous êtes en plein découplage front/back, l’article Headless e-commerce : avantages, limites et critères de décision pose bien les impacts d’architecture (et oui, la sécurité en fait partie).
Enfin, un détail qui évite des sueurs froides : ne logguez jamais les tokens (ni en clair, ni “juste le temps du debug”). Si vous avez besoin de corréler, logguez un identifiant de session côté serveur, ou un hash irréversible du token (et encore, avec prudence).
OAuth 2.0 / OIDC avec Strapi 5 : déléguer l’identité sans déléguer le cerveau
OAuth 2.0 est un cadre d’autorisation, souvent couplé à OpenID Connect pour l’authentification. La phrase de référence (et non, ce n’est pas “un bouton Google”) : “The OAuth 2.0 authorization framework enables a third-party application to obtain limited access to an HTTP service…” — RFC 6749. En entreprise, la promesse est simple : SSO, MFA géré par l’IdP, politique de mot de passe centralisée, offboarding propre.
Dans Strapi, l’OAuth se configure via le plugin Users & Permissions avec des providers (Google, GitHub, Microsoft, etc.). Le flux typique : redirection vers l’IdP, retour sur un callback Strapi, création/liaison d’un user, puis émission d’un JWT Strapi.
C’est là que les ennuis commencent si vous ne cadrez pas :
- mapping email → user sans vérification de domaine (bonjour les collisions)
- absence de contrôle sur
state/anti-CSRF côté callback - redirections ouvertes (open redirect) si vous laissez passer n’importe quel
redirect_uri
Deux points qui cassent souvent en prod (et pas en démo)
- Account linking : si un utilisateur se connecte d’abord en
local(email + mot de passe), puis via Google avec le même email, que se passe-t-il ? Fusion ? Deux comptes ? Le choix doit être explicite, testé, et idéalement réversible (support). - Multi-tenant / B2B : sur Azure AD / Keycloak, vous pouvez avoir plusieurs “tenants”/realms. Sans garde-fous, vous acceptez potentiellement des identités “valides” mais hors de votre périmètre. Une règle simple : allowlist de domaines/tenants, et refus par défaut.
En 2026, le flux recommandé côté clients web est Authorization Code + PKCE (Implicit Flow : à laisser au musée, à côté des applets Java). Problème : beaucoup de stacks “CMS + front” ne gèrent pas PKCE de manière ergonomique out-of-the-box. Solution réaliste : un BFF qui fait le code exchange côté serveur et ne renvoie au navigateur qu’un cookie de session. Oui, c’est plus de boulot. Non, ce n’est pas optionnel si votre menace inclut XSS, extension navigateur, ou terminal partagé.
Dernier point souvent “oublié” : OAuth ne remplace pas votre modèle d’autorisation Strapi. Même avec un IdP béton, si votre rôle Strapi “Authenticated” a des permissions trop larges, vous venez de construire un SSO ultra efficace… pour se faire piller l’API. Si vous avez besoin d’un rappel sur la séparation authN/authZ et la logique métier, retournez lire l’article sur l’authentification vs autorisations côté API et la logique métier.
API tokens Strapi 5 : le M2M propre, pas le “token de prod collé dans Postman”
Les API tokens de Strapi servent aux appels machine-to-machine (CI/CD, import catalogues, jobs, connecteurs, scripts d’admin). L’idée : ne pas utiliser un compte utilisateur + JWT “humain” pour des automatisations. C’est plus traçable, plus facilement révocable, et compatible avec le principe du moindre privilège.
Dans Strapi 5, on retrouve généralement des niveaux de permission du type Full access, Read-only et Custom (permissions granulaires). Utilisez Custom dès que vous avez autre chose qu’un script d’extraction de contenu public. Exemple concret : un connecteur ERP ne devrait pas pouvoir modifier les rôles/permissions, ni écrire dans des collections qui touchent à la sécurité (utilisateurs, tokens, etc.). Ça paraît évident, donc c’est rarement fait.
Une convention simple qui aide vraiment (noms + périmètre)
Au lieu de “token-prod”, adoptez une convention qui encode l’usage :
m2m_catalog_import_prod_ro(lecture seule)m2m_erp_sync_prod_write_orders(écriture limitée à certaines collections)m2m_cicd_deploy_staging_custom(staging seulement)
Ce n’est pas cosmétique : le jour où vous devez révoquer en urgence, vous gagnez du temps et vous réduisez le risque de couper “le mauvais” token.
Côté exploitation, un API token se gère comme un secret de prod :
- Jamais dans le dépôt Git (même “temporairement”).
- Jamais en query string (logs + referers, combo gagnant).
- Rotation planifiée (mensuelle/trimestrielle selon criticité) + révocation immédiate si suspicion.
- Stockage dans un secret manager (Vault, AWS Secrets Manager, SOPS, etc.), injection via variables d’environnement.
Et surtout : cloisonnez par environnement (dev/staging/prod) et par usage. Un token “intégration” n’a rien à faire sur un poste développeur. Si vous devez industrialiser ça, le sujet dépasse Strapi : c’est du MCS/MCO, de la gouvernance des secrets, de la traçabilité. Vous pouvez relier cette démarche à une approche plus large de maintien en conditions de sécurité : MCO/MCS – Maintien en Conditions Opérationnelles / Maintien en Conditions de Sécurité.
Un bonus “facile” quand vous avez un proxy/gateway devant Strapi : limiter l’usage d’un token M2M par IP, par route, et par quota (ex. 60 req/min). Ce n’est pas une sécurité absolue, mais ça réduit l’exploitabilité d’une fuite et ça accélère la détection.
Patterns d’architecture : Strapi 5 dans le monde réel (proxy, gateway, Zero Trust)
Dans un SI moderne, Strapi n’est souvent qu’un composant derrière un reverse-proxy, un API gateway, un WAF, parfois un CDN. Et c’est très bien : on ne demande pas à un CMS headless d’être aussi un produit IAM, un SIEM et un pare-feu applicatif (sinon on finit avec une “plateforme” qui fait tout, sauf marcher). L’important est de décider où vivent : la validation JWT, la rate-limit, la gestion des refresh tokens, la détection d’anomalies, et la journalisation.
Un pattern robuste : API Gateway (authn préliminaire + rate-limit) → BFF (session/PKCE/refresh, normalisation) → Strapi (RBAC, règles métier, validation des permissions). Ça limite la pression sur Strapi, réduit l’exposition directe, et facilite l’observabilité. Si vous exposez Strapi directement sur Internet “parce que c’est une API REST donc c’est fait pour”, vous faites partie de la grande famille des gens qui apprennent la sécurité en prod.
- Ne jamais supposer le réseau interne “de confiance” : appliquez les mêmes contrôles (auth, quotas, logs) entre services, surtout si vous avez du Kubernetes, du serverless ou des environnements multi-cloud.
- Séparer les surfaces : admin panel Strapi (back-office) ≠ Content API ≠ endpoints webhook. Des noms de domaine différents, des règles WAF différentes, des logs différents.
Pour les webhooks (paiement, CRM, marketing), ne mélangez pas tout avec l’auth utilisateur. Utilisez des signatures HMAC, timestamps, replay protection, et validation stricte du schéma. La logique est la même que dans cet article : Webhooks HubSpot : authentification X-HubSpot-Signature et sécurité SHA-256. En pratique, un endpoint webhook Strapi devrait être isolé (route dédiée, policy dédiée, logs dédiés) et protégé contre le bruteforce et le replay.
Enfin, si vous opérez en contexte e-commerce, ne sous-estimez pas l’intérêt de méthodes de connexion résistantes au phishing côté front (passkeys, WebAuthn). Ce n’est pas Strapi qui gère ça directement, mais c’est un choix d’expérience et de risque. Votre lecture connexe : Passkeys e-commerce : réduire la friction de connexion et limiter le phishing.
DevSecOps et observabilité : sécuriser l’auth, c’est aussi la surveiller
L’authentification Strapi 5 “sécurisée” qui n’est pas monitorée, c’est comme un firewall sans logs : ça rassure surtout les PowerPoints. Mettez de la télémétrie sur : taux d’échec login, fréquence de refresh, géolocalisation atypique, bursts d’accès 401/403, endpoints sensibles, et latence des routes d’auth. Pour instrumenter proprement, une stack d’observabilité moderne s’appuie sur la corrélation logs/traces/métriques : OpenTelemetry : unifier métriques, traces et logs pour l’observabilité.
Quelques signaux d’alerte “pragmatiques” (à adapter à votre trafic) :
- pic de
401sur/api/auth/localsur 5–10 minutes (bruteforce ou credential stuffing) - hausse brutale des
403sur des endpoints “admin-like” (scan d’API, tentative d’escalade) - tokens valides utilisés depuis des ASNs/pays inattendus pour votre activité (attention : la géolocalisation est un indice, pas une preuve ; et côté RGPD, minimisez ce que vous conservez et justifiez l’usage sécurité)
- taux d’erreurs sur callback OAuth (mauvaise config
redirect_uri, attaque sur le flux, ou changement côté IdP)
Sur la CI/CD, automatisez ce qui peut l’être :
- SAST/Dependency scanning (Node, packages) + policy de mises à jour
- tests d’intégration sur endpoints d’auth (JWT invalid, expired, audience mismatch, etc.)
- tests de permissions (un rôle ne doit pas pouvoir “escalader”)
- rate-limit et protections anti-bruteforce au niveau proxy/gateway
Côté infra, l’auth dépend aussi de la qualité du durcissement : TLS correct, headers, patching, secrets, segmentation réseau. Si votre Strapi tourne sur une VM “config par défaut” avec un SSH ouvert au monde, vous avez d’autres priorités avant de débattre de aud vs iss. Deux lectures utiles : VPS Linux : guide de déploiement, durcissement et maintenance proactive et Hébergement informatique sécurisé : meilleures pratiques pour les professionnels.
Enfin, préparez l’incident. Oui, quand (pas “si”) un token fuite ou qu’un provider OAuth a une mauvaise configuration, il faut une procédure : révocation, rotation, invalidation de sessions, analyse des logs, communication, patch, post-mortem. Et si vous avez besoin d’une cellule d’intervention, gardez ce point d’entrée : Urgence cybersécurité.
Un point souvent sous-estimé : la répétabilité. Si la rotation d’un secret nécessite “Michel qui connaît le serveur”, ce n’est pas un process : c’est un risque.
Check-list pragmatique : JWT, OAuth et API tokens Strapi 5 en production
Côté JWT Strapi (utilisateurs), commencez par des choix “non négociables” : expiration courte, validation stricte des algorithmes, transport uniquement via HTTPS, et stratégie de stockage cohérente (cookie HttpOnly + anti-CSRF ou BFF). Ajoutez ensuite : révocation (blacklist/rotation), device binding (au moins logique via fingerprint léger ou session côté serveur), et protection contre le bruteforce. Oui, ça demande du code. Non, “Strapi ne le fait pas nativement” n’est pas une excuse : c’est une information.
Pour cadrer rapidement les décisions, une règle simple :
- JWT Strapi : bon pour utilisateur → API si TTL court + protections navigateur.
- OAuth/OIDC : bon pour SSO + MFA et gouvernance des identités.
- API tokens : bon pour service → API avec permissions minimales et rotation.
Côté OAuth/OIDC, privilégiez Authorization Code + PKCE, verrouillez redirect_uri, vérifiez state, et si possible utilisez OIDC (ID token signé) plutôt qu’un bricolage sur un simple profil récupéré via API. Le point clé : vous déléguez l’authentification, pas l’autorisation. Donc RBAC Strapi + policies métier restent obligatoires, et doivent être testés comme n’importe quelle logique critique.
Côté API tokens, appliquez une discipline DevOps : un token par usage, permissions minimales, rotation planifiée, stockage en secret manager, et observabilité (qui appelle quoi, quand, depuis où). Si vous voulez industrialiser l’ensemble (gateway, BFF, monitoring, durcissement, procédures), c’est typiquement le terrain d’une démarche d’audit et roadmap : Audit de site web : technique, SEO, UX et sécurité pour une roadmap — parce que oui, la sécurité d’auth impacte aussi l’UX, la perf et la conversion.
Si votre objectif est de sécuriser Strapi 5 dans une architecture e-commerce/marketing réelle (pas une démo), vous savez déjà que “mettre un JWT” est le début de la conversation, pas la fin. Et la bonne nouvelle, c’est qu’en faisant les choses proprement, vous gagnez en sécurité et en opérabilité — ce qui, dans la vraie vie, vaut plus qu’un énième débat théorique sur la taille idéale d’un token.