WordPress DiscourseConnect client - expired nonce

I ran into the same problem and it does it for logging in with Google. Before WordPress we use Nginx as a reverse proxy. Could this be related?

I’m assuming this is happening with logging into WordPress via your Discourse site. If that’s the case, the issue is that the nonce generated by WordPress is expired. This happens on WordPress sites that have an Object Caching enabled.

One solution is to disable the Object Cache on any pages that have the “Login With Discourse” link. For this approach, make sure the Object Cache is disabled for anonymous users.

Another solution is outlined here: Wordpress SSO Expired nonce - #15 by simon. The function in that post can by copied exactly as it is into your WordPress theme’s functions.php file.

That function adds a randomly string to the Login With Discourse URL. The random string triggers WordPress to break the cache and generate a fresh nonce for the user. @angus, this should probably get added to the plugin’s code: https://github.com/discourse/wp-discourse/blob/main/lib/sso-client/sso-client-base.php#L77. There’s no downside to it, and I don’t think there’s another way of dealing with object caching causing stale nonces to be used instead of generating new ones for each visit.

3 Likes

Thanks a lot for the response. Once we launch Discourse into live operation, we will try to disable the Nging cache on the WordPress site and if that doesn’t work we will edit the functions.php according to the instructions.

Thanks @simon!

I’m a little unclear as to why this would clear Wordpress’ object cache, as typically adding a random string to a url is used to avoid the browser’s cache. Which query is being cached in Wordpress’ object cache? I’m seeing a non-object-cache reason why that approach might work

However if that’s the case we may need a slightly different tweak. But perhaps I’m missing something?

The problem isn’t with the WordPress object cache, as far as I know it’s not persistent across requests. The problem happens with sites that have some kind of persistent caching: https://developer.wordpress.org/reference/classes/wp_object_cache/#persistent-caching. This can be configured through a plugin, but it’s also enabled by default by some hosting providers, for example WP Engine. I think for the case of WP Engine, they don’t enable the object cache on their login page, but they do enable it for anonymous users on all other pages. So on WP Engine the problem is only triggered if the “login with Discourse” link is added to a page other than the login page.

The problem with the discourse_sso_url is that when it’s always set to the same value, for sites that have a persistent cache enabled, it will always return the same nonce. Setting its discourse_sso value to a random string, instead of setting it to its default value of 1 breaks the cache. At least it’s always worked that way when I’ve tested it previously. I don’t have things configured to test it at the moment.

Edit: there are a few more details about the issue here: Discourse (as provider) + WP SSO nonce error - #14 by simon. It’s quite a while since I looked at this. The fix for the issue at the time seemed to be to both add a random string to the discourse_sso_url and to ensure that page caching wasn’t enabled on the page the login link was displayed on (otherwise, the random string won’t be unique for each visit by an anonymous user.)

I see. Thanks for the explanation.

I think we should perhaps take this one step at a time, as I’m wary of pushing a fix here without being sure it’ll be “pluralistic”, i.e. that it will work with different caching approaches.

I’m also still a little unclear as to the role of the various caches in causing this specific issue, in particular the differing roles of persistent object and page caches (if they’re present). I can see why a page cache might cause this issue, but not a persistent object cache (yet). If it’s the latter, we may want to tweak the queries in our Nonce class instead.

I’ll need to test this in a bit more depth next week.

@Petr_Mišák Could you please first try disabling any page caching you have on the page with the login link and let us know how you go with that?

I will try to disable our Nginx Microcache for a test login page on WordPress. Our test page where we login to WordPress through Discourse is here Test Discourse Login | Svět Androida

I have (occasionally) noticed the problem if I use Google login to log in.
SnĂ­mek obrazovky 2023-11-14 132812

But now I’m surprised that the Discourse login links that we put on the page using the shortcode have disappeared from our test page.

Anyone have any idea why this is happening

Until I solve the problem with the test login page, I have no “expired nonce” to test it.

Please first make sure there isn’t some kind of caching issue. Let us know how you go with that.

I understand, we will solve it step by step, I agree.

It seems that the error also occurs with the official login. Here is an email to simulate it so you can try it yourself.

  1. go to the page Přihlásit se ‹ Svět Androida — WordPress
  2. log in using “Log in with Discourse” and use your Google account there
  3. after logging in Discourse, you will be redirected back to https://www.svetandroida.cz/ or https://www.svetandroida.cz/wp-login.php with an error message, see screenshot.

It’s poorly tested because the problem doesn’t always show up.
Please try and let me know if you get the error before I disable Nginx Cache. Thanks

1 Like

I checked the status of our Nginx Microcache at Přihlásit se ‹ Svět Androida — WordPress, but it seems that Nginx Microcache is not used there at all. The problem with the “expired nonce” will therefore be related to something else.

1 Like

Hey @Petr_Mišák just checking if you managed to find the culprit for this?