Discourse SSO 문제 해결 도와주세요

안녕하세요, 조언을 구하고 싶습니다. 이번 주에 SSO가 작동하지 않기 시작했는데, 어제 모든 문제를 해결했다고 생각했습니다(작동했거든요, 정말입니다 :slight_smile: 참고: 어제와 오늘의 "New Users"를 확인해 봤는데, 두 날 모두(수정 후) 새로운 사용자가 있었습니다. 그런데 지금은 다시 깨져버렸네요…). 불행히도, 제가 한 업데이트가 오늘은 작동하지 않습니다.

문제: 사용자가 새 계정을 생성할 수 없고, 로그아웃한 사용자가 다시 로그인할 수 없습니다.

다음 라우트에서 discourse 서버에 400 에러가 발생하고 있음을 발견했습니다:

403: GET: discourse-url/users/by-external/USER-ID.json?
참고: 최근 API 문서에서 이 라우트가 존재하지 않는다는 것을 발견했습니다(그동안 작동했던 것 같지만요). 라우트는 다음과 같이 보입니다: https://discourse.example.com/u/by-external/{external_id}.json

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

? 기호가 끝에 있는 이유는 URL을 생성하는 함수에 선택적 파라미터 필드가 있기 때문이며, 이 두 라우트의 경우 모든 데이터는 폼 바디나 헤더로 전송됩니다.

저는 다음 라이브러리를 사용하고 있습니다.

업데이트한 내용(그리고 문제를 해결했다고 생각했던 부분):

모든 요청에서 Api-Key와 Api-Username을 쿼리 파라미터로 전송하고 있었습니다. 지난 몇 달간 관리자 패널에서 요청에 오래된 헤더를 사용하고 있다는 경고가 표시되고 있음을 확인했습니다. 이 게시물로 링크되어 있었고, 주요 내용은 다음과 같습니다:

:warning: 비추천 경고!
2020년 4월 6일, HTTP 헤더 기반 인증이 아닌 모든 인증 방식(rss, mail-receiver, ics 라우트 제외)에 대한 지원을 중단했습니다. 이는 쿼리 파라미터나 HTTP 바디에 api_key와 api_username이 포함된 API 요청이 곧 더 이상 작동하지 않게 된다는 것을 의미합니다. API 요청을 업데이트하여 인증에 HTTP 헤더를 사용하는 방법에 대해서는 아래 cURL 요청 예시를 참고하세요.

모든 요청을 업데이트했으며, 이제 모든 요청에서 Api-Key와 Api-Username이 헤더에 포함되어 있고 콘텐츠 타입은 multipart form data로 설정되어 있습니다.

이 문제를 디버깅하기 위해 무엇을 살펴봐야 할지 조언을 주실 수 있다면 매우 감사하겠습니다. 어제 퇴근 직전까지는 100% 가까울 정도로 이 시스템이 작동하고 있었다고 확신합니다. 제 계정으로 로그인과 로그아웃을 할 수 있었고, 새 계정도 생성할 수 있었습니다.

추가 정보가 필요하시면 알려주세요. 감사합니다!

헤더 필드에는 밑줄(_)이 아니라 대시(-)를 사용해야 합니다. 필드 이름을 Api-Key와 Api-Username으로 변경해 보세요.

이것이 사이트 로그인 문제가 해결될지는 확실하지 않지만, 현재 보고 계신 400 오류는 해결될 것입니다.

@simon, 답변해 주셔서 감사합니다! 불행히도 제 게시물을 잘 설명하지 못했네요. 저는 요청에서 이미 -를 사용하고 있으며 _는 사용하지 않습니다.

디버깅을 시작하려면 Discourse 사이트 설정 페이지로 이동하여 'sso’를 검색하여 모든 SSO 설정을 확인하세요. enable sso, sso url, sso secret 설정이 정확한지 확인한 후 verbose sso logging 사이트 설정을 활성화하세요. 이 설정을 활성화하면 사이트의 에러 로그(관리자 / 로그 / 에러 로그에서 확인 가능)에 추가적인 로그 항목이 기록됩니다.

SSO를 통해 로그인해 보세요. 그런 다음 에러 로그를 확인하여 문제가 되는 부분에 대한 세부 정보가 있는지 살펴보세요. 유용한 정보가 표시되지 않으면 브라우저의 웹 인스펙터를 Network 탭으로 열고 “Preserve log” 체크박스를 선택하세요. 보내지고 있는 요청들을 살펴보세요.

문제를 해결하는 과정에서 사이트 접근이 차단된 경우, 관리자 사용자로 /u/admin-login으로 이동하여 이메일 주소를 입력하면 SSO를 우회할 수 있습니다. 로그인 링크가 포함된 이메일이 발송됩니다.

@simon, 팁 주셔서 감사합니다! 로그를 확인하고 있지만, 로그를 읽는 데는 아직 경험이 많지 않습니다. 두 가지 유형의 경고와 하나의 오류가 표시됩니다:

자주 발생하는 경고 메시지입니다:

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

오류 메시지입니다:

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

Discourse에서 로그아웃한 후 내 사이트에서 테스트 사용자로 로그인하려고 하면 네트워크 패널에 다음과 같은 내용이 표시됩니다:

503 Service Unavailable: GET- https://my-site/auth/discourse_sso?sso=XXXX&sig=xxxx

아쉽게도 여기서 다음으로 어떻게 진행해야 할지 막혀 있습니다.

이 오류 메시지는 아마존 S3에서 발생했을 가능성이 있습니다. 문제를 해결하는 방법에 대한 유용한 정보가 이 토픽에 있을 수 있습니다: Backups have started failing due to server time being wrong. 여기에 더 많은 정보가 있습니다: https://stackoverflow.com/questions/4770635/s3-error-the-difference-between-the-request-time-and-the-current-time-is-too-la.

@simon 도움 주셔서 감사합니다! 제 서버 시간이 동기화되지 않아서 업데이트했는데, 이제 백업이 다시 정상적으로 작동합니다!

그런데 이제 새로운 오류가 간헐적으로 발생하고 있습니다:

로그 섹션에서 다음과 같은 경고가 무작위로 표시됩니다(총 2번만 확인했습니다):

MaxMindDB (/var/www/discourse/vendor/data/GeoLite2-City.mmdb) could not be found: No such file or directory @ rb_sysopen - /var/www/discourse/vendor/data/GeoLite2-City.mmdb

그리고

MaxMindDB (/var/www/discourse/vendor/data/GeoLite2-ASN.mmdb) could not be found: No such file or directory @ rb_sysopen - /var/www/discourse/vendor/data/GeoLite2-ASN.mmdb

현재 이 문제를 해결하는 방법을 조사하고 있습니다. 앱을 다시 빌드(rebuild)해 보았지만, 빌드가 성공적으로 완료되었는지 100% 확신하지는 못합니다. 이전에도 발생하던 400 오류와 503 오류 외에도 여전히 MaxMindDB 파일을 찾을 수 없다는 오류가 무작위로 발생하고 있습니다.

이번 주 초 대부분을 이 문제로 씨름하고 있지만, 별다른 진전이 없습니다. MaxMindDB 오류는 제거한 것 같습니다(이전에는 간헐적이고 일관성이 없었지만, 지난 3시간 동안 재현하지 못했습니다). 또한 앱을 여러 번 성공적으로 다시 빌드했습니다.

SSO 파이프라인이 깨지는 지점은 다음과 같습니다:

  • 사용자가 discourse에 접속합니다.
  • 활성 세션이 없으므로 사용자는 discourse/session/sso_login으로 리디렉션됩니다.
  • 사용자는 my-site/discourse_sso?sso=XXXX&sig=XXXX로 리디렉션됩니다.
  • 내 사이트의 이전 라우트가 호출되면 /users/by-external/userId.json에 GET 요청을 보내게 됩니다.
    • 이 요청은 403 Forbidden을 반환합니다.
  • 바로 다음으로 /admin/users/sso_sync에 POST 요청이 전송됩니다.
    • 이 요청은 404 “No route matches [POST] /admin/users/sync_sso” 오류를 반환합니다.
  • 결국, 내 사이트는 503 Forbidden 메시지를 반환합니다(내 사이트 쪽의 일부 오류 메시지를 정리해야 합니다).

오류는 Rails 앱 쪽에 있는 것 같습니다(틀렸다면 지적해 주세요). 이렇게 생각하는 이유 중 하나는, 금요일 마감 시간(EOD)까지 모든 것이 정상 작동했다는 점입니다. 금요일 저녁부터 토요일 사이에 몇 명의 새 사용자가 가입한 기록이 이를 증명합니다(로그인 또는 새 사용자 생성이 깨져 있던 부분이었습니다). 이전 게시물에서 언급했듯이, 당시에는 모든 것을 수정했다고 생각했지만, 토요일에 작업을 시작했을 때 다시 깨져 있는 것을 발견했습니다.

/users/by-external/<external_id>.json과 /admin/users/sync_sso로 요청을 보내는 이유가 무엇인지 잘 모르겠습니다. 일반적인 흐름은 SSO 페이로드를 URL의 쿼리 파라미터로 설정하고 사용자를 /session/sso_login으로 리다이렉트하는 것입니다. sync_sso 경로가 무엇에 사용되는지에 대한 세부 사항은 여기에서 확인할 수 있습니다: Sync DiscourseConnect user data with the sync_sso route.

아직 Discourse 사용자와 연결되지 않은 external_id로 /users/by-external/<external_id>에 요청을 보내면 404(not found) 오류가 반환되어야 합니다. external_id가 Discourse 사용자와 연결되어 있는 경우, 해당 사용자를 반환해야 합니다.

@simon, /users/by-external/USER-ID.json에 대한 요청은 사용자가 내 discourse에 이미 계정이 있는지 확인하기 위한 것입니다. 해당 ID로 사용자가 발견되면, PUT 요청(/admin/groups/groupId/members.json)을 통해 내 사이트와 연관된 discourse 그룹에 추가/제거된 후 my-discourse/session/sso_login으로 리디렉션됩니다.

사용자가 계정을 가지고 있지 않은 경우, POST /admin/users/sync_sso를 통해 계정이 추가되고, 사용자가 생성된 후(그리고 적절한 discourse 그룹에 추가된 후) my-discourse/session/sso_login으로 리디렉션됩니다.

나중에 다시 확인하고, 나열해 주신 문서를 다시 읽어보겠습니다(감사합니다!). 이 플로우가 2015년 초부터 아무 문제 없이 작동해 왔는데(discourse와 SSO 옵션이 우리에게 정말 가치 있는 도구였기 때문에!), 지난주에 갑자기 작동이 멈춘 것이 이상합니다.

@simon 도움 주신 점 진심으로 감사드립니다! 문제를 해결했습니다. 우리가 사용하던 Api-Username이 지난주 어딘가에서 비활성화(장기간 미사용으로 인해)되었습니다. 처음에는 이것이 문제일 수 있다고 추측했었습니다. 금요일에 해당 사용자를 다시 활성화했는데, 아마도 금요일에 모든 것이 정상화된 이유가 바로 이것일 것입니다(처음에는 Api-Username과 Api-Key를 헤더로 옮긴 것이 원인이라고 생각했었거든요).

Discourse가 토요일 아침 어딘가에서 같은 사용자를 다시 비활성화했는데, 이것이 모든 것이 잘 작동하다가 갑자기 멈춘 이유를 설명해 줍니다. 장기간 미사용으로 인해 사용자가 그렇게 빨리 다시 비활성화될 것이라고는 생각하지 못했습니다.

앞으로 이런 문제가 반복되지 않도록 Api-Username을 "system"으로 변경했습니다. 다시 한번 도움 주셔서 감사합니다. 이 문제를 디버깅하는 과정에서 백업 로그도 다시 정상적으로 작동하게 되었고, 정말 많은 것을 배웠습니다!