0

I’ve recently added jwt authentication to my website because frontend of my site is completely decoupled from backend.
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?

Also, nonces are used to secure wordpress from csrf for example. Is there any way to secure rest api from csrf, other than setting cors rules correctly (to allow only frontend domain?

4
  • nonces are not authentication tokens, if your site is only accepting API requests from users on that site then I do not see any advantages to using JWT to authenticate REST API requests. The standard cookie + nonce that comes with WordPress would be enough assuming HTTPS is set up
    – Tom J Nowell
    Jan 28, 2021 at 11:12
  • Currently I've got frontend on another domain on another server (built with React- GatsbyJS). I think I could host frontend on subdomain (or backend on subdomain and frontend on main domain). Is standard wordpress session doable with this setup? I want smooth SPA experience on frontend, so I would need to send request to rest api anyway. I probably would need to create login endpoint where I manually log in user with username and password and create authentication cookie manually. I would need nonce that lasts as long as wordpress session too....
    – user179669
    Jan 28, 2021 at 12:37
  • This depends on where the frontend and backend are located in relation to each other, but that's not a WP problem, that's a general browser cookie scope problem. I do not see a need for the two to have separate domains, it needlessly complicates things. Either use a WordPress theme that just bootstraps a SPA, or, route wp-* URLs to WordPress and everything else to Node or whatever is serving your SPA.
    – Tom J Nowell
    Jan 28, 2021 at 12:40
  • And as I said earlier, nonces are not authentication tokens. An authentication protocol based entirely off of nonces would be disastrous, and a gross misunderstanding of what they're intended for.
    – Tom J Nowell
    Jan 28, 2021 at 12:40

1 Answer 1

0

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.

10
  • I think I formed my question in a bad way :( I dont want to use nonces as authenticators. I just need to store wp_nonce on frontend for users to be able to use protected routes of my rest api (which lets them modify their own data etc) for at least as long as their session is active. I just wanted to ask if storing wp_nonce on frontend for that long and continously using the same wp_nonce (which wordpress needs to authenticate user) with cookie to authenticate user is more vurnerable than just session cookie. If im hosting my SPA on nodejs I need to create that nonce on my wordpress install
    – user179669
    Jan 28, 2021 at 13:02
  • In short - if I want to use wp_nonce + session instead of jwt in my SPA I need to create that nonce and make it valid for like 7 days on my wordpress install, then pass it to my frontend (lets say on subdomain) and pass both that same nonce and session id for 7 days. Isnt it vulnerable in some way?
    – user179669
    Jan 28, 2021 at 13:05
  • OR I could refresh the nonce on every request. Again, just wanted to ask if it has some security implications
    – user179669
    Jan 28, 2021 at 13:07
  • For the same reasons you shouldn't use nonces as session identifiers, nonces are meant to be throwaway values
    – Tom J Nowell
    Jan 28, 2021 at 13:10
  • So what should I do then? Wordpress REST API needs wp-nonce to authorize user (I need to pass both wp-nonce and session cookie to use api resources that need authorization). I'm using React static site generator (GatsbyJS) output (static html files with app on top of them) as frontend. I think I need to place it on subdomain atleast.
    – user179669
    Jan 28, 2021 at 13:25

Your Answer

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