0

I'm developing an API for my Wordpress website, I want to authorize all API request using jwt token. already installed and configured this plugin "JWT Authentication for WP REST API".But when I try via get/post methode my API will return data with out passing jwt access token how can I prevent this?

function api_version()
{
    $api=array( "version"=> "v1",

    "time"=>date('Y-m-d H:i:s P'));
    return $api;
}

add_action( 'rest_api_init', function () {
  register_rest_route( 'v1/', 'info', array(
    'methods' => 'GET',
    'callback' => 'api_version',

  ) );
} );

2 Answers 2

1

The token just authenticates the request as coming from a specific user. You still need to use the permissions callback to check if that user has permission for whatever it is you're doing. If you omit the permissions_callback argument when registering the route then the route is public.

If you only need to check if there is a user, and not specific permissions, you could just use is_user_logged_in():

register_rest_route( 'v1/', 'info', array(
    'methods' => 'GET',
    'callback' => 'api_version',
    'permissions_callback' => function() {
        return is_user_logged_in();
    },
) );
3
  • hi my problem is fixed using "rest_pre_dispatch" hook . i check is_user_logged_in() in this hook Commented Oct 24, 2019 at 13:36
  • 1
    That’s not the correct way to do this. To protect routes use the permissions callback. Commented Oct 24, 2019 at 14:02
  • 1
    return is_user_logged_in(); this is not working Commented Dec 23, 2019 at 11:40
0

Good Question and not that easy to do propperly (took me 1 week to figure that out).

Then I found 2 good summaries in WordPress docs:
Home / REST API Handbook / Extending the REST API / Routes and Endpoints
Home / REST API Handbook / Extending the REST API / Adding Custom Endpoints

There I found out how to use namespaces, routes and permission_callback correctly.

Critical part was to add the Permission Callback into the function.php of your theme, as @Jacob Peattie mentioned correctly in his answer.

Following, I used the if ( !isset($_COOKIE['wp-postpass_'. COOKIEHASH] )) in the Permission Callback (being the wp-postpass_ cookie the one that holds the token for password protected posts, as an alternative to is_user_logged_in() )

/**
  * This is our callback function to return (GET) our data.
  *
  * @param WP_REST_Request $request This function accepts a rest request to process data.
  */
function get_your_data($request) {
    global $wpdb;
    $yourdata = $wpdb->get_results("SELECT * FROM your_custom_table");

    return rest_ensure_response( $yourdata );
};

/**
 * This is our callback function to insert (POST) new data record.
 *
 * @param WP_REST_Request $request This function accepts a rest request to process data.
 */
function insert_your_data($request) {
    global $wpdb;
    $contentType = isset($_SERVER["CONTENT_TYPE"]) ? trim($_SERVER["CONTENT_TYPE"]) : '';

    if ($contentType === "application/json") {
        $content = trim(file_get_contents("php://input"));
        $decoded = json_decode($content, true);
        $newrecord = $wpdb->insert( 'your_custom_table', array( 'column_1' => $decoded['column_1'], 'column_2' => $decoded['column_2']));
    };
    if($newrecord){
        return rest_ensure_response($newrecord);
    }else{
        //something gone wrong
        return rest_ensure_response('failed');
    };

    header("Content-Type: application/json; charset=UTF-8");
};
/**
 * This is our callback function to update (PUT) a data record.
 *
 * @param WP_REST_Request $request This function accepts a rest request to process data.
 */
function update_your_data($request) {
    global $wpdb;
    $contentType = isset($_SERVER["CONTENT_TYPE"]) ? trim($_SERVER["CONTENT_TYPE"]) : '';

    if ($contentType === "application/json") {
        $content = trim(file_get_contents("php://input"));
        $decoded = json_decode($content, true);
        $updatedrecord = $wpdb->update( 'your_custom_table', array( 'column_1' => $decoded['column_1'], 'column_2' => $decoded['column_2']), array('id' => $decoded['id']), array( '%s' ));
    };

    if($updatedrecord){
        return rest_ensure_response($updatedrecord);
    }else{
        //something gone wrong
        return rest_ensure_response('failed');
    };

    header("Content-Type: application/json; charset=UTF-8");
};

//  Permission Callback 
// 'ypp' is the Prefix I chose (ypp = Your Private Page)

function ypp_get_private_data_permissions_check() {
    // Restrict endpoint to browsers that have the wp-postpass_ cookie.

    if ( !isset($_COOKIE['wp-postpass_'. COOKIEHASH] )) {
       return new WP_Error( 'rest_forbidden', esc_html__( 'OMG you can not create or edit private data.', 'my-text-domain' ), array( 'status' => 401 ) );
    };
    // This is a black-listing approach. You could alternatively do this via white-listing, by returning false here and changing the permissions check.
    return true;
};

// And then add the permission_callback to your POST and PUT routes:

add_action('rest_api_init', function() {
    /**
    * Register here your custom routes for your CRUD functions
    */
    register_rest_route( 'your_private_page/v1', '/data', array(
       array(
          'methods'  => WP_REST_Server::READABLE,
          'callback' => 'get_your_data',
          // Always allow.
          'permission_callback' => '__return_true' // <-- you can protect GET as well if your like
       ),
       array(
          'methods'  => WP_REST_Server::CREATABLE,
          'callback' => 'insert_your_data',
          // Here we register our permissions callback. The callback is fired before the main callback to check if the current user can access the endpoint.
          'permission_callback' => 'ypp_get_private_data_permissions_check', // <-- that was the missing part
       ),
       array(
          'methods'  => WP_REST_Server::EDITABLE,
          'callback' => 'update_your_data',
          // Here we register our permissions callback. The callback is fired before the main callback to check if the current user can access the endpoint.
          'permission_callback' => 'ypp_get_private_data_permissions_check', // <-- that was the missing part
       ),
    ));
});

If you like, I posted a Question (similar issue to yours concerning JWT Authentication) and then my findings in the answer as it worked finally.

Full story with full code at:
How to force Authentication on REST API for Password protected page using custom table and fetch() without Plugin

Hope this helps a little.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.