Ajude-me a solucionar problemas no SSO do Discourse

Olá, espero receber algumas orientações. Meu SSO parou de funcionar esta semana e achei que tivesse resolvido tudo ontem (estava funcionando, juro :slight_smile: Nota: verifiquei a seção “Novos Usuários” de ontem e de hoje, e havia novos usuários em ambos os dias (após a correção), mas agora está quebrado novamente…). Infelizmente, as atualizações que fiz não estão funcionando hoje.

Problema: Usuários não conseguem criar novas contas e usuários que fazem logout não conseguem fazer login novamente.

Percebi que meu servidor Discourse está retornando erros 400 nas seguintes rotas:

403: GET : discourse-url/users/by-external/USER-ID.json?
Nota: Recentemente descobri na documentação da API que essa rota não existe? (embora tenha funcionado antes), parece que a rota correta é: https://discourse.example.com/u/by-external/{external_id}.json

404: POST: discourse-url/admin/users/sync_sso?

O motivo do ponto de interrogação ? no final é que tenho um campo de parâmetro opcional em uma função que gera URLs; para essas duas rotas, todos os dados são enviados no corpo do formulário ou nos cabeçalhos.

Estou usando a seguinte biblioteca.

O que atualizei (e o que achei que tivesse resolvido o problema):

Em todas as minhas solicitações, eu enviava a Api-Key e o Api-Username como parâmetros de consulta. Nos últimos meses, notei no meu painel de administração um aviso indicando que estava usando cabeçalhos desatualizados na minha solicitação. O aviso me levou a este post, e os detalhes principais são:

:warning: Aviso de Depreciação!
Em 6 de abril de 2020, removemos o suporte para toda autenticação baseada em parâmetros não cabeçalhos HTTP (exceto algumas rotas de RSS, recebimento de e-mail e ICS). Isso significa que solicitações de API que possuem api_key e api_username nos parâmetros de consulta ou no corpo HTTP da solicitação deixarão de funcionar em breve. Consulte o exemplo de solicitação cURL abaixo para saber como atualizar suas solicitações de API para usar cabeçalhos HTTP para autenticação.

Atualizei todas as minhas solicitações; agora, todas elas têm a Api-Key e o Api-Username no cabeçalho e o tipo de conteúdo está definido como multipart/form-data.

Se alguém puder oferecer orientações sobre o que investigar para depurar esse problema, ficaria muito grato. Tenho quase 100% de certeza de que isso estava funcionando no final do meu expediente ontem; consegui fazer login e logout na minha conta e também criar novas contas.

Por favor, me avise se precisar de mais informações. Obrigado!

Os campos do cabeçalho devem usar hífens (-), não sublinhados (_). Tente alterar os nomes dos campos para Api-Key e Api-Username.

Não tenho certeza se isso resolverá o problema de os usuários não conseguirem fazer login no seu site, mas isso corrigirá o problema dos erros 400 que você está vendo.

@simon, obrigado pela resposta! Infelizmente, não documentei bem minha postagem; já estou usando - e não _ nas minhas requisições.

Para começar a depurar isso, acesse a página de configurações do seu site Discourse e pesquise por ‘sso’ para obter todas as suas configurações de SSO. Certifique-se de que as configurações enable sso, sso url e sso secret estão corretas. Em seguida, ative a configuração do site verbose sso logging. Com essa configuração ativada, algumas entradas de log adicionais serão adicionadas aos logs de erro do seu site (encontrados em Admin / Logs / Error Logs.)

Tente fazer login via SSO. Em seguida, examine seus logs de erro para ver se eles fornecem detalhes sobre o problema. Se você não estiver vendo nada útil, abra o inspetor web do seu navegador na aba “Network” com a caixa de seleção “Preserve log” marcada. Analise as requisições que estão sendo feitas.

Se você se trancar fora do seu site enquanto tenta corrigir o problema, como usuário administrador, pode contornar o SSO acessando /u/admin-login e inserindo seu endereço de e-mail no formulário. Um e-mail será enviado a você com um link de login.

@simon, obrigado pela dica! Tenho analisado os logs, mas não sou muito experiente na leitura deles. Estou recebendo dois tipos diferentes de avisos e um erro:

Aqui está o aviso que recebo com frequência:

Verbose SSO log: Started SSO process add_groups: admin: moderator: avatar_force_update: avatar_url: bio: card_background_url: email: external_id: groups: locale: locale_force_update: logo

Aqui está o erro:

Job exception: The difference between the request time and the current time is too large.

Quando tento fazer login com um usuário de teste no meu site, do qual saí no Discourse, recebo o seguinte no painel de rede:

503 Serviço Indisponível: GET- https://my-site/auth/discourse_sso?sso=XXXX&sig=xxxx

Infelizmente, estou travado e não sei qual é o próximo passo.

Acho que essa mensagem de erro está vindo do Amazon S3. Pode haver detalhes úteis sobre como resolver o problema neste tópico: Backups have started failing due to server time being wrong. Há mais informações aqui: https://stackoverflow.com/questions/4770635/s3-error-the-difference-between-the-request-time-and-the-current-time-is-too-la.

@simon obrigado pela ajuda! O horário do meu servidor estava dessincronizado e atualizei isso; agora meus backups funcionam novamente!

Agora estou recebendo esporadicamente um novo erro:

Na seção de logs, recebo aleatoriamente os seguintes avisos (só os recebi 2 vezes):

MaxMindDB (/var/www/discourse/vendor/data/GeoLite2-City.mmdb) não foi encontrado: No such file or directory @ rb_sysopen - /var/www/discourse/vendor/data/GeoLite2-City.mmdb

e

MaxMindDB (/var/www/discourse/vendor/data/GeoLite2-ASN.mmdb) não foi encontrado: No such file or directory @ rb_sysopen - /var/www/discourse/vendor/data/GeoLite2-ASN.mmdb

Estou no processo de pesquisar como resolver esse problema. Tentei reconstruir meu aplicativo, mas não tenho 100% de certeza se a reconstrução foi bem-sucedida. Ainda estou recebendo aleatoriamente os erros “MaxMindDB não foi encontrado”, além dos erros 400 e do erro 503 que eu estava recebendo anteriormente.

Tenho trabalhado nisso desde o início da manhã e não avancei muito. Acredito que eliminei os erros do MaxMindDB (eles eram esporádicos e inconsistentes antes; não consegui replicá-los nas últimas 3 horas) e reconstruí meu aplicativo várias vezes com sucesso.

É aqui que o pipeline SSO falha:

  • O usuário acessa o Discourse
  • Como não há uma sessão ativa, o usuário é redirecionado para discourse/session/sso_login
  • O usuário é redirecionado para my-site/discourse_sso?sso=XXXX&sig=XXXX
  • Quando a rota anterior do meu site é acionada, faço uma requisição GET para /users/by-external/userId.json
    • isso retorna um 403 Forbidden
  • Imediatamente após, uma requisição POST é enviada para /admin/users/sync_sso
    • isso resulta em um 404 "No route matches [POST] /admin/users/sync_sso
  • Por fim, meu site retorna uma mensagem 503 Forbidden (preciso limpar algumas mensagens de erro no lado do meu site)

Sinto que o erro está no lado da aplicação Rails (por favor, me corrija se estiver errado). Um motivo para pensar assim é que, ao final do dia de sexta-feira, tudo funcionava; há prova disso, pois alguns novos usuários se cadastraram entre sexta à noite e sábado (e era exatamente o login ou a criação de novos usuários que estava quebrado). Como mencionei em posts anteriores, achei que havia corrigido tudo na época, porém, quando comecei a trabalhar no sábado, notei que havia voltado a falhar.

Não tenho certeza do motivo pelo qual você está fazendo as requisições para /users/by-external/<external_id>.json e /admin/users/sync_sso. O fluxo normal seria apenas redirecionar o usuário para /session/sso_login, com o payload SSO definido como parâmetros de consulta na URL. Há detalhes sobre o uso da rota sync_sso aqui: Sync DiscourseConnect user data with the sync_sso route.

Fazer uma requisição para /users/by-external/<external_id> com um external_id que ainda não está associado a um usuário do Discourse deve retornar um erro 404 (não encontrado). Se o external_id estiver associado a um usuário do Discourse, o usuário deve ser retornado.

@simon, a solicitação para /users/by-external/USER-ID.json é para verificar se o usuário já possui uma conta no meu Discourse. Se um usuário for encontrado com esse ID, ele é adicionado/removido dos grupos do Discourse associados ao meu site por meio de uma requisição PUT para /admin/groups/groupId/members.json e, em seguida, redirecionado para my-discourse/session/sso_login.

Se o usuário não tiver uma conta, ela é criada por meio de uma requisição POST para /admin/users/sync_sso. Após a criação do usuário (e sua adição aos grupos do Discourse adequados), ele é redirecionado para my-discourse/session/sso_login.

Vou acompanhar e reler a documentação que você listou (obrigado!). Esse fluxo tem funcionado sem problemas desde o início de 2015 (e o Discourse, junto com a opção SSO, tem sido uma ferramenta tão valiosa para nós!), então é estranho que tenha parado de funcionar repentinamente na semana passada.

@simon Agradeço muito toda a sua ajuda! Consertei o problema. O Api-Username que estávamos usando foi “desativado” em algum momento da semana passada (devido à inatividade). Eu originalmente especulei que isso poderia ter sido o problema. Reativei o usuário na sexta-feira e, muito provavelmente, foi isso que corrigiu tudo na sexta-feira (eu originalmente pensei que fosse mover o Api-Username e a Api-Key para o cabeçalho).

O Discourse desativou o mesmo usuário novamente na manhã de sábado, o que explica por que tudo estava funcionando e, de repente, parou. Eu não achei que o usuário seria desativado novamente tão cedo devido à inatividade.

Mudei o Api-Username agora para “system” para evitar que isso quebre no futuro. Obrigado novamente pela sua ajuda; no processo de depuração, meus logs de backup voltaram a funcionar e certamente aprendi muito!