Discord '연결' 기능에서 OAuth2 csrf_detected 오류 발생

안녕하세요! 이 오류를 해결하는 데 도움이 절실히 필요합니다:


재현 단계:
사용자가 설정(Preferences)에서 Discord의 “연결” 버튼을 클릭하면,


사용자가 올바르게 Discord 인증 페이지로 리디렉션됩니다.

그러나 Authorize 버튼을 클릭한 후, 사용자는 포럼에서 이 메시지를 받게 됩니다:
image
그리고 이 토픽 상단에 표시된 오류가 관리자 로그에 나타납니다.


이 문제를 해결하기 위해 읽을 것은 다 읽고 시도해 보았다고 느끼지만, 여전히 계속 발생하고 있습니다.
Discord Client ID와 Secret 사이트 설정이 정확한지 확인했습니다.
또한 URI가 올바른 구문인지도 확인했습니다(본 몇 가지 관련 토픽을 기반으로):

제안이 있을까요? 작동할지 확실하지 않더라도 무엇이든 시도해 볼 의향이 있습니다 :laughing:

혹시 아이디어가 있으신가요? 여전히 이 문제로 고생 중이에요 :confused:

nginx 또는 캐싱 문제인 것 같다고 생각하는데(?)요. discourse.conf에 인증이나 CSRF 관련 설정이 별도로 정의되어야 하는 건지, 혹시 누락된 설정이 있는지 궁금합니다.

@merefield, @david, @sam - 언급드려 죄송합니다만, 과거 csrf 관련 토론에서 여러분의 이름을 많이 보았습니다. 이에 대해 추천하실 사항이 있으신가요? Discord 인증이 discourse에 통합된 부분인 점을 고려하면, 이런 문제가 발생하는 원인이 무엇인지 도무지 모르겠습니다.

미리 도움을 주시면 감사하겠습니다. 감사합니다 :smiling_face:

우리는 이 중 하나를 위반하고 있는 걸까요?

여전히 패턴을 찾지 못하고 있습니다. 때로는 정상적으로 작동하여 올바르게 연결되지만, 다른 때는 csrf 페이지가 표시됩니다.
현재로서는 verified_request?의 마지막 조건 검사에 가장 의심이 갑니다.
(valid_request_origin? && any_authenticity_token_valid?)가 true를 반환하는지 쉽게 확인할 수 있는 방법이 있을까요?

디버그할 수 있는 정보가 부족해서 죄송합니다. 하지만 (아픈 만큼) 제가 (제 생각에는) 문제의 원인을 찾아냈습니다. 아직 해결책은 불분명하니, 계속 읽어 주세요 :kissing_heart:


아래 사진들은 제 계정을 성공적으로 연동한 직후, 페이지를 새로고침하여 다시 시도했고 csrf 감지 페이지에 실패한 연속된 상황을 보여줍니다. 저는 인코그니토 창을 사용했으며, 성공적인 연결과 csrf 실패 사이에 아무것도 변경하거나 하지 않았습니다. 제가 발견한 내용은 다음과 같습니다:

첫 번째 사진은 1번과 2번 요청 헤더에서 _forum_session 쿠키가 일치하여 성공적으로 연결된 것을 보여줍니다.

그러나 페이지를 새로고침하고 다시 시도했을 때(연결에 실패했을 때), 왼쪽 검색 결과에서 요청 헤더에 _forum_session 쿠키가 1회만 표시되는 것을 볼 수 있으며, 이는 실패로 이어졌습니다.

요약하자면: 문제는 discord?reconnect 요청 헤더의 forum_session 쿠키와 그 후속 callback? 요청 헤더가 일치하지 않기 때문이라고 확신합니다. 이것이 서로 다르게 되는 원인은 무엇일까요?

음, 점점 가까워지는 것 같네요.

아래 사진에서 볼 수 있듯이, discord?reconnect POST 요청 직후에 update POST 요청이 발생하는 것을 확인할 수 있습니다.


그리고 역시, 이는 _forum_session 쿠키를 설정하여 위에서 설명한 대로 불일치를 일으키는 원인이 되고 있습니다.

성공적으로 연결된 인스턴스(아래)를 확인해 보면, update가 discord?reconnect POST 요청 전에만 발생하고 있음을 알 수 있습니다.

이렇게 하면 _forum_session 쿠키가 일치하여 csrf 문제 없이 계정을 성공적으로 연결할 수 있습니다.

사용자가 연결 과정을 시작한 후에 해당 update가 발생하지 않도록 어떻게 방지할 수 있을까요?

@FerrariFlunker 답변이 늦어서 죄송합니다. 아직 확인해볼 기회가 없었는데, 코어 팀에서 확인해 주시면 좋겠습니다.

위로가 될지는 모르겠지만, 재현이 가능한 것 같습니다. 같은 오류가 발생하고 있는 것 같아요:

(discord) Authentication failure! csrf_detected: OmniAuth::Strategies::OAuth2::CallbackError, csrf_detected | CSRF detected

걱정 마세요 @merefield, 답변 주셔서 감사합니다!

혹시 본인 환경에서도 해당 오류가 발생하나요? 어느 쪽이든, 이 오류는核心团队이 확인해야 할 것 같습니다. 디버깅을 2주 이상 해왔는데도 아직 해결책을 찾지 못했습니다 :confused:

좋은 조사 결과네요! 이런 종류의 경쟁 조건(race condition)은 실제로 여러분이 보고 있는 문제를 일으킬 수 있습니다.

다만, 이 문제에 대한 다른 보고는 없었기 때문에, 여러분의 사이트/설정과 관련된 특정 문제인 것 같습니다. 사이트에 어떤 플러그인이 설치되어 있나요? “update” 호출을 열어보내고 어떤 페이로드가 전송되는지 확인해 주실 수 있을까요?

update 호출들을 살펴본 결과, 당신이 맞으신 것 같습니다. csrf 실패를 일으킨 확인된 ‘update’ 요청들의 스크린샷을 첨부합니다.

cdn 관련 패턴을 발견했습니다 :face_with_monocle: 그 부분에 대해 무엇이 잘못 구성되어 있을까요? 플러그인 목록이 여전히 필요하시다면 말씀해 주세요. 그냥 이 답변에 사진 1장을 더 추가하는 걸로 충분할 것 같아서요 :smile:

흥분되는 업데이트가 있습니다! 며칠 전 ‘update’ 페이로드를 더 자세히 살펴보다가 우연히 다음을 성공적으로 연결하게 되었습니다:

이것이 우리 플러그인 중 하나와 관련되어 있다는 것을 알게 되었습니다! :partying_face: :expressionless: :smile:
플러그인을 비활성화하고 추가 테스트를 거쳐 관련 기능을 커뮤니티에 성공적으로 배포한 후… 이제 원인을 확신 있게 찾아냈다고 말할 수 있습니다.

결국 문제의 주범은 이 플러그인이었습니다: GitHub - discourse/discourse-chat: Chat inside Discourse · GitHub

돌이켜 보면 이 플러그인이 원인일 수 있다는 것이 당연합니다. 이 플러그인은 여전히 실험 단계로 표시되어 있으며 프로덕션 사이트 사용을 의도하지 않았기 때문입니다. :sweat:

이 문제를 진단하는 데 3주 이상을 소요했고 커뮤니티의 다른 프로젝트로 다시 집중해야 하므로 :face_with_spiral_eyes:, unfortunately discourse-chat 플러그인의 수정 방법을 찾는 데 도움을 드릴 수 없습니다.

누군가 플러그인에 수정 사항을 적용한다면, 우리는 (아마도 :smile:) 사이트에 플러그인을 다시 활성화하는 것을 검토할 것입니다. 하지만 당장은 안정적인 계정 연결(Connect) 기능이 필요합니다.

진단에 도움을 주신 모든 분께 다시 한번 감사드립니다! :+1:

상세한 조사 감사합니다 @FerrariFlunker!

Discourse 코어에서 수정 사항을 위한 PR을 방금 생성했습니다:

채팅 플러그인을 제거한 후에야 수정이 된 이유는, 채팅 기능이 이 ‘PresenceChannel’ API를 광범위하게 사용하기 때문에 해당 문제가 발생할 가능성이 훨씬 더 높기 때문입니다. 채팅 쪽에서는 변경 사항이 필요하지 않을 것으로 보입니다.

이 수정으로 Google 로그인에서도 동일한 문제가 해결될까요? 채팅 플러그인을 테스트 중이던 제 인스턴스 중 하나에서 사용자분들이 이 기능을 매우 좋아하셨지만, Discord 로그인과 동일한 오류로 Google 로그인이 깨졌습니다.

네, 이 수정 사항은 모든 로그인 유형에 적용됩니다 :+1: