Bloquer l’accès à wp-admin ressemble à une opération simple : une redirection, une vérification de rôle, et le tour est joué. Bloquer wp-admin tout en laissant l’API REST parfaitement fonctionnelle est une opération légèrement plus délicate, car les deux chemins ne partagent qu’une partie de leur cycle d’exécution WordPress, et une redirection mal ciblée referme les deux portes à la fois sans qu’on s’en rende compte immédiatement.
Pourquoi la distinction est nécessaire
Sur un projet headless où le contenu est entièrement piloté depuis un outil de gestion tiers ou depuis un accès restreint, l’interface d’administration classique de WordPress devient superflue pour la majorité des utilisateurs, voire une surface d’attaque à réduire. Fermer wp-admin à toute personne non autorisée, tout en laissant l’API REST répondre normalement aux requêtes légitimes du front, permet de réduire cette surface sans perdre la capacité du front à consommer les données.
Le point de vigilance principal tient au hook utilisé pour appliquer cette restriction. Une requête REST ne charge jamais wp-admin, mais elle traverse tout de même une partie du chargement de WordPress commune aux deux univers, notamment le hook init. Une condition posée trop largement, ou accrochée au mauvais moment, peut casser les deux chemins simultanément.
La recette

add_action( 'init', function () {
$est_requete_rest = defined( 'REST_REQUEST' ) && REST_REQUEST;
$est_ajax = wp_doing_ajax();
$est_admin = is_admin();
if ( $est_admin && ! $est_requete_rest && ! $est_ajax && ! current_user_can( 'manage_options' ) ) {
wp_safe_redirect( home_url( '/' ) );
exit;
}
} );
La constante REST_REQUEST, définie par WordPress dès qu’une requête transite par le serveur REST, permet de distinguer sans ambiguïté ce contexte du reste de l’exécution. La fonction is_admin(), elle, ne vérifie absolument pas un rôle utilisateur : elle indique seulement que la requête courante cible une URL de wp-admin, qu’il s’agisse d’un affichage de page ou d’une requête admin-ajax.php. C’est justement pour cette raison que wp_doing_ajax() doit être vérifié séparément, faute de quoi certains appels internes de l’éditeur de blocs, qui transitent par admin-ajax.php, se retrouveraient bloqués à tort.
Ce qui reste accessible
- Toutes les routes de
/wp-json/, y compris celles ajoutées par des extensions tierces - La page de connexion
wp-login.php, nécessaire pour que les utilisateurs autorisés puissent encore s’identifier - L’accès complet à
wp-adminpour tout utilisateur disposant de la capacitémanage_options, généralement réservée aux administrateurs
Un piège fréquent : bloquer trop tôt
Accrocher cette vérification à un hook qui s’exécute avant que les capacités utilisateur ne soient pleinement disponibles — trop tôt dans le cycle de chargement de WordPress — produit un comportement erratique, où current_user_can() retourne systématiquement faux même pour un administrateur légitime déjà connecté. Le hook init reste un choix sûr, car il se déclenche après l’initialisation complète de l’utilisateur courant, contrairement à des hooks plus précoces comme plugins_loaded.
Vérifier que l’API reste bien intacte
Une fois la restriction en place, un test simple consiste à interroger une route publique de l’API REST depuis un terminal, sans être authentifié, et à vérifier que la réponse JSON attendue arrive normalement, avec un statut 200 :
curl -i https://exemple.test/wp-json/wp/v2/posts
Si cette commande retourne une redirection vers la page d’accueil plutôt que le JSON attendu, la condition posée sur init est probablement trop large et capture aussi les requêtes REST, signe qu’il faut revérifier la constante REST_REQUEST utilisée dans la condition.
En résumé
Fermer wp-admin sans toucher à l’API REST tient à une seule distinction technique : la constante REST_REQUEST permet de reconnaître à coup sûr un appel à l’API, indépendamment du reste de la logique de restriction posée sur wp-admin. Une fois cette distinction posée correctement, un projet headless peut réduire drastiquement sa surface d’administration exposée sans jamais perturber le fonctionnement du front qui consomme ses données.