Le WordPress d'aujourd'hui, décodé pour les développeurs

Headless & API

Cabinet notarial : limiter les champs exposés par /wp/v2/posts

Un espace client et un site vitrine ne devraient jamais partager la même surface d'API. Le cas d'une étude notariale qui a dû trancher entre confort et confidentialité.

Par WordPress Développement • 3 juillet 2020 • 4 min de lecture • Aucun commentaire
Cabinet notarial : limiter les champs exposés par /wp/v2/posts

Un espace client et un site vitrine ne devraient jamais partager le même point d’entrée d’API, et c’est précisément l’erreur qu’une étude notariale a failli commettre en construisant son nouveau site public. Le contenu éditorial du site vitrine — actualités du cabinet, présentation des notaires, articles d’information juridique — devait rester accessible publiquement via l’API REST, tandis que l’espace client, hébergé sur le même WordPress pour des raisons pratiques, contenait des documents sensibles rattachés à des types de contenus distincts mais visibles par la même route générique si elle n’était pas restreinte.

La route native /wp/v2/posts renvoie par défaut une douzaine de champs par article : contenu complet, extrait, méta liées au format, liens vers l’auteur et bien d’autres. Sur un site où certains de ces champs peuvent laisser fuiter des informations internes, ce comportement par défaut ne convient pas tel quel.

Ce que révèle un simple appel non filtré

Un appel brut à la route standard, sans aucune restriction, retourne des champs que le front vitrine n’utilisera jamais, mais qui restent techniquement accessibles à quiconque connaît l’URL de l’API.

GET /wp-json/wp/v2/posts/42

{
  "id": 42,
  "date": "2020-06-28T09:15:00",
  "guid": { "rendered": "https://etude-exemple.fr/?p=42" },
  "content": { "rendered": "..." },
  "excerpt": { "rendered": "..." },
  "author": 3,
  "meta": { "_notes_internes": "à revoir avant publication" }
}

Le champ meta ici illustre le vrai risque : une méta interne, jamais destinée à sortir du back-office, se retrouve exposée simplement parce qu’elle est enregistrée avec show_in_rest activé sur son groupe de champs, sans restriction supplémentaire.

Première protection : filtrer côté serveur avec rest_prepare_post

Le filtre rest_prepare_post permet de retirer des champs de la réponse juste avant son envoi, quelle que soit la façon dont le client a formulé sa requête. C’est la seule approche fiable pour une donnée réellement sensible, puisqu’elle ne dépend d’aucun paramètre côté client.

L'essentiel à retenir : La route /wp/v2/posts expose par défaut bien plus que le nécessaire ; Le filtre rest_prepare_post retire les champs indésirables ; L'argument _fields côté client réduit la charge sans rien filtrer côté serveur
add_filter( 'rest_prepare_post', function( $response, $post, $request ) {
    $data = $response->get_data();
    unset( $data['guid'] );
    unset( $data['meta']['_notes_internes'] );
    $response->set_data( $data );
    return $response;
}, 10, 3 );

Deuxième levier : l’argument _fields côté client

Pour les cas où la donnée n’est pas sensible mais simplement inutile au front, l’argument de requête _fields réduit la réponse aux seules propriétés demandées, sans rien changer côté serveur.

GET /wp-json/wp/v2/posts?_fields=id,title,excerpt,link

Ce mécanisme allège la réponse et le temps de sérialisation JSON, mais il ne doit jamais être confondu avec une mesure de sécurité : rien n’empêche un client d’omettre _fields et de récupérer la totalité des données non filtrées côté serveur.

Le cas particulier des révisions et des brouillons

Un point a failli échapper à l’équipe technique lors des tests : la route /wp/v2/posts ne renvoie par défaut que les articles publiés à un visiteur non authentifié, mais un paramètre de requête mal contrôlé aurait pu, dans une version antérieure du code, laisser filtrer un statut différent si l’authentification de l’espace client partageait par erreur le même jeton que le site vitrine.

Ce risque a été écarté en s’assurant que les deux espaces utilisent des mécanismes d’authentification totalement distincts, sans jamais partager de cookie de session ni de jeton entre le site vitrine public et l’espace client réservé.

Répartition des responsabilités

  • Donnée sensible à ne jamais exposer : filtrage obligatoire côté serveur via rest_prepare_post
  • Donnée publique mais inutile pour un affichage donné : réduction côté client via _fields

Une donnée sensible filtrée uniquement côté client n’est jamais réellement protégée ; elle est simplement moins visible dans les cas d’usage prévus.

En résumé

Pour cette étude notariale, la séparation nette entre filtrage serveur des champs sensibles et allégement client des champs inutiles a permis de conserver un WordPress unique pour le site vitrine et l’espace client, sans jamais mélanger les deux surfaces exposées par l’API REST. Ce cas ne traite pas la question de l’authentification de l’espace client lui-même, qui mériterait un traitement séparé et plus approfondi.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Partager :

À propos de l'auteur

WordPress Développement

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi