Привет , я написал этот модуль аутентификации SimpleSAMLphp, чтобы использовать Discourse в качестве провайдера SSO в установке SimpleSAMLphp. То есть вы можете использовать Discourse как провайдера SSO для любых сервисов, поддерживающих аутентификацию через SAML или Shibboleth, что очень удобно.
Дайте знать, что вы думаете (если хотите прокомментировать код, используйте GitHub Issues).
Это отлично! Если вы хотите сделать модуль более заметным, вы можете создать тему о нём в нашей категории #plugin:extras. Эта категория представляет собой каталог всех расширений и интеграций для Discourse, которые не являются плагинами Discourse.
Я внедряю эту систему единого входа (SSO) на существующем веб-сайте и просто хочу узнать, как люди «представляют» пользователям свой метод входа.
Например, допустим, на моём сайте www.example.com в верхнем меню есть кнопка «Войти».
Должна ли эта кнопка сразу перенаправлять пользователей на страницу аутентификации входа в Discourse? Или предпочтительнее сначала показать информационную страницу или модальное окно, что-то вроде:
Меня просто интересует, не запутаются ли пользователи, если им не сказать, что сейчас произойдёт?
У кого-нибудь есть опыт работы с пользователями или лучшие практики, которыми можно поделиться?
И кстати, большое спасибо @techAPJ за очень подробный первый пост в этой теме. Следуя вашим инструкциям, я смог успешно внедрить это в свой веб-сайт на ASP.NET с нуля
Возможно ли добавить параметр состояния, который возвращается без изменений, как это делается в OAuth? Middleware аутентификации в ASP.NET Core полагается на генерацию корреляционного идентификатора для предотвращения CSRF-атак, и у меня сейчас нет простого способа включить его.
@jessicah Я попробовал это сегодня, и да, всё работает отлично.
' Создаем URL возврата
Dim strReturnURL As String = "https://www.example.com/authtestRETURNURL.aspx?myownparametershere=surewhynot"
' Генерируем случайный nonce. Временно сохраняем его, чтобы можно было проверить по возвращенному значению nonce
Dim strNonce As String = Guid.NewGuid().ToString("N")
' Создаем новую полезную нагрузку (payload) с nonce и URL возврата (куда Discourse перенаправит пользователя после проверки)
' Полезная нагрузка должна выглядеть так: nonce=NONCE&return_sso_url=RETURN_URL
Dim strPayload As String = "nonce=" & strNonce & "&return_sso_url=" & strReturnURL
Затем на странице, которая вызывается обратно, вы найдете это внутри вашей декодированной SSO-строки запроса:
Мульти-сайтовые подходы к использованию discourse-auth-proxy?
Есть ли примеры или рекомендации по использованию Discourse в качестве провайдера SSO для аутентификации на нескольких сайтах?
Похоже, что существует два основных подхода для мульти-сайтов:
Использование нескольких экземпляров discourse-auth-proxy, по одному для каждого защищенного сайта.
Использование одного экземпляра discourse-auth-proxy, так что полезная нагрузка, содержащая return_sso_url, меняется в зависимости от источника запроса на вход.
Я думаю, что любой из этих вариантов может сработать, но проблема с этими двумя подходами заключается в том, что вам все равно потребуется вход на каждый отдельный сайт.
Также существует риск того, что что-то, хранящееся в Postgres, будет перезаписываться при каждом входе с разных сайтов. Например: site1.com, site2.com.
(Я не знаю деталей схемы аутентификации Discourse/PG, поэтому не уверен).
Идеальным вариантом был бы способ выполнить вход один раз, что позволит авторизоваться на всех сайтах в группе мульти-сайтов. Например: site1.com, site2.com, site3.com.
Похоже, что Stackoverflow реализует это с помощью комбинации локального хранилища Session и Iframe как основного механизма. техническое описание
Но я бы очень хотел узнать, реализовал ли кто-либо какой-либо подход к входу на нескольких сайтах с использованием Discourse в качестве провайдера SSO.
Подход 1: несколько экземпляров discourse-auth-proxy
Подход 2: модифицированный discourse-auth-proxy, влияющий на return_sso_url в полезной нагрузке.
Подход 3: реализация #1 или #2 таким образом, чтобы вход один раз означал, что вам не нужно входить снова при переходе с site1.com на site2.com.
Я отмечаю вас @sam, так как вы изначально написали программу discourse-auth-proxy на Go.
Проблема в том, что возвращаемый URL обрабатывается функцией urldecode в PHP (это основной рабочий процесс аутентификации MediaWiki), и значение wpLoginToken неожиданно меняется с 123+\ на 123 \.
Кажется, я нашёл причину:
Похоже, что клиент и сервер реализуют кодирование/декодирование, но следуют разным спецификациям.
Я не прошу Discourse что-то менять, а ищу совет, как решить эту проблему.
Спасибо.
Редактирование:
Я решил это, просто дважды закодировав знак + с помощью urlencode.
Я сейчас это тестирую. Я отправил вам два pull-запроса на GitHub: один для обновления документации и один для исправления ошибки, с которой я столкнулся.
Поскольку параметры поставщика и непоставщика предназначены для противоположных сценариев использования — когда Discourse управляет пользователями для чего-то другого, и наоборот, когда что-то другое управляет пользователями для Discourse — их совместное отображение может привести к ошибочной конфигурации. Было бы менее запутанно, если бы два параметра поставщика шли подряд и располагались либо полностью до, либо полностью после параметров непоставщика.
@techAPJ Можно ли использовать это с AWS Cognito? Я хочу создать приложение в AWS Amplify для своего сообщества Discourse и настроить аутентификацию моего приложения через Discourse.
@mdoggydog Спасибо за недавнее обновление расширения MediaWiki DiscourseSsoConsumer. Мы долго размышляли, как решить проблему, когда пользователи выходят из нашей вики, не выходя из Discourse. Настройка $wgPluggableAuth_EnableAutoLogin точно не подходила, так как она блокирует анонимный доступ к вики. Добавленная вами настройка $wgDiscourseSsoConsumer_AutoRelogin — это именно то, что нам было нужно.
Я пытаюсь использовать пример на PHP из оригинального поста, но способ, которым они хранят данные, кажется мне бессмысленным. Они просто сохраняют значения в базе данных SQL с ключами login и nonce. Если я хочу использовать SQL для хранения nonce, как именно должна выглядеть моя база данных?
Дополнительная информация, которая может помочь: для чего я это использую. Я надеюсь связать пользователя Discourse с аккаунтом Minecraft, сгенерировав ссылку SSO, привязанную к их UUID. После успешного входа через Discourse я планирую сохранить их UUID и ID пользователя Discourse в таблице.
На данный момент мне удалось заставить пример на PHP работать, но, похоже, я до конца не понимаю, как именно мне нужно его изменить, чтобы он подходил для моего случая. В идеале я хочу генерировать ссылку через GET-запрос и отправлять её пользователю, чтобы UUID уже был связан с nonce.
Спасибо за этот пост, без него я был бы ещё больше в тупике!
Редактирование: Не лучше ли мне просто хранить nonce в таблице и искать их по этому значению? Я знаю, что мне нужно сопоставить nonce, но, если я не могу передать дополнительную информацию через URL перенаправления (что мне пока не удаётся), я не уверен, как правильно ссылаться на nonce.
Я удалил часть значения параметра sso, которое вы предоставили. Если бы кто-то не знал ваш секретный ключ, он не смог бы декодировать это значение, но всё же было безопаснее не раскрывать его полностью. Это не связано с ошибкой 502, которую вы получаете.
Похоже, это ошибка базы данных. Я пробовал тот же плагин и конфигурацию на другом сайте Discourse, и там всё работает. Как можно исправить эту проблему?
Похоже, что попытка аутентификации в discourse-auth-proxy с именами пользователей или групп, содержащими не-ASCII символы (в моём случае — китайские), приводит к ошибке, поскольку куки не могут содержать такие символы. Вот моё решение (предупреждение: я не очень хорошо знаком с golang):
diff --git a/main.go b/main.go
index 1b1dc28..18f8c9e 100644
--- a/main.go
+++ b/main.go
@@ -154,7 +154,12 @@ func redirectIfNoCookie(handler http.Handler, r *http.Request, w http.ResponseWr
var username, groups string
if err == nil && cookie != nil {
- username, groups, err = parseCookie(cookie.Value, config.CookieSecret)
+ var value string
+ value, err = url.QueryUnescape(cookie.Value)
+ if err != nil {
+ return
+ }
+ username, groups, err = parseCookie(value, config.CookieSecret)
}
if err == nil {
@@ -224,7 +229,7 @@ func redirectIfNoCookie(handler http.Handler, r *http.Request, w http.ResponseWr
cookieData := strings.Join([]string{username, strings.Join(groups, "|")}, ",")
http.SetCookie(w, &http.Cookie{
Name: cookieName,
- Value: signCookie(cookieData, config.CookieSecret),
+ Value: url.QueryEscape(signCookie(cookieData, config.CookieSecret)),
Expires: expiration,
HttpOnly: true,
Path: "/",