Discourse-saml: SLO가 세션을 취소하지 않음

안녕하세요,

현재 다음과 같은 환경에서 문제를 겪고 있습니다:
공식 Discourse 2.5.0 ([ 3f7658cc6e ])에 discourse-saml 플러그인 (커밋 230a58b)을 사용 중이며,
Identity Provider로는 Keycloak (10.0.2)를 사용하고 있습니다.

우리의 Identity Provider는 https://discourse.our-domain.xxx/auth/saml/slo URL을 Logout Service POST Binding URL로 설정되어 있습니다. 로그인 프로세스는 완벽하게 작동합니다. Discourse의 로그아웃 버튼을 사용하면 IdP 세션도 함께 종료됩니다.

문제는 IdP의 로그아웃 기능을 사용할 때 발생합니다. Discourse 세션이 종료되지 않습니다. 포럼은 요청을 수신하지만 올바르게 처리하지 않는 것 같습니다. 사용자는 로그인된 상태로 유지되며 discourse 로그에 오류가 발생합니다.

다음 로그의 사용자 이름은 test입니다.

Started POST "/auth/saml/slo" for 127.0.0.1 at 2020-07-09 18:29:33 +0000                                                                                                                            
OmniAuth::Strategies::SAML::ValidationError (SAML failed to process LogoutRequest)                                                                                                                  
/var/www/discourse/plugins/discourse-saml/gems/2.6.6/gems/omniauth-saml-1.9.0/lib/omniauth/strategies/saml.rb:189:in `handle_logout_request'

예외로 이어지는 if 조건문은 다음과 같습니다 (saml.rb):

if logout_request.is_valid? &&
     logout_request.name_id == session["saml_uid"]
디버그 출력용 코드
STDERR.puts '*************************************************************************'
STDERR.puts 'raw_request:'                                                             
STDERR.puts raw_request                                                                
STDERR.puts '*************************************************************************'
STDERR.puts 'logout_request.is_valid?'                                                 
STDERR.puts logout_request.is_valid?                                                   
STDERR.puts '*************************************************************************'
STDERR.puts 'logout_request.name_id'                                                   
STDERR.puts logout_request.name_id                                                     
STDERR.puts '*************************************************************************'
STDERR.puts 'session[saml_uid]'                                                        
STDERR.puts session["saml_uid"]                                                        
STDERR.puts '*************************************************************************'

saml.rb (181번째 줄)에 디버그 출력을 추가한 결과 다음과 같은 값들을 확인했습니다:

*************************************************************************
raw_request:
raw request (base64로 디코딩됨)
<?xml version="1.0"?>
<samlp:LogoutRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns="urn:oasis:names:tc:SAML:2.0:assertion" Destination="https://discourse.test.our-domain.xxx/auth/saml/slo" ID="ID_ee6ef1f7-a269-443f-9942-1311b2c09636" IssueInstant="2020-07-09T19:20:27.882Z" Version="2.0">
  <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">https://ima.test.our-domain.xxx/auth/realms/master</saml:Issuer>
  <dsig:Signature xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
    <dsig:SignedInfo>
      <dsig:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
      <dsig:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
      <dsig:Reference URI="#ID_ee6ef1f7-a269-443f-9942-1311b2c09636">
        <dsig:Transforms>
          <dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
          <dsig:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
        </dsig:Transforms>
        <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
        <dsig:DigestValue>nbeIwX97u+NNRf4KswI95oSmI2w=</dsig:DigestValue>
      </dsig:Reference>
    </dsig:SignedInfo>
    <dsig:SignatureValue>[...]</dsig:SignatureValue>
    <dsig:KeyInfo>
      <dsig:KeyName>[...]</dsig:KeyName>
      <dsig:X509Data>
        <dsig:X509Certificate>[...]</dsig:X509Certificate>
      </dsig:X509Data>
      <dsig:KeyValue>
        <dsig:RSAKeyValue>
          <dsig:Modulus>[...]</dsig:Modulus>
          <dsig:Exponent>AQAB</dsig:Exponent>
        </dsig:RSAKeyValue>
      </dsig:KeyValue>
    </dsig:KeyInfo>
  </dsig:Signature>
  <saml:NameID xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">test</saml:NameID>
  <samlp:SessionIndex>393fc3ab-6a18-4b8e-89a5-a005fc48f7cf::36a71dc0-22a0-4b72-be02-68639bedea06</samlp:SessionIndex>
</samlp:LogoutRequest>

*************************************************************************
logout_request.is_valid?           
true                                          
*************************************************************************
logout_request.name_id
test
*************************************************************************
session[saml_uid]
                                                                       
*************************************************************************

혹시 도움을 주실 수 있는 분이 있을까요? 설정 문제처럼 보이지 않습니다.

미리 감사드립니다

Max

우리의 플러그인에서는 saml_uid 세션 값을 처리하지 않습니다. 해당 값은 omniauth-saml 젠 자체에서 처리됩니다. 따라서 session["saml_uid"] 값이 비어 있는 이유가 무엇인지 확신할 수 없습니다. 문제가 있다면 omniauth 젠에 이슈를 보고해야 할 수 있습니다.

또한, 아직 SLO와 관련하여 고객이 보고한 이슈는 없습니다.

저도 동일한 문제를 확인했습니다:

  • Keycloak에 SAML로 연결된 2개의 애플리케이션(디스커스 및 다른 애플리케이션 X라고 부르겠습니다).
  • 디스커스에서 로그아웃을 하면 X에서도 로그아웃이 되고, X에서는 아무것도 할 수 없습니다.
  • X에서 로그아웃을 하면 Keycloak의 세션은 사라지지만, 디스커스에서는 사용자가 여전히 로그인 상태입니다.

디스커스에서 브라우저 페이지를 새로고침해도 SAML 인증이 사라졌는지(= 사용자가 로그아웃되었는지)를 검증하지 않습니다.

디스커스에서도 로그아웃이 되기를 기대합니다.
디스커스가 Keycloak의 SAML 인증을 확인하나요?
언제 확인하나요?

SAML 세션이 여전히 활성 상태인지 검증할 수 있을까요? 위 답변을 참고해 주세요 @vinothkannans