I would like to understand the best practices regarding nonce validation in REST APIs.

I see a lot of people talking about `wp_rest` nonce for REST requests. But upon looking on WordPress core code, I saw that `wp_rest` is just a nonce to validate a logged in user status, if it's not present, it just runs the request as guest.

That said, should I submit two nonces upon sending a POST request to a REST API? One for authentication `wp_rest` and another for the action `foo_action`?

If so, how should I send `wp_rest` and `foo_action` nonce in JavaScript, and, in PHP, what's the correct place to validate those nonces? (I mean validate\_callback for a arg? permission\_callback?)
['https://wordpress.stackexchange.com/questions/323637', 'https://wordpress.stackexchange.com', 'https://wordpress.stackexchange.com/users/27278/']
Building on what @lucas-bustamante wrote (which helped me a ton!), once you have the X-WP-Nonce header setup in your custom routes you can do the following:

```php
    register_rest_route('v1', '/my_post', [
        'methods' => WP_REST_Server::CREATABLE,
        'callback' => [$this, 'create_post'],
        'args' => [
            'post_title' => [
                'required' => true,
            ],
            'post_excerpt' => [
                'required' => true,
            ]
        ],
        'permission_callback' => function ( ) {
            return current_user_can( 'publish_posts' );
        },
    ]);

```

Note that the `permission_callback` is on the root level not under args ([documented here](https://developer.wordpress.org/rest-api/extending-the-rest-api/adding-custom-endpoints/#permissions-callback)) and I've removed the additional `nonce` check from `args` since checking the permission alone will fail if the nonce is invalid or not supplied (I've tested this extensively and can confirm I get an error when no nonce is supplied or it's invalid).
One thing to note about @Lucas Bustamante's answer is that the verification process described is user-based authentication. This means if you have an anonymous API end point which doesn't require a user, then by simply by not providing the `X-WP-NONCE` header you'll pass the described nonce check. Supplying an incorrect nonce will still throw an error.

The reason for this is that the `rest_cookie_check_errors` which is what does the verification will simply set the `current_user` to empty if no nonce is provided. This works fine when a user is required, but not otherwise. (see: <https://developer.wordpress.org/reference/functions/rest_cookie_check_errors/>)

If you want to expand on Lucas' answer to also include annonymous end points, then you can add a manual nonce check to the start of your end point, like this:

```
if ( !$_SERVER['HTTP_X_WP_NONCE'] || !wp_verify_nonce( $_SERVER['HTTP_X_WP_NONCE'], 'wp_rest' ) ) {
    header('HTTP/1.0 403 Forbidden');
    exit;
}

```