외부 SSO에서 서명 매칭을 가져오지 못함

안녕하세요,

외부 SSO 엔드포인트와 Discourse를 연동하려고 시도하고 있는데, 서명이 일치하지 않는 것 같습니다.

로그에는 다음과 같은 내용이 표시됩니다:

[2020-12-23 21:10:50 +0000] [7] [DEBUG] 2d9c3e07e2e7551e51af471ca3b50e83d06411b2c75e443f96def5b6a257d141
[2020-12-23 21:10:50 +0000] [7] [DEBUG] ad02fdc5bd85adce7722bc264352cca9b931392735ed72474966c4461f188b8c
[2020-12-23 21:10:50 +0000] [7] [DEBUG] compare_digest is different

무엇을 잘못하고 있을까요? hmac 준비 과정은 정상적으로 보이나요?

endpoint:
@app.route(/discourse)
def discourse():
    try:
        cookie = request.cookies['__session']
    except KeyError:
        logging.error("Session cookie was not present")
        return redirect(login_url)
    
    try:
        decoded_token = verify_session_cookie(cookie, check_revoked=True)
    except ValueError:
        return {"message": "Session cookie was present but not a valid string or empty"}, 400
    except ExpiredSessionCookieError:
        return {"message": "Session cookie was present but expired."}, 400
    
    try:
        uid = decoded_token['uid']
    except KeyError:
        return {"message": "The user id could not be read from the decoded token"}, 500
    
    try:
        payload = request.args['sso']
    except KeyError:
        return {"message": "Payload parameter was not present"}, 400
    
    try:
        sig = request.args['sig']
    except KeyError:
        return {"message": "Sig parameter was not present"}, 400
    
    try:
        nonce = validate_sso_and_generate_nonce(payload, sig, sso_secret)
    except DiscourseError as e:
        current_app.logger.error("sso validation failed: " + str(e))
        return redirect(login_url)
    
    user = get_user(uid)
    sso_url = generate_sso_redirect_url(forum_url, nonce, sso_secret, user.email, uid, user.display_name, user.display_name)
    current_app.logger.debug("Discourse endpoint complete")
    return redirect(sso_url)

서명을 생성하는 부분입니다:

def validate_sso_and_generate_nonce(payload, signature, secret):
    """
        payload: Discourse가 SSO 엔드포인트로 HTTP 호출 시 sso GET 파라미터로 제공하는 값
        signature: Discourse가 SSO 엔드포인트로 HTTP 호출 시 sig GET 파라미터로 제공하는 값
        secret: Discourse sso secret에 입력한 시크릿 키
        반환 값: discourse가 리다이렉트 URL을 검증하는 데 사용되는 nonce
    """
    if None in [payload, signature]:
        raise DiscourseError('No SSO payload or signature.')

if not secret:
    raise DiscourseError('Invalid secret..')

if not payload:
    raise DiscourseError('Invalid payload..')

payload = bytes(parse.unquote(payload), encoding='utf-8')
decoded = base64.decodestring(payload).decode('utf-8')
if len(payload) == 0 or 'nonce' not in decoded:
    raise DiscourseError('Invalid payload..')

h = hmac.new(base64.b64encode(bytes(secret, encoding='utf-8')), payload, digestmod=hashlib.sha256)
this_signature = h.hexdigest()

current_app.logger.debug(this_signature)
current_app.logger.debug(signature)

#if this_signature != signature:
#    raise DiscourseError('Payload does not match signature.')

if not hmac.compare_digest(this_signature, signature):
    current_app.logger.debug("compare_digest is different")

nonce = decoded.split('=')[1]

return nonce

이 문제를 해결할 수 있었나요? 아직이라면, 다음 코드를 살펴보면 어디서 문제가 발생하고 있는지 확인할 수 있을지도 모릅니다:

https://github.com/bennylope/pydiscourse/blob/master/pydiscourse/sso.py#L39

HMAC 함수에 사용할 페이로드를 준비하는 방식에 몇 가지 차이가 있긴 하지만, 이 코드는 서명이 일치하지 않는 동일한 문제로 실패합니다.