the wp_verify_nonce() keep returning false
If you were logged-in to your (WordPress) site when you used the form, then the above is normal. Here’s why so:
-
Your form submits to a custom REST API endpoint (at
/wp-json/ilms_plugin/new_membership) and the default authentication method used by the REST API is cookie-based, i.e. it checks if a nonce with the action namedwp_restis set and that it’s valid (not yet expired), and if not (not set or it’s invalid/expired), then WordPress sets the current user to0which affects all nonce-related functions including but not limited towp_verify_nonce(). -
In simple words, it means functions like
wp_verify_nonce()will return false because nonces are based on the current user, so if the user is logged-in to your site (when filling in the form), but not the REST API (when the form submission/data is processed), thenwp_verify_nonce()will return false because the user ID becomes0in the REST API.
Check out the REST API handbook for more details about the authentication: https://developer.wordpress.org/rest-api/using-the-rest-api/authentication/
How to fix the issue
Just add wp_nonce_field( 'wp_rest', '_wpnonce', false ); somewhere in your form, e.g. right after the opening <form> tag: (Note that I escaped the URL using esc_url())
<form action="<?php echo esc_url( get_rest_url( null, 'ilms_plugin/new_membership' ) ); ?>" ...>
<?php wp_nonce_field( 'wp_rest', '_wpnonce', false ); ?>
...
Additional Notes
-
Instead of
get_rest_url( null, 'ilms_plugin/new_membership' ), you could userest_url( 'ilms_plugin/new_membership' )which usesrest_url()and is shorter.. 🙂 -
Instead of using
$wpdb->query(), I would use$wpdb->insert()to insert the data to the database. -
A REST API endpoint should always set a
permission_callbackand you should also use theargsargument to define the parameters for the endpoint like thetest_noncein your case. Nonetheless, refer to Adding Custom Endpoints in the REST API handbook for further details.