wp_nonce vs jwt

What I haven’t thought of is that I could use wp_nonce instead of jwt – create nonce on backend, store it on frontend and send it with every request till it expires.

What drawbacks does wp nonce method have vs jwt method?

Using nonces as a replacement for an authentication protocol, or as a session identifier would be insecure. A nonce is not an authentication or identifying token.

Using it as an authentication token is not going to work, or rather it will function but it will have incredibly weak security.

The purpose of a nonce is to prove that when a user takes an action, that they intended to take that action, that the request was deliberate. It is not proof that the user are who they said they are, and it provides no guarantees in relation to identity.

If they are used in authentication it is as a test to detect replay attacks and avoid a recorded login request being resent by an attacker, but they can’t be used to verify and login a user.

TLDR: This is a bad idea, nonces cannot be used as authenticators. stick to a known good method that is well defined and battle hardened if you want security and safety.

And don’t roll your own crypto


Lets test just how secure a WP nonce would be, at the time of writing, this is the implementation WP uses:

function wp_create_nonce( $action = -1 ) {
    $user = wp_get_current_user();
    $uid  = (int) $user->ID;
    if ( ! $uid ) {
        /** This filter is documented in wp-includes/pluggable.php */
        $uid = apply_filters( 'nonce_user_logged_out', $uid, $action );
    }
 
    $token = wp_get_session_token();
    $i     = wp_nonce_tick();
 
    return substr( wp_hash( $i . '|' . $action . '|' . $uid . '|' . $token, 'nonce' ), -12, 10 );
}

In the proposed scheme, this would be simplified down to:

function wp_create_nonce( $action = -1 ) {
    $i     = wp_nonce_tick();
    return substr( wp_hash( $i . '|' . $action . '||', 'nonce' ), -12, 10 );
}

So a user would need to know the action, the nonce tick, and the salt used by wp_hash. We will know the action, the nonce tick is a simple time calculation with some rounding, therefore we just need to bruteforce the salt.

We can do this by adjusting wp_create_nonce to use a version of wp_hash that cycles through every possible value for wp_salt. This will give us either the AUTH_SALT or SECURE_AUTH_SALT in wp-config.php.

From there on a chain of events occurs that allows us to impersonate anybody on your site. Mitigating this would involve the nonce_user_logged_out and devising a scheme to insert more user session based data, but this just delays the inevitable.