Dans un WordPress headless, le CMS n’est plus seulement un back-office : il devient une source de données consommée par un frontend, une application mobile, un outil métier ou des automatisations. Cette séparation peut améliorer la performance et la souplesse du projet, mais elle rend indispensable une gestion précise des accès à l’API REST.
Le bon objectif n’est pas de « cacher » /wp-json/. Il est de n’exposer que les données nécessaires, d’authentifier chaque client selon son usage et de vérifier les droits sur chaque action sensible. Ce guide propose une méthode pragmatique pour sécuriser une API WordPress REST en environnement headless.
Pourquoi l’API REST est un point sensible en headless
Dans une architecture classique, de nombreux échanges restent dans le périmètre de WordPress. En headless, le frontend et le CMS sont séparés, parfois sur des sous-domaines distincts. L’API devient alors l’interface entre les contenus, les comptes, les commandes ou les outils tiers.
Cette exposition ne constitue pas un défaut en soi. Elle appelle toutefois un modèle de sécurité explicite : qui peut lire quelle donnée, qui peut modifier quel objet, depuis quel contexte et avec quel secret ? C’est particulièrement important pour une boutique, un espace client ou un back-office métier.
Pour les fondations d’une telle architecture, consultez aussi notre article sur Astro et WordPress headless et notre analyse des gains réels sur les Core Web Vitals.
Commencer par une cartographie des données et des clients
Avant de modifier les en-têtes CORS ou d’ajouter un plugin d’authentification, listez les routes réellement utiles. Une API sûre est d’abord une API dont le périmètre est connu. L’OWASP classe d’ailleurs l’inventaire insuffisant des API parmi les risques majeurs.
Définir les profils d’appelants
- Frontend public : lecture de contenus publiés, sans secret embarqué dans le navigateur.
- Frontend connecté : consultation ou modification des données de l’utilisateur authentifié.
- Build ou SSR côté serveur : récupération de contenu depuis un environnement maîtrisé.
- Intégration tierce : CRM, ERP, PIM, logistique ou automatisation.
- Administrateur ou éditeur : opérations de gestion réservées au back-office.
Classer chaque route par niveau de sensibilité
Documentez pour chaque endpoint la méthode HTTP, les champs renvoyés, le rôle attendu, le type d’authentification et le propriétaire de la donnée. Ne traitez jamais une route qui reçoit un identifiant comme sûre par défaut : l’OWASP rappelle que l’autorisation au niveau de l’objet doit être contrôlée à chaque accès à une ressource identifiée.
| Cas d’usage | Accès recommandé | Point de vigilance |
|---|---|---|
| Blog ou catalogue public | Lecture anonyme, champs minimaux, cache CDN | Ne pas exposer de métadonnées internes ou de brouillons |
| Espace client | Session ou jeton adapté au frontend | Contrôle du propriétaire de chaque commande ou ressource |
| Connecteur serveur à serveur | Compte de service dédié et secret révocable | Droits minimaux, rotation et journalisation |
| Route métier personnalisée | Autorisation par capacité et par objet | Validation stricte des paramètres et des champs modifiables |
Choisir l’authentification selon le flux
Il n’existe pas un mécanisme unique valable pour tous les projets. Le choix dépend du fait que la requête provient d’un navigateur, d’un serveur ou d’un outil tiers. Surtout, une authentification réussie ne remplace jamais le contrôle des permissions.
Ne pas utiliser un nonce comme identifiant d’accès
Les nonces WordPress protègent principalement contre le CSRF dans une session WordPress existante. La documentation officielle précise qu’ils ne doivent jamais servir d’authentification, d’autorisation ou de contrôle d’accès. Ils ne sont donc pas une solution pour exposer une API à un frontend headless public sur un autre domaine.
Un nonce transmis via X-WP-Nonce reste pertinent pour des appels effectués dans le contexte d’un utilisateur WordPress connecté avec ses cookies. Pour une application séparée, privilégiez un véritable mécanisme d’identité conçu pour ce flux.
Utiliser des mots de passe d’application pour les intégrations ciblées
WordPress fournit des mots de passe d’application, révocables et associés à un utilisateur. Ils conviennent à un script de déploiement, un connecteur d’import ou un service tiers maîtrisé. Créez un compte dédié à chaque intégration, avec le rôle le moins permissif possible, puis nommez clairement le secret et révoquez-le dès qu’il n’est plus utile.
Ils s’utilisent avec Basic Auth sur HTTPS. Ils ne doivent pas être embarqués dans le JavaScript, une application mobile distribuée ou le dépôt Git. La documentation WordPress sur les mots de passe d’application confirme leur caractère révocable et leur usage prévu pour les accès programmatiques.
Prévoir OAuth 2.0 ou des jetons courts pour une application avec utilisateurs
Quand le frontend gère ses propres comptes, les permissions et la révocation doivent être pensées au niveau de l’application. Un fournisseur d’identité ou une couche d’authentification dédiée peut émettre des jetons courts, avec audience, durée de vie et scopes contrôlés. Le serveur valide ensuite ces éléments avant d’appeler WordPress ou une API métier.
Ce choix ajoute de la complexité, mais évite de donner à chaque navigateur un secret WordPress durable. Il est souvent plus approprié pour un SaaS, un espace client ou une application mobile.
Faire de l’autorisation la barrière principale
Les failles les plus coûteuses viennent souvent d’un accès accordé à un objet ou à une action qu’un utilisateur authentifié ne devrait pas pouvoir atteindre. Dans un endpoint personnalisé, vérifiez la capacité WordPress requise et, lorsque la ressource est liée à un utilisateur ou une organisation, vérifiez aussi qu’elle lui appartient.
Exiger un permission_callback sur chaque route privée
WordPress prévoit permission_callback lors de l’enregistrement d’une route REST. La recommandation officielle est d’utiliser current_user_can() plutôt qu’un simple test de connexion : être connecté ne prouve pas qu’un utilisateur peut effectuer l’action demandée.
add_action( 'rest_api_init', function () {
register_rest_route( 'acme/v1', '/orders/(?P<id>\d+)', array(
'methods' => 'GET',
'callback' => 'acme_get_order',
'permission_callback' => function ( WP_REST_Request $request ) {
$order_id = (int) $request['id'];
if ( ! current_user_can( 'read' ) ) {
return new WP_Error( 'rest_forbidden', 'Accès refusé.', array( 'status' => 403 ) );
}
return acme_current_user_owns_order( get_current_user_id(), $order_id );
},
'args' => array(
'id' => array(
'validate_callback' => 'is_numeric',
),
),
) );
} );
La fonction acme_current_user_owns_order() doit interroger la source métier de façon fiable. Ne déduisez pas la propriété depuis un paramètre envoyé par le client. Pour une action administrative, utilisez une capacité métier adaptée, par exemple manage_woocommerce, et non le rôle affiché dans l’interface.
Limiter les champs lus et écrits
Retourner l’objet WordPress ou WooCommerce brut est rarement nécessaire. Construisez une réponse explicite : identifiant, libellé, statut et champs réellement utilisés. De même, pour une mise à jour, acceptez une liste blanche de propriétés et ignorez les autres.
Cette précaution réduit le risque d’exposition excessive et de modification de masse, regroupés par l’OWASP sous le risque d’autorisation insuffisante au niveau des propriétés.
Configurer CORS sans en faire une fausse protection
CORS indique au navigateur quels sites web peuvent lire une réponse. Ce n’est ni une authentification ni une protection contre un appel serveur à serveur. Une API protégée seulement par CORS reste accessible à un attaquant qui appelle directement l’endpoint hors navigateur.
Par défaut, WordPress renvoie des en-têtes CORS permissifs et reprend l’origine reçue. Sa documentation REST explique que ce choix est intentionnel et qu’il est possible de remplacer le comportement par une liste d’origines stricte.
Autoriser explicitement les origines attendues
- Autorisez uniquement les domaines frontend nécessaires, en HTTPS et sans joker global.
- Traitez les environnements de production, préproduction et local séparément.
- Ne renvoyez jamais
Access-Control-Allow-Origin: *avec des credentials. - Répondez correctement aux prérequis
OPTIONSet limitez les méthodes et en-têtes aux besoins réels. - Vérifiez la présence de
Vary: Originpour éviter qu’un cache ne serve une réponse CORS à la mauvaise origine.
La restriction CORS est surtout utile pour des appels navigateur avec cookies ou jetons. Si le frontend est rendu côté serveur ou généré lors du build, préférez les appels privés serveur à serveur : aucun secret ne circule alors dans le navigateur.
Réduire l’exposition opérationnelle
Ne jamais placer un secret durable dans le frontend
Une variable préfixée pour être exposée au navigateur, un bundle JavaScript ou un dépôt public ne sont pas des coffres-forts. Placez les secrets côté serveur, dans le gestionnaire de secrets de votre hébergeur ou dans des variables d’environnement non publiques. Empêchez leur apparition dans les logs, les messages d’erreur et les outils d’analytics.
Protéger les routes coûteuses et les parcours métier
Une route de recherche, d’export, d’envoi d’email ou de création de commande peut être détournée sans tentative de connexion. Fixez des limites de débit au niveau CDN, WAF, reverse proxy ou application ; imposez des tailles maximales de requête et une pagination bornée. Ajoutez un contrôle spécifique sur les opérations déclenchant un coût ou un effet métier.
Ne vous limitez pas à une limite par IP : pour un parcours sensible, combinez-la avec l’identité, le compte, l’empreinte du client et des règles adaptées au cas d’usage.
Durcir WordPress et son infrastructure
- Imposez HTTPS et activez HSTS après vérification des sous-domaines.
- Maintenez WordPress, PHP, thèmes et extensions ; retirez les extensions inutilisées.
- Conservez des sauvegardes testées et un environnement de préproduction.
- Protégez l’administration avec MFA et des comptes nominatifs.
- Assurez-vous que le proxy transmet bien l’en-tête
Authorization, sans le journaliser en clair. - Désactivez ou restreignez les routes, plugins et comptes devenus obsolètes.
Journaliser, tester et revoir les accès
La sécurité ne se termine pas à la mise en ligne. Journalisez les erreurs 401/403, les appels anormaux, les créations de secrets et les actions sensibles, en évitant les données personnelles et les tokens. Définissez qui consulte ces alertes et comment révoquer rapidement un accès compromis.
Tests à intégrer avant chaque mise en production
- Appelez chaque route privée sans identifiant : la réponse doit être 401 ou 403.
- Appelez l’objet d’un autre compte avec un utilisateur valide : l’accès doit être refusé.
- Envoyez des champs non prévus dans une requête de mise à jour : ils ne doivent pas être enregistrés.
- Testez les origines autorisées et non autorisées, y compris le prérequis
OPTIONS. - Vérifiez les limites de pagination, de taille et de débit sur les routes coûteuses.
- Révoquez un mot de passe d’application et confirmez l’arrêt immédiat de l’intégration.
Les tests d’autorisation par objet sont essentiels : ils répondent directement au premier risque de l’OWASP API Security Top 10 2023. Ajoutez-les à vos tests automatisés dès qu’une route manipule une commande, un document, un utilisateur ou une ressource multi-tenant.
Une approche proportionnée au projet
Un site éditorial statique qui lit uniquement des contenus publiés n’exige pas la même architecture qu’un espace client WooCommerce ou qu’un SaaS multi-tenant. Dans le premier cas, réduire les champs publics, mettre en cache et isoler le CMS peuvent suffire. Dans le second, la gestion d’identité, des droits fins, des sessions et de la traçabilité doit être conçue comme une fonctionnalité centrale.
Le headless n’est donc pas automatiquement plus sûr qu’un WordPress classique. Il peut réduire certaines surfaces d’attaque côté frontend, mais introduit des flux supplémentaires qui doivent être documentés et contrôlés. Pour éviter de compromettre référencement et fonctionnement du frontend, retrouvez aussi les erreurs SEO à éviter avec WordPress headless.
Checklist de sécurisation avant mise en production
- Chaque route est inventoriée, documentée et rattachée à un propriétaire technique.
- Les données publiques, privées et administratives sont clairement séparées.
- Chaque route non publique possède une authentification adaptée et un
permission_callback. - Les contrôles vérifient à la fois la capacité et la propriété de l’objet.
- Les réponses et les écritures appliquent une liste blanche de champs.
- CORS est limité aux origines nécessaires, sans confondre ce mécanisme avec une protection d’accès.
- Aucun secret durable n’est livré au navigateur, au dépôt ou aux logs.
- Les appels coûteux et les parcours sensibles sont limités, surveillés et testés.
- Les comptes de service et leurs secrets peuvent être identifiés, rotatés et révoqués.
Questions fréquentes
Faut-il désactiver l’API REST WordPress en headless ?+
Non. En headless, l’API REST est généralement le lien entre WordPress et le frontend. Désactivez ou restreignez seulement les routes inutiles, puis appliquez une authentification et une autorisation adaptées aux routes privées.
Un nonce WordPress suffit-il pour sécuriser un frontend séparé ?+
Non. Un nonce aide à prévenir le CSRF dans une session WordPress existante, mais il ne remplace ni l’authentification ni l’autorisation. Pour un frontend headless, choisissez un mécanisme d’identité adapté et contrôlez les permissions sur chaque route.
CORS protège-t-il une API WordPress contre les appels non autorisés ?+
Non. CORS contrôle ce que les navigateurs autorisent à lire depuis une autre origine. Il n’empêche pas une requête directe réalisée depuis un serveur ou un script. Les permissions doivent être vérifiées côté API.
Quand utiliser un mot de passe d’application WordPress ?+
Il est pertinent pour une intégration serveur à serveur, un script ou un outil tiers maîtrisé. Utilisez un compte dédié avec des droits minimaux, HTTPS, un stockage secret côté serveur et une procédure de rotation ou de révocation.
Sécuriser votre architecture WordPress headless
Vous exposez WordPress à un frontend, un ERP, un CRM ou une application métier ? Naxialis peut auditer les flux existants, définir les droits et mettre en place une architecture d’API maintenable, du CMS au frontend. Parlons de votre projet WordPress headless ou de vos intégrations API.