Olá, estou recebendo informações de que vários membros do meu fórum estão sendo desconectados automaticamente após 20 a 30 minutos.
Como utilizo SSO, estou me perguntando se o problema pode estar relacionado ao fato de eles fazerem login no site principal, acessarem o Discourse (o que inicia uma nova sessão lá?), retornarem ao site principal (o que deixa o Discourse inativo) e, em seguida, voltarem ao Discourse e, de alguma forma, serem desconectados.
(Isso não faz muito sentido, pois, toda vez que eles acessam o Discourse, o “tempo limite de inatividade” deveria ser redefinido para 0 novamente, certo?)
Encontrei alguns tópicos sobre tempos limite etc. aqui no meta, mas nenhum deles parece ter uma resposta clara.
Pergunta: existe uma configuração para impedir que os membros sejam desconectados até ficarem inativos por um período X? Não consigo encontrá-la.
Vejo nas configurações do meu Discourse que tenho o “tempo máximo de sessão” definido para 1 hora, mas acho que isso não faz muita diferença com uma implementação de SSO, certo? (Observação: quando um membro faz logout no meu site principal, envio uma mensagem /logout para o Discourse, apenas para manter tudo organizado. E sempre que um membro realiza qualquer atividade no Discourse, atualizo o tempo da última atividade no meu site principal, para que não seja o site principal que está expirando. Estou adicionando código de depuração adicional agora para confirmar que tudo isso está funcionando como deveria.)
Isso se aplica ao SSO, então provavelmente essa é a origem do seu problema. Após 1 hora de inatividade, a sessão do Discourse será encerrada e os usuários terão que se autenticar novamente via SSO.
Isso é aceitável e está tudo bem… após 1 hora de inatividade, eles devem ser desconectados.
O problema é que estou recebendo relatos de pessoas sendo desconectadas após 20 a 30 minutos.
Existe uma configuração para esse tempo limite de inatividade de 1 hora? Como mencionei em minha postagem original, não consigo encontrá-la… e isso parece ser o primeiro lugar para verificar, não é?
Só para descartar a causa mais óbvia… é possível que as pessoas estejam confusas quanto ao horário exato? 30 minutos e 1 hora não são tão diferentes
Para continuar a depuração, sugiro que o próximo passo seja analisar os dados disponíveis nas tabelas user_auth_tokens e user_auth_token_logs. Elas contêm todas as informações sobre os tokens de sessão e sua expiração.
Hmm. Conforme as pessoas usam os fóruns e leem tópicos, etc., se elas realizam alguma ação que gera um evento (create_post, create_topic, edit_post, etc.), recebo uma mensagem via webhook. Isso informa ao site principal que elas ainda estão ativas, permitindo que eu atualize o valor de ‘Último Clique’ na sessão delas, evitando um logout. Como deveria ser. Tudo certo.
No entanto, se um membro estiver apenas lendo mensagens por um tempo… o tempo de inatividade no Discourse é reiniciado sempre que eles fazem algo (o que é bom), mas meu site principal nunca recebe mensagens de webhook indicando que o usuário está ativo. Assim, após 1 hora sem nenhuma atividade (parece que eles foram aos fóruns e se afastaram do computador), o site principal assume que eles saíram e os faz logout.
Parece haver uma falha na lógica aqui. Para uma implementação SSO adequada, não deveria haver uma maneira de o Discourse me informar se a sessão de um usuário está ativa (mesmo que eles estejam apenas lendo)? Talvez o Discourse devesse enviar um ping a cada 5 minutos se o membro estiver ativo, mas não tiver gerado outras mensagens de webhook.
Ou, talvez, quando meu site achar que um usuário expirou, eu deveria consultar o Discourse e perguntar se o usuário está ativo lá. Existe uma maneira de fazer isso? (Vejo Is there an endpoint to check if a user is logged in - #3 by pfaffman, mas não consigo dizer ao certo se é isso que quero, e /session/current.json não está na documentação da API.) Isso geraria um grande número de chamadas de API, no entanto — eu faço logout de cerca de 15 a 20 usuários por minuto no meu site devido à inatividade, então isso significaria fazer uma chamada para cada um (e possivelmente mais de uma chamada, se eu não tiver um cache local do ID deles no Discourse).
Todos os endpoints de perfil possuem um valor last_seen, que você pode utilizar.
Acho que nunca vi esse tipo de configuração em nenhum protocolo SSO, e também não recebemos solicitações para coisas assim. Mais comumente, as pessoas mantêm os dois sistemas independentes.
Se você realmente quisesse criar um webhook para ‘usuário visto’, talvez pudesse fazer isso usando um plugin personalizado.
Não tenho certeza do que você quer dizer com manter os dois sistemas independentes? Avise-me se estiver perdendo alguma maneira óbvia de resolver o problema que descrevi, por favor!
Caso contrário, parece que minhas opções são:
Quando um usuário expirar no site principal, antes de deslogá-lo, chamar o Discourse e verificar o valor de last_seen para ver se o membro esteve realmente ativo nos fóruns (apenas não fazendo nada que gere uma chamada de webhook). Prós: fácil de fazer. Contras: gerará muitas chamadas de API, algo com o qual já estou lutando e tentando contornar os limites de taxa.
Criar meu próprio plugin para fazer ping no meu site principal de vez em quando, para que eu possa atualizar o tempo da última atividade do usuário no meu site principal. Prós: parece mais a solução “certa” (indicar atividade com uma mensagem de push); meio que elegante. Contras: não é fácil de implementar.
Alterar o tempo de logout no meu site principal para 2 horas. Prós: fácil de implementar. Contras: existem algum?
Não se preocupar com isso. Os usuários são deslogados no meio de sua sessão no Discourse e reclamam muito. É isso que tenho agora. Prós: fácil de implementar, lol. Contras: uma experiência de usuário muito ruim.
Perdi algo?
Parece que a opção #3 seria uma boa resposta, embora eu precise pensar nas ramificações de ter um tempo de logout mais longo no site principal.
Ainda gosto da opção #1 como a melhor escolha, mas aí tenho que resolver como evitar tantos problemas de limite de taxa. Gostaria que existisse uma maneira de desativar globalmente todos os limites de taxa no Discourse (e no nginx, já que estou usando a instalação do Discourse via Docker), ponto final. Não preciso de nenhum deles. É apenas o meu site principal falando com minha instância do Discourse. Não permito chaves de API de usuário e sou o único com uma chave de API de sistema. É um sistema completamente fechado e os limites de taxa só estão (constantemente) atrapalhando. Acho que esse é um tópico diferente.
Se você precisa manter o comportamento que descreveu, então sim, acredito que essas são as 4 opções. Mas, se você mudar um pouco o comportamento, funcionará melhor com as ferramentas disponíveis.
A parte incomum da sua configuração é:
Você está encerrando a sessão do Discourse sempre que a sessão expira no seu site principal. Se remover essa parte, acredito que a configuração ficará alinhada com as configurações típicas.
Você ainda pode chamar /logout quando um usuário fizer logout explicitamente no seu site principal. Apenas não a chame quando a sessão expirar naturalmente.
Não dá para saber pelo post original, mas vocês estão rodando um site altamente especializado focado em pessoas compartilhando informações super sensíveis, ou onde a maioria dos usuários está fazendo login em computadores públicos compartilhados ou algo assim?
De longe, a solução mais simples aqui parece ser simplesmente não ser hiperagressivo ao expirar sessões de usuário e forçar o logout. Minha preferência como usuário é sempre “nunca me desconecte, a menos que eu clique especificamente em sair”. Se isso não for possível, vocês poderiam pelo menos fazer com que seja um dia, uma semana ou algo assim?
Entendi — essa é uma boa solução; acho que a maioria dos meus membros usa a caixa de seleção “manter-me conectado” na página de login, então seria transparente trazê-los de volta ao site principal. Se a sessão deles tiver expirado no site principal, eles seriam (invisivelmente) logados novamente exatamente nesse momento. Hmm.
É um site para um segmento da população que é muito sensível quanto à privacidade. Mas entendo o que estão dizendo e acho que poderia simplesmente fazer como vocês (e David) sugerem.
Muito obrigado a ambos. Eu não tinha uma boa noção do “quadro geral” aqui, ou de como outros sites lidam com esse tipo de cenário… agora tenho e vejo algumas soluções possíveis para minha situação. Muito apreciado!