Клиент WordPress DiscourseConnect: истёкший nonce

Я столкнулся с той же проблемой, и она возникает при входе через Google. До WordPress мы использовали Nginx в качестве обратного прокси. Может ли это быть связано?

Я предполагаю, что проблема возникает при входе в WordPress через ваш сайт Discourse. Если это так, то дело в том, что nonce, сгенерированный WordPress, устарел. Это происходит на сайтах WordPress, где включено объектное кэширование.

Одно из решений — отключить объектное кэширование на всех страницах, содержащих ссылку «Войти через Discourse». При таком подходе убедитесь, что объектное кэширование отключено для анонимных пользователей.

Другое решение описано здесь: Wordpress SSO Expired nonce - #15 by simon. Функцию из того сообщения можно скопировать в точности как есть в файл functions.php вашей темы WordPress.

Эта функция добавляет случайную строку к URL «Войти через Discourse». Случайная строка заставляет WordPress сбросить кэш и сгенерировать для пользователя новый nonce. @angus, это, вероятно, стоит добавить в код плагина: wp-discourse/lib/sso-client/sso-client-base.php at main · discourse/wp-discourse · GitHub. В этом нет никаких недостатков, и я не думаю, что существует другой способ решить проблему, когда объектное кэширование приводит к использованию устаревших nonce вместо генерации новых при каждом посещении.

Большое спасибо за ответ. Как только мы запустим Discourse в рабочем режиме, мы попробуем отключить кеш Nginx на сайте WordPress, а если это не поможет, внесем изменения в functions.php согласно инструкциям.

Спасибо, @simon!

Я немного не понимаю, почему это должно очищать объектный кэш WordPress, так как обычно добавление случайной строки к URL используется для обхода кэша браузера. Какой именно запрос кэшируется в объектном кэше WordPress? Я вижу причину, по которой этот подход может сработать, которая не связана с объектным кэшем.

Однако, если это так, возможно, нам потребуется немного другая корректировка. Но, возможно, я что-то упускаю?

Проблема не в объектном кэше WordPress, насколько мне известно, он не сохраняется между запросами. Проблема возникает на сайтах, где используется какой-либо вид постоянного кэширования: https://developer.wordpress.org/reference/classes/wp_object_cache/#persistent-caching. Это можно настроить через плагин, но также оно включено по умолчанию у некоторых хостинг-провайдеров, например, WP Engine. Насколько я понимаю, в случае с WP Engine объект-кэш не включен на их странице входа, но включен для анонимных пользователей на всех остальных страницах. Таким образом, на WP Engine проблема возникает только если ссылка «Войти через Discourse» добавлена на страницу, отличную от страницы входа.

Проблема с discourse_sso_url заключается в том, что когда он всегда установлен в одно и то же значение, для сайтов с включенным постоянным кэшированием он всегда будет возвращать один и тот же nonce. Установка его значения discourse_sso в случайную строку вместо значения по умолчанию 1 нарушает работу кэша. По крайней мере, так всегда работало в моих предыдущих тестах. В данный момент у меня нет возможности проверить это.

Редакция: здесь есть ещё несколько деталей по этой проблеме: Discourse (as provider) + WP SSO nonce error - #14 by simon. Прошло уже довольно много времени с тех пор, как я смотрел на это. Исправление проблемы на тот момент заключалось в том, чтобы одновременно добавить случайную строку в discourse_sso_url и убедиться, что кэширование страниц не включено на странице, где отображается ссылка входа (иначе случайная строка не будет уникальной для каждого посещения анонимным пользователем).

Понятно. Спасибо за объяснение.

Я думаю, что нам стоит двигаться постепенно, так как я не хочу внедрять исправление, не будучи уверенным, что оно будет «универсальным», то есть будет работать с различными подходами к кэшированию.

У меня всё ещё есть некоторая неясность в отношении роли различных кэшей в возникновении этой конкретной проблемы, в частности, в различии ролей кэша постоянных объектов и кэша страниц (если они используются). Я понимаю, почему кэш страниц может вызывать эту проблему, но пока не вижу, как это может быть связано с кэшем постоянных объектов. Если дело во втором, возможно, нам стоит доработать запросы в нашем классе Nonce.

На следующей неделе мне нужно будет провести более глубокое тестирование.

@Petr_Mišák Не могли бы вы сначала попробовать отключить любое кэширование страниц на странице со ссылкой для входа и сообщить нам, как это сработает?

Я попробую отключить наш Nginx Microcache для тестовой страницы входа в WordPress. Наша тестовая страница, где мы входим в WordPress через Discourse, находится здесь: Test Discourse Login | Svět Androida

Я (иногда) замечал эту проблему, если использую вход через Google.

Но теперь я удивлён, что ссылки на вход в Discourse, которые мы разместили на странице с помощью шорткода, исчезли с нашей тестовой страницы.

У кого-нибудь есть идея, почему это происходит?

Пока я не решу проблему со страницей тестового входа, у меня нет «истёкшего nonce» для проверки.

Сначала убедитесь, что проблема не в кэшировании. Дайте нам знать, как у вас получится.

Понял, мы решим это пошагово, согласен.

Похоже, ошибка возникает и при использовании официального входа. Вот инструкция для симуляции, чтобы вы могли проверить это самостоятельно:

  1. Перейдите на страницу Přihlásit se ‹ Svět Androida — WordPress
  2. Войдите, используя «Войти через Discourse», и авторизуйтесь через свой аккаунт Google.
  3. После входа в Discourse вас перенаправит обратно на https://www.svetandroida.cz/ или https://www.svetandroida.cz/wp-login.php с сообщением об ошибке, см. скриншот.

Тестирование проведено недостаточно тщательно, так как проблема проявляется не всегда.
Пожалуйста, попробуйте и сообщите, появится ли ошибка, прежде чем я отключу Nginx Cache. Спасибо.

Я проверил статус нашего Nginx Microcache по адресу Přihlásit se ‹ Svět Androida — WordPress, но, похоже, Nginx Microcache там вообще не используется. Следовательно, проблема с «истёкшим nonce» связана с чем-то другим.

Привет @Petr_Mišák, просто проверяю, удалось ли тебе найти виновника этого?

Мы провели поиск, но, к сожалению, пока безрезультатно. Однако мы продолжим поиск и постараемся выяснить причину проблемы.

Я почти уверен, что проблема с входом в систему на https://www.svetandroida.cz/ через Discourse связана с кэшированием nonce. Я проверял это, нажимая на ссылку «Войти через Discourse» (https://www.svetandroida.cz/?discourse_sso=1&redirect_to=https%3A%2F%2Fwww.svetandroida.cz%2F).

В первый раз меня перенаправило на https://komunita.svetandroida.cz/, я создал аккаунт на сайте Discourse с помощью Gmail, а затем вернулся на ваш сайт WordPress уже как авторизованный пользователь.

Затем я вышел из аккаунта на вашем сайте WordPress и попытался войти снова, нажав на ссылку «Войти через Discourse». На этот раз я получил ошибку «истекший nonce».

После этого я сгенерировал ссылку для входа со случайным значением параметра URL discourse_sso, например https://www.svetandroida.cz/?discourse_sso=181253058&redirect_to=https%3A%2F%2Fwww.svetandroida.cz%2F, и смог войти в ваш сайт WordPress через Discourse без каких-либо проблем.

Я пробовал это несколько раз, как со ссылкой для входа, сгенерированной плагином (https://www.svetandroida.cz/?discourse_sso=1&redirect_to=https%3A%2F%2Fwww.svetandroida.cz%2F), так и со ссылками для входа со случайным значением параметра discourse_sso. Похоже, что возвращаемый nonce кэшируется как минимум несколько минут.

Без полной отладки проблемы я почти уверен, что вы можете заставить всё работать, просто добавив следующее в файл functions.php вашей темы (это установит случайную строку в параметр URL discourse_sso. Это должно сработать, если на странице входа не включено также «кэширование страниц».)

add_filter('wpdc_sso_client_query', 'wpdc_custom_sso_client_query' );
function wpdc_custom_sso_client_query() {
    return wp_generate_password( 12, false );
}

Если вы всё же хотите отладить проблему, вот что я вижу для успешного запроса. Обратите внимание на строку Cache-Svetzitrka: STALE. Это может указывать на то, что есть дополнительный слой кэширования и что кэш был STALE для успешного запроса (поэтому был сгенерирован новый nonce.)

Сводка
Request URL:
https://www.svetandroida.cz/?discourse_sso=1&redirect_to=https%3A%2F%2Fwww.svetandroida.cz%2F
Request Method:
GET
Status Code:
302 Found
Remote Address:
93.185.102.156:443
Referrer Policy:
strict-origin-when-cross-origin
Cache-Control:
max-age=0
Cache-Svetzitrka:
STALE
Content-Length:
0
Content-Type:
text/html; charset=UTF-8
Date:
Mon, 11 Dec 2023 09:38:05 GMT
Expires:
Mon, 11 Dec 2023 09:21:47 GMT
Location:
https://komunita.svetandroida.cz/session/sso_provider?sso=bm9uY2U9MGU3NTNjYWNhNjMwNmMzNzM5M2MyODk4MjZlYzMxMjQmcmV0dXJuX3Nzb191cmw9aHR0cHMlM0ElMkYlMkZ3d3cuc3ZldGFuZHJvaWRhLmN6JTJG&sig=32ddcc85bd2dd7175f963e791cc9ac734a607355d773422d3abec6173c9f656b
Server:
nginx
Strict-Transport-Security:
max-age=10886400; includeSubdomains; preload
X-Content-Type-Options:
nosniff
X-Frame-Options:
SAMEORIGIN
X-Redirect-By:
WordPress

А вот что я вижу для неудачного запроса. Строка Cache-Control: no-cache, no-store кажется указывающей на то, что ответ не должен кэшироваться, но запись from service worker в ответе указывает на то, что ответ может поступать из кэша сервис-воркера.

Сводка
Request URL:
https://www.svetandroida.cz/?discourse_sso=1&redirect_to=https%3A%2F%2Fwww.svetandroida.cz%2F
Request Method:
GET
Status Code:
302 Found (from service worker)
Referrer Policy:
strict-origin-when-cross-origin
Cache-Control:
no-cache, no-store
Content-Security-Policy:
upgrade-insecure-requests; base-uri 'self'; object-src 'none'; script-src https://komunita.svetandroida.cz/logs/ https://komunita.svetandroida.cz/sidekiq/ https://komunita.svetandroida.cz/mini-profiler-resources/ https://komunita.svetandroida.cz/assets/ https://komunita.svetandroida.cz/extra-locales/ https://komunita.svetandroida.cz/highlight-js/ https://komunita.svetandroida.cz/javascripts/ https://komunita.svetandroida.cz/plugins/ https://komunita.svetandroida.cz/theme-javascripts/ https://komunita.svetandroida.cz/svg-sprite/ https://www.google-analytics.com/analytics.js https://www.googletagmanager.com/gtag/js 'sha256-8uAKDaK4QxxCeYZl0Wxad2Nnj2tgKyA14hYBh66pnn0='; worker-src 'self' https://komunita.svetandroida.cz/assets/ https://komunita.svetandroida.cz/javascripts/ https://komunita.svetandroida.cz/plugins/; frame-ancestors 'self'; manifest-src 'self'
Content-Type:
text/html; charset=utf-8
Date:
Mon, 11 Dec 2023 09:38:05 GMT
Discourse-Logged-Out:
1
Location:
https://komunita.svetandroida.cz/login
Referrer-Policy:
strict-origin-when-cross-origin
Server:
nginx
Set-Cookie:
sso_payload=sso%3Dbm9uY2U9MGU3NTNjYWNhNjMwNmMzNzM5M2MyODk4MjZlYzMxMjQmcmV0dXJuX3Nzb191cmw9aHR0cHMlM0ElMkYlMkZ3d3cuc3ZldGFuZHJvaWRhLmN6JTJG%26sig%3D32ddcc85bd2dd7175f963e791cc9ac734a607355d773422d3abec6173c9f656b; path=/; SameSite=Lax
Set-Cookie:
_forum_session=kGW2K6gafsjS90qQMEmxzjggEYo4tZPZe76XZNVro34ilyuuHsaYt2nEzC9h6tfiSBmY9XoDdxh1SV3S8n%2BwqrbsD58UvJBz6khjm%2Fty83ufkgry8daHDdyoTfFwQOjAbXrWeGIwkS4edGY1XetNwXhu%2FNJUghqmq8BEUycBt7098KUO%2BmRYDl5iSL0FNhUzo5Hc7xwRg0tfxuxmb%2FIyVLnbFz6IJuGB3Y95PRcU5DYIwAAny1GQbKQ23kSjgALxAThG7aA%2B7LCI9cJNWV1JRSy%2FTElDN3iugKuVpaQcrSPhV3SvQaiNH3MCfLwu6yxlp%2BZ%2BwTyw22czX8bb197z36WhlbghYtxvKYGRjONJQUagisjPpMrCAcGeTKsGB4JgnUKCtlrwIoFvaDxjec7hMo3aCnibbbkmcxWc6LvD6G2xaxkDgebe7RpvfTYdG8cn8j6rNwX3hM8la4RqZnmma0%2FQlSrfj0BjfY7lnan6TYm28vLwH%2FFfdZoRbo6JdTs5AFjCJvx9UXSjFmoXHH1R1yfAizPeKDFnpiuUs4a%2FBzWafQ%3D%3D--8PEvbWwpqBuJMSRJ--CzzhBea4mmv58a7KLEnukw%3D%3D; path=/; secure; HttpOnly; SameSite=Lax
Set-Cookie:
_t=; path=/; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax
Strict-Transport-Security:
max-age=31536000
Vary:
Accept
X-Content-Type-Options:
nosniff
X-Discourse-Route:
session/sso_provider
X-Download-Options:
noopen
X-Frame-Options:
SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
none
X-Request-Id:
001750b9-94f2-4bf0-8503-9d673463b91e
X-Runtime:
0.012335
X-Xss-Protection:
0