Hola , he escrito este módulo de autenticación SimpleSAMLphp para poder usar Discourse como proveedor de SSO dentro de una instalación de SimpleSAMLphp. Es decir, puedes usar Discourse como proveedor de SSO para cualquier servicio que admita autenticación SAML o Shibboleth, lo cual es realmente útil.
Cuéntame qué te parece (si te interesa comentar sobre el código, puedes usar los Issues de GitHub).
¡Eso es genial! Si deseas hacer el módulo más visible, podrías crear un tema sobre él en nuestra categoría #plugin:extras. Esa categoría es un directorio de todas las extensiones e integraciones para Discourse que no son plugins de Discourse.
Estoy implementando este SSO en un sitio web existente y solo quiero consultar cómo la gente “presenta” su método de inicio de sesión a los usuarios.
Por ejemplo, supongamos que mi sitio web en www.example.com tiene un botón de Inicio de sesión en la barra de navegación superior.
¿Debería ese botón de inicio de sesión llevar inmediatamente a las personas a mi página de autenticación de inicio de sesión de Discourse? ¿O es preferible mostrar primero una página o un modal con información, algo como esto:
Me pregunto si la gente se confundirá si no se les dice qué está a punto de suceder.
¿Alguien tiene alguna experiencia de usuario o mejores prácticas que compartir?
Y por cierto, gracias también a @techAPJ por la publicación inicial muy detallada en este hilo. Logré implementar esto en mi sitio web ASP.NET desde cero siguiendo tus pasos.
¿Es posible incluir un parámetro de estado que se devuelva sin cambios, como se hace en OAuth? El middleware de autenticación de ASP.NET Core depende de generar un ID de correlación para prevenir ataques CSRF, y actualmente no tengo una forma sencilla de incluirlo.
@jessicah Lo probé hoy y sí, funciona correctamente.
' Crear una URL de retorno
Dim strReturnURL As String = "https://www.example.com/authtestRETURNURL.aspx?myownparametershere=surewhynot"
' Generar un nonce aleatorio. Guárdalo temporalmente para poder verificarlo con el valor de nonce devuelto
Dim strNonce As String = Guid.NewGuid().ToString("N")
' Crear una nueva carga útil con el nonce y la URL de retorno (a donde Discourse redirigirá al usuario tras la verificación)
' La carga útil debería verse así: nonce=NONCE&return_sso_url=RETURN_URL
Dim strPayload As String = "nonce=" & strNonce & "&return_sso_url=" & strReturnURL
Luego, en la página que se llama de nuevo, encontrarás esto dentro de tu cadena de consulta SSO decodificada:
Enfoques multi-sitio para el uso de discourse-auth-proxy?
¿Existen ejemplos o recomendaciones para utilizar Discourse como proveedor de SSO para la autenticación multi-sitio?
Parece que hay dos enfoques básicos multi-sitio:
Usar múltiples instancias de discourse-auth-proxy, una por cada sitio protegido.
Usar una única instancia de discourse-auth-proxy de modo que la carga útil que contiene return_sso_url cambie según el origen de la solicitud de inicio de sesión.\n
Creo que cualquiera de estos podría funcionar, pero el problema con estos dos enfoques es que aún se requiere iniciar sesión en cada sitio diferente.
También existe el riesgo de que algo se almacene en Postgres y sea sobrescrito por cada inicio de sesión desde los diferentes sitios. Es decir: site1.com, site2.com.
(No conozco los detalles del esquema de autenticación de Discourse/PG, así que no lo sé).
Lo ideal sería tener una forma de realizar el inicio de sesión una sola vez, lo que te mantendría conectado en todos los sitios del grupo multi-sitio. Es decir, site1.com, site2.com, site3.com.
Aparentemente, Stackoverflow hace esto utilizando una combinación de almacenamiento local sessionStorage y Iframes como habilitador principal. descripción técnica
Pero me encantaría saber si alguien ha implementado algún enfoque para el inicio de sesión multi-sitio utilizando Discourse como proveedor de SSO.
enfoque 1: múltiples instancias de discourse-auth-proxy
enfoque 2: discourse-auth-proxy modificado que afecta return_sso_url en la carga útil.
enfoque 3: #1 o #2 implementados de tal manera que iniciar sesión una vez significa que no tienes que iniciar sesión nuevamente al moverte de site1.com a site2.com
Te etiqueto @sam, ya que fuiste el autor original del programa Go discourse-auth-proxy.
El problema es que la URL de retorno será procesada por la función urldecode en PHP (que es el flujo de trabajo central en la autenticación de MediaWiki), y el valor de wpLoginToken cambiará de manera inesperada de 123+\\ a 123 \\.
Parece que he encontrado la causa:
Bueno, el cliente y el servidor implementan la codificación/decodificación pero siguen especificaciones diferentes.
No estoy pidiendo a Discourse que cambie algo, sino que busco consejos para resolver esto.
Gracias.
Edición:
Lo resolví simplemente codificando el signo + dos veces.
En Configuración > Inicio de sesión, las dos configuraciones de proveedor de DiscourseConnect no son consecutivas y aparecen intercaladas con las configuraciones de DiscourseConnect:
Dado que las configuraciones de proveedor y las de no proveedor son para casos de uso opuestos: usar Discourse para gestionar usuarios de otra cosa versus usar otra cosa para gestionar usuarios de Discourse, mostrar estas configuraciones mezcladas invita a una mala configuración. Sería menos confuso si las dos configuraciones de proveedor fueran consecutivas y estuvieran completamente antes o completamente después de las configuraciones de no proveedor.
@techAPJ ¿Se puede usar esto con AWS Cognito? Quiero crear una aplicación en AWS Amplify para mi comunidad de Discourse y deseo que mi aplicación se autentique a través de Discourse.
@mdoggydog Gracias por la reciente actualización de la extensión MediaWiki DiscourseSsoConsumer. Habíamos estado dándole vueltas a qué hacer con los usuarios que se desconectaban de nuestra wiki sin haberse desconectado de Discourse, y $wgPluggableAuth_EnableAutoLogin definitivamente no era lo que queríamos, ya que impide el acceso anónimo a la wiki. La configuración $wgDiscourseSsoConsumer_AutoRelogin que añadiste es exactamente lo que necesitábamos.
Estoy intentando usar el ejemplo de PHP de la publicación original, pero la forma en que almacenan las cosas no tiene sentido. Simplemente almacenan valores en una base de datos SQL con las claves login y nonce. Si quiero usar SQL para almacenar los nonces, ¿cómo se vería exactamente mi base de datos SQL?
Otra información que podría ayudar es para qué estoy usando esto: espero vincular un usuario de Discourse a una cuenta de Minecraft generando un enlace SSO que esté vinculado a su UUID. Al iniciar sesión correctamente con Discourse, almacenaré su UUID y su ID de Discourse en una tabla.
Hasta ahora, pude hacer que el ejemplo de PHP funcione, pero supongo que no entiendo completamente cómo tendría que modificarlo para que funcione para mi caso de uso. Idealmente, quiero generar el enlace a través de una solicitud GET y enviárselo al usuario, de modo que el UUID ya esté asociado con el nonce.
¡Gracias por esta publicación, ya que estaría aún más perdido sin ella!
Edición: Para los nonces, ¿sería mejor almacenar los nonces en la tabla y buscar por ellos? Sé que necesito hacer coincidir el nonce, pero, a menos que pueda pasar información adicional en la URL de redirección (lo cual no he logrado hacer), no estoy seguro de cómo referenciar el nonce correctamente.
Eliminé parte del valor del parámetro sso que habías proporcionado. A menos que alguien conociera tu clave secreta, no podría decodificar el valor, pero aun así me pareció más seguro no proporcionar el valor completo. No estará relacionado con el error 502 que estás recibiendo.
Parece un error de base de datos. Porque probé el mismo plugin y configuración en otro sitio web de Discourse, y está funcionando. ¿Cómo puedo solucionar este problema?
Parece que intentar autenticarse en discourse-auth-proxy con nombres de usuario o grupos no ASCII (chino en mi caso) genera un error porque las cookies no pueden contener estos caracteres. Esta es mi solución: (descargo de responsabilidad: no estoy muy familiarizado con 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: "/",