I'm trying to add Telegram Web Login to my Django+Vue project. I'm handling login on Vue and directly passing the authorization data taken from TG to Django via DRF. That's working fine. The problem occurs in the verification on REST's POST view. When i was using js-sha256 library on Vue it works perfectly and im getting the true value of hash string provided by sha256.hmac()
function from the js-sha256 library. I'm struggling to get same hash on Python. Here is the TG data verification explained and the code i'm using in POST view:
class TelegramLoginSerializer(serializers.Serializer):
raw_data = serializers.JSONField(required=True)
def create(self, validated_data):
raw_data = validated_data['raw_data']
tg_data = "\n".join([f'{k}={raw_data[k]}' for k in sorted(raw_data)])
if raw_data['hash'] != self.verify_telegram_data(tg_data):
return PermissionDenied()
else:
...
@staticmethod
def verify_telegram_data(data):
secret_key = hashlib.sha256(settings.TG_BOT_TOKEN.encode('utf-8'))
message = data.encode('utf-8')
return hmac.new(secret_key.digest(), message, hashlib.sha256).hexdigest()
Here is a solution:
message = data.encode('utf-8').decode('unicode-escape').encode('ISO-8859-1')
Edited: I simplified the solution, also forgot to mention that the issue is related to encoding and decoding of the bytes when you concatenate the query strings using the join of "\n". You need to decode with escaping and encode once again.
Hope it helps.