Hola, me han informado de que varios miembros de mi foro se están desconectando automáticamente después de 20-30 minutos.
Uso SSO, por lo que me pregunto si el problema podría estar relacionado con que inicien sesión en el sitio principal, luego accedan a Discourse (¿se inicia una nueva sesión allí?), vuelvan al sitio principal (lo que significa que Discourse está inactivo) y luego regresen a Discourse y, de alguna manera, se desconecten.
(Aunque eso no tiene mucho sentido, porque cada vez que entran en Discourse, debería restablecer el “tiempo de espera por inactividad” a 0, ¿verdad?)
Encontré algunos hilos sobre tiempos de espera, etc., aquí en meta, pero ninguno parece tener una respuesta clara.
Pregunta: ¿Existe una configuración para evitar que los miembros se desconecten hasta que hayan estado inactivos durante un período X? No logro encontrarla.
Veo en la configuración de Discourse que tengo la “edad máxima de la sesión” establecida en 1 hora, pero no creo que eso marque mucha diferencia con una implementación de SSO, ¿verdad? (Nota: cuando un miembro se desconecta en mi sitio principal, envío un mensaje /logout a Discourse, solo para mantener todo ordenado. Y cada vez que un miembro realiza cualquier actividad en Discourse, actualizo el tiempo de última actividad en mi sitio principal, por lo que no es el sitio principal el que se agota el tiempo. Estoy agregando código de depuración adicional ahora para confirmar que todo esto funciona como debería.)
Sí se aplica a SSO, por lo que probablemente esa sea la fuente de tu problema. Después de 1 hora de inactividad, la sesión de Discourse se terminará y los usuarios tendrán que volver a autenticarse con SSO.
Está bien, y es totalmente aceptable… tras 1 hora de inactividad, deberían cerrar sesión.
El problema es que estoy recibiendo informes de personas que son desconectadas después de 20-30 minutos.
¿Existe una configuración para ese tiempo de espera inactivo de 1 hora? Como mencioné en mi publicación original, no puedo encontrarla… y parece ser el primer lugar para verificar, ¿no?
Solo para descartar la causa más obvia… ¿es posible que la gente se equivoque con la hora exacta? 30 minutos y 1 hora no son tan diferentes
Para continuar con la depuración, sugiero que el siguiente paso sea revisar los datos disponibles en las tablas user_auth_tokens y user_auth_token_logs. Estas contienen toda la información sobre los tokens de sesión y su expiración.
Hmm. A medida que la gente usa los foros y lee temas, etc., si realizan alguna acción que genere un evento (crear_publicación, crear_tema, editar_publicación, etc.), recibo un mensaje a través del webhook. Esto le indica al sitio principal que siguen activos, por lo que puedo actualizar el valor de ‘Último clic’ en su sesión, evitando que se cierren. Como debería ser. Todo bien.
Sin embargo, si un miembro solo está leyendo mensajes durante un tiempo… su tiempo de inactividad en Discourse se reinicia cada vez que hacen algo (lo cual es bueno), pero mi sitio principal nunca recibe mensajes del webhook que indiquen que el usuario está activo. Así que, tras una hora sin ninguna actividad (parece que fueron a los foros y se alejaron del ordenador), el sitio principal asume que ya no están y los cierra sesión.
Parece que hay un hueco en la lógica aquí. Para una implementación correcta de SSO, ¿no debería haber una forma de que Discourse me informe si la sesión de un usuario está activa (incluso si solo están leyendo)? Quizás Discourse debería enviar un ping cada 5 minutos si el miembro está activo pero no ha generado otros mensajes del webhook.
O tal vez, cuando mi sitio considera que un usuario ha expirado, debería llamar a Discourse y preguntar si el usuario está activo allí. ¿Existe alguna forma de hacerlo? (Veo Is there an endpoint to check if a user is logged in - #3 by pfaffman, pero no estoy seguro de si es lo que necesito, y /session/current.json no aparece en la documentación de la API.) Eso generaría una gran cantidad de llamadas a la API, aunque: cierro sesión a unos 15-20 usuarios cada minuto en mi sitio por inactividad, por lo que tendría que hacer una llamada por cada uno (y posiblemente más de una llamada, si no tengo una caché local de su ID de Discourse).
Cada punto final de perfil tiene un valor last_seen, que podrías utilizar.
No creo haber visto este tipo de configuración en ningún protocolo SSO, y no hemos recibido solicitudes para cosas como esta. Más comúnmente, las personas mantienen los dos sistemas independientes.
Si realmente quisieras crear un webhook para ‘usuario visto’, podrías hacerlo utilizando un plugin personalizado.
No estoy seguro de qué te refieres con mantener los dos sistemas independientes. Avísame si estoy pasando por alto alguna forma obvia de resolver el problema que he planteado, ¡por favor!
De lo contrario, parece que mis opciones son:
Cuando un usuario agote su tiempo de espera en el sitio principal, antes de cerrar su sesión, llama a Discourse y verifica el valor de last_seen para ver si el miembro ha estado realmente activo en los foros (simplemente no haciendo nada que genere una llamada de webhook). Ventajas: fácil de hacer. Desventajas: generará muchas llamadas a la API, algo con lo que ya estoy luchando y tratando de sortear los límites de tasa.
Crear mi propio plugin para hacer ping a mi sitio principal de vez en cuando, para que pueda actualizar la última actividad del usuario en mi sitio principal. Ventajas: se siente más como la solución “correcta” (indicar actividad con un mensaje push); algo elegante. Desventajas: no es fácil de implementar.
Cambiar el tiempo de cierre de sesión en mi sitio principal a 2 horas. Ventajas: fácil de implementar. Desventajas: ¿hay alguna?
No preocuparse por ello. Los usuarios son cerrados en medio de su sesión en Discourse y se quejan amargamente. Esto es lo que tengo ahora. Ventajas: fácil de implementar, jaja. Desventajas: una experiencia de usuario muy pobre.
¿He pasado por alto algo?
Parece que la opción #3 sería una buena respuesta, aunque necesito pensar en las repercusiones de tener un tiempo de cierre de sesión más largo en el sitio principal.
Todavía me gusta la opción #1 como la mejor elección, pero luego tengo que resolver cómo evitar tantos malditos problemas de límite de tasa. Ojalá hubiera una forma de desactivar globalmente todos los límites de tasa en Discourse (y en nginx, ya que estoy usando la instalación de Discourse con Docker), punto final. No necesito ninguno de ellos. Solo es mi sitio principal hablando con mi instancia de Discourse. No permito claves de API de usuario y soy el único con una clave de API del sistema. Es un sistema completamente cerrado y los límites de tasa solo están (constantemente) estorbando. Supongo que ese es un tema diferente.
Si necesitas mantener el comportamiento que describiste, entonces sí, creo que esas son las 4 opciones. Pero si modificas un poco el comportamiento, funcionará mejor con las herramientas disponibles.
Lo inusual de tu configuración es:
Estás cerrando la sesión de Discourse cada vez que la sesión caduca en tu sitio principal. Si eliminas esta parte, creo que la configuración coincidirá con las configuraciones típicas.
Aún podrías llamar a /logout cuando un usuario explícitamente cierra sesión en tu sitio principal. Solo no lo llames cuando la sesión caduca naturalmente.
No se puede saber por el autor original, pero ¿están ejecutando un sitio altamente especializado centrado en que las personas compartan información súper sensible, o donde la mayoría de los usuarios inician sesión desde computadoras públicas compartidas o algo así?
De lejos, la solución más simple aquí parece ser simplemente no ser hiperagresivo al expirar las sesiones de los usuarios y forzar el cierre de sesión. Mi preferencia como usuario es siempre “nunca cerrarme la sesión a menos que haga clic específicamente en cerrar sesión”. Si eso no es posible, ¿podrían al menos hacerlo por un día, una semana o algo así?
Entiendo, es una buena solución; creo que muchos de mis miembros usan la casilla “mantenerme conectado” en la página de inicio de sesión, por lo que sería fluido traerlos de vuelta al sitio principal. Si su sesión ha caducado en el sitio principal, se les volvería a conectar (de forma invisible) en ese mismo momento. Hmm.
Es un sitio para un segmento de la población que es muy sensible con la privacidad. Pero entiendo lo que dices y creo que podría simplemente hacer lo que tú (y David) sugieren.
Muchas gracias a ambos. No tenía una buena idea del “panorama general” aquí, ni de cómo otros sitios manejan este tipo de escenarios… ahora sí y veo algunas soluciones posibles para mi situación. ¡Muy agradecido!