wp_verify_nonce( string $nonce, string|int $action = -1 ): int|false

Verifies that a correct security nonce was used with time limit.

Description

A nonce is valid for 24 hours (by default).

Parameters

$noncestringrequired
Nonce value that was used for verification, usually via a form field.
$actionstring|intoptional
Should give context to what is taking place and be the same when nonce was created.

Default:-1

Return

int|false 1 if the nonce is valid and generated between 0-12 hours ago, 2 if the nonce is valid and generated between 12-24 hours ago.
False if the nonce is invalid.

More Information

The function is used to verify the nonce sent in the current request usually accessed by the $_REQUEST PHP variable.

Nonces should never be relied on for authentication or authorization, access control. Protect your functions using current_user_can(), always assume Nonces can be compromised.

Source

function wp_verify_nonce( $nonce, $action = -1 ) {
	$nonce = (string) $nonce;
	$user  = wp_get_current_user();
	$uid   = (int) $user->ID;
	if ( ! $uid ) {
		/**
		 * Filters whether the user who generated the nonce is logged out.
		 *
		 * @since 3.5.0
		 *
		 * @param int        $uid    ID of the nonce-owning user.
		 * @param string|int $action The nonce action, or -1 if none was provided.
		 */
		$uid = apply_filters( 'nonce_user_logged_out', $uid, $action );
	}

	if ( empty( $nonce ) ) {
		return false;
	}

	$token = wp_get_session_token();
	$i     = wp_nonce_tick( $action );

	// Nonce generated 0-12 hours ago.
	$expected = substr( wp_hash( $i . '|' . $action . '|' . $uid . '|' . $token, 'nonce' ), -12, 10 );
	if ( hash_equals( $expected, $nonce ) ) {
		return 1;
	}

	// Nonce generated 12-24 hours ago.
	$expected = substr( wp_hash( ( $i - 1 ) . '|' . $action . '|' . $uid . '|' . $token, 'nonce' ), -12, 10 );
	if ( hash_equals( $expected, $nonce ) ) {
		return 2;
	}

	/**
	 * Fires when nonce verification fails.
	 *
	 * @since 4.4.0
	 *
	 * @param string     $nonce  The invalid nonce.
	 * @param string|int $action The nonce action.
	 * @param WP_User    $user   The current user object.
	 * @param string     $token  The user's session token.
	 */
	do_action( 'wp_verify_nonce_failed', $nonce, $action, $user, $token );

	// Invalid nonce.
	return false;
}

Hooks

apply_filters( ‘nonce_user_logged_out’, int $uid, string|int $action )

Filters whether the user who generated the nonce is logged out.

do_action( ‘wp_verify_nonce_failed’, string $nonce, string|int $action, WP_User $user, string $token )

Fires when nonce verification fails.

Changelog

VersionDescription
2.0.3Introduced.

User Contributed Notes

  1. Skip to note 4 content

    Example
    Verify an nonce created with wp_create_nonce():

    <?php
    // Step A: Create an nonce, and add it as a query var in a link to perform an action.
    $nonce = wp_create_nonce( 'my-nonce' );
    echo "<a href='myplugin.php?_wpnonce={$nonce}'>" . __( 'Save Something', 'textdomain' ) . "</a>";
    ?>
    // Step B: In our file that handles the request, verify the nonce.
    $nonce = $_REQUEST['_wpnonce'];
    if ( ! wp_verify_nonce( $nonce, 'my-nonce' ) ) {
    	die( __( 'Security check', 'textdomain' ) ); 
    } else {
    	// Do stuff here.
    }

    You may also decide to take different actions based on the age of the nonce:

    $nonce = wp_verify_nonce( $nonce, 'my-nonce' );
    switch ( $nonce ) {
    	case 1:
    		echo 'Nonce is less than 12 hours old';
    		break;
    	case 2:
    		echo 'Nonce is between 12 and 24 hours old';
    		break;
    	default:
    		exit( 'Nonce is invalid' );
    }
  2. Skip to note 6 content

    This system is not very accurate and the comment about the return values is incorrect. The value 1 means < 12 hours old, but 2 means anywhere from 1 second to < 24 hours old.

    Observe what happens to the nonce tick value over a day:

    local time ~~~ seconds since epoch ~~~ tick
    2021-05-20T00:00:00+03:00 ~~~ 1621458000 ~~~ 37534
    2021-05-20T01:00:00+03:00 ~~~ 1621461600 ~~~ 37534
    2021-05-20T02:00:00+03:00 ~~~ 1621465200 ~~~ 37534
    2021-05-20T03:00:00+03:00 ~~~ 1621468800 ~~~ 37534
    2021-05-20T04:00:00+03:00 ~~~ 1621472400 ~~~ 37535
    2021-05-20T05:00:00+03:00 ~~~ 1621476000 ~~~ 37535
    2021-05-20T06:00:00+03:00 ~~~ 1621479600 ~~~ 37535
    2021-05-20T07:00:00+03:00 ~~~ 1621483200 ~~~ 37535
    2021-05-20T08:00:00+03:00 ~~~ 1621486800 ~~~ 37535
    2021-05-20T09:00:00+03:00 ~~~ 1621490400 ~~~ 37535
    2021-05-20T10:00:00+03:00 ~~~ 1621494000 ~~~ 37535
    2021-05-20T11:00:00+03:00 ~~~ 1621497600 ~~~ 37535
    2021-05-20T12:00:00+03:00 ~~~ 1621501200 ~~~ 37535
    2021-05-20T13:00:00+03:00 ~~~ 1621504800 ~~~ 37535
    2021-05-20T14:00:00+03:00 ~~~ 1621508400 ~~~ 37535
    2021-05-20T15:00:00+03:00 ~~~ 1621512000 ~~~ 37535
    2021-05-20T16:00:00+03:00 ~~~ 1621515600 ~~~ 37536
    2021-05-20T17:00:00+03:00 ~~~ 1621519200 ~~~ 37536
    2021-05-20T18:00:00+03:00 ~~~ 1621522800 ~~~ 37536
    2021-05-20T19:00:00+03:00 ~~~ 1621526400 ~~~ 37536
    2021-05-20T20:00:00+03:00 ~~~ 1621530000 ~~~ 37536
    2021-05-20T21:00:00+03:00 ~~~ 1621533600 ~~~ 37536
    2021-05-20T22:00:00+03:00 ~~~ 1621537200 ~~~ 37536
    2021-05-20T23:00:00+03:00 ~~~ 1621540800 ~~~ 37536

    …and over the boundary of a tick:

    local time ~~~ seconds since epoch ~~~ tick
    2021-05-20T14:59:58+03:00 ~~~ 1621511998 ~~~ 37535
    2021-05-20T14:59:59+03:00 ~~~ 1621511999 ~~~ 37535
    2021-05-20T15:00:00+03:00 ~~~ 1621512000 ~~~ 37535
    2021-05-20T15:00:01+03:00 ~~~ 1621512001 ~~~ 37536
    2021-05-20T15:00:02+03:00 ~~~ 1621512002 ~~~ 37536

    In this example, you can see that a nonce generated at 3pm and verified one second later will return 2 because of the tick change. The ticks do not align with timezones due to their basis in universal time, so nonces will always appear “old” to your code at certain times of the day.

You must log in before being able to contribute a note or feedback.