L'API WP REST requiert un mot de passe pour GET Endpoint

8

J'ai un type de publication personnalisé card, que j'expose via l'API WP REST. Existe-t-il un moyen d'exiger une authentification, avec un cookie ou un en-tête d'authentification de base? Je vois un argument sous le bloc de méthode POST pour le mot de passe, mais je ne sais pas comment l'utiliser.

entrez la description de l'image ici

YarGnawh
la source

Réponses:

9

Lorsque nous enregistrons une route de repos avec register_rest_route(), nous pouvons utiliser le permission_callbackparamètre avec le type d'autorisation que nous voulons.

Vérifiez par exemple comment WP_REST_Posts_Controller::register_routes()et WP_REST_Users_Controller::register_routes()implémentez le rappel d'autorisation.

L'argument du mot de passe auquel vous faites référence est le mot de passe du contenu, que vous pouvez définir pour chaque publication et ce n'est pas le même.

Mais puisque vous souhaitez cibler des itinéraires existants, comme:

/wp/v2/cards
/wp/v2/cards/(?P<id>[\d]+)
/wp/v2/cards/...possibly some other patterns...

vous pouvez par exemple essayer le rest_dispatch_requestfiltre pour configurer votre vérification d'autorisation supplémentaire pour ce type de routes.

Voici un plugin de démonstration:

add_filter( 'rest_dispatch_request', function( $dispatch_result, $request, $route, $hndlr )
{
    $target_base = '/wp/v2/cards';    // Edit to your needs

    $pattern1 = untrailingslashit( $target_base ); // e.g. /wp/v2/cards
    $pattern2 = trailingslashit( $target_base );   // e.g. /wp/v2/cards/

    // Target only /wp/v2/cards and /wp/v2/cards/*
    if( $pattern1 !== $route && $pattern2 !== substr( $route, 0, strlen( $pattern2 ) ) )
        return $dispatch_result;

    // Additional permission check
    if( is_user_logged_in() )  // or e.g. current_user_can( 'manage_options' )
        return $dispatch_result;

    // Target GET method
    if( WP_REST_Server::READABLE !== $request->get_method() ) 
        return $dispatch_result;

    return new \WP_Error( 
        'rest_forbidden', 
        esc_html__( 'Sorry, you are not allowed to do that.', 'wpse' ), 
        [ 'status' => 403 ] 
    );

}, 10, 4 );

où nous ciblons les routes /wp/v2/cardset /wp/v2/cards/*GET, avec des vérifications supplémentaires des autorisations des utilisateurs.

Lors du débogage avec l'authentification par cookie WordPress, nous pouvons par exemple le tester directement avec:

https://example.tld/wp-json/wp/v2/cards?_wpnonce=9467a0bf9c

où la partie nonce a été générée à partir de wp_create_nonce( 'wp_rest' );

J'espère que cela t'aides!

Birgire
la source
J'ai essayé de le rendre général pour une base cible donnée, mais peut-être y a-t-il un moyen plus simple de contourner cela? J'ai ajouté un exemple de capacité en tant que commentaire en ligne @MarkKaplun
birgire
Il est peut-être encore plus simple de supprimer le point de terminaison pour un type de publication personnalisé donné, avec le register_post_type_argsfiltre et e, g, définis $args['show_in_rest'] = is_user_logged_in();pour un type de publication donné ou basés sur $args['rest_base']. Je ne sais pas si c'est voulu ou recommandé ;-)
birgire
3

Le champ "mot de passe" que vous voyez n'est en fait pas pour l'API REST, mais pour l'entrée de publication elle-même. Les messages individuels dans WordPress peuvent être protégés par mot de passe de sorte que vous avez besoin du mot de passe pour voir leur contenu.

Cette forme de post-mot de passe individuel n'est pas un mécanisme de mot de passe solide, c'est un mot de passe partagé. Le mot de passe est le même pour tous les utilisateurs et il est stocké dans la base de données non chiffré et sans hachage. Il n'a jamais été conçu comme un mécanisme sécurisé, c'est un mécanisme simple pour masquer le contenu de manière simple.

Si vous souhaitez utiliser ce mécanisme avec l'API REST, c'est possible. Par exemple, si l'ID de la publication individuelle est 123, alors une publication peut être récupérée comme suit:

http://example.com/wp-json/wp/v2/posts/123

Si ce message est protégé par mot de passe, cette URL le récupérera:

http://example.com/wp-json/wp/v2/posts/123?password=example-pass

Référence: https://developer.wordpress.org/rest-api/reference/posts/#retrieve-a-post

Si vous avez besoin d'une authentification basée sur l'utilisateur plus forte, alors WordPress offre un moyen de rendre les publications "privées" à la place. Ce paramètre rend les publications uniquement visibles pour les comptes d'utilisateurs qui ont la capacité "read_private_posts", qui est limitée aux rôles Administrateur et Éditeur par défaut. (Remarque: Private ne rend le contenu de la publication que privé, leurs titres peuvent toujours être exposés.)

Lorsque vous créez un type de publication personnalisé, cette même capacité est mappée au pluriel de votre type (à l'aide de plural_base). Ainsi, pour un type de publication de cartes, il y aurait une autorisation similaire "read_private_cards" disponible pour vous attribuer des rôles d'utilisateur si vous le souhaitez.

Désormais, l'authentification au niveau de l'utilisateur n'est pas réellement intégrée à l'API REST. L'authentification standard basée sur les cookies WordPress fonctionne bien, mais l'API ne propose aucun moyen d'obtenir ce cookie. Il l'acceptera s'il est présent, mais vous devez suivre le flux de connexion normal pour obtenir un tel cookie. Si vous voulez une autre approche d'authentification, vous avez besoin d'un plugin pour cela.

Il existe quatre plugins de ce type. Il s'agit d'OAuth 1.0, des mots de passe d'application, des jetons Web JSON et d'un plug-in d'authentification de base. Notez que l'authentification de base est la plus simple, mais elle est également non sécurisée et n'est donc recommandée qu'à des fins de test et de développement. Il ne doit pas être utilisé sur un serveur de production en direct.

Vous pouvez trouver plus d'informations sur ces plugins ici:

https://developer.wordpress.org/rest-api/using-the-rest-api/authentication/#authentication-plugins

Otto
la source