Source code for pytdbot.utils.webapps

import hashlib
import hmac
import time

from urllib.parse import parse_qs

from ..exception import WebAppDataInvalid, WebAppDataOutdated, WebAppDataMismatch

_webapp_secret_key = b"WebAppData"


[docs] def create_webapp_secret_key(bot_token: str) -> bytes: r"""Create a secret key for Web App data validation \Parameters: bot_token (``str``): Bot token """ return hmac.new( key=_webapp_secret_key, msg=bot_token.encode("utf-8"), digestmod=hashlib.sha256, ).digest()
[docs] def parse_webapp_data( secret_key: bytes, init_data: str, max_data_age: int = 60 ) -> dict: r"""Parse and validate init data received from Web App \Parameters: secret_key (``bytes``): Secret key for Web App data validation; can be created using :func:`pytdbot.utils.create_webapp_secret_key` init_data (``str``): Init data received from Web App max_data_age (``int``, *optional*): Maximum age of init data in seconds. Default is ``60`` seconds Returns: ``dict``: Parsed data Raises: :class:`pytdbot.exception.WebAppDataInvalid` :class:`pytdbot.exception.WebAppDataOutdated` :class:`pytdbot.exception.WebAppDataMismatch` """ assert isinstance(secret_key, bytes), "secret_key must be bytes" assert isinstance(init_data, str), "init_data must be a string" assert isinstance(max_data_age, int), "max_data_age must be an int" # In Python 3.8.7 or earlier, parse_qs treats ';' as query separator in addition to '&' # Which may cause issues with the hash validation data = parse_qs(init_data) data = {k: v[0] for k, v in data.items()} if "hash" not in data or "auth_date" not in data: raise WebAppDataInvalid("Missing hash or auth_date") if int(data["auth_date"]) < int(time.time() - max_data_age): raise WebAppDataOutdated received_hash = data.pop("hash") sorted_keys = sorted(data.keys()) data_check_string = "\n".join([f"{key}={data[key]}" for key in sorted_keys]) expected_hash = hmac.new( key=secret_key, msg=data_check_string.encode("utf-8"), digestmod=hashlib.sha256 ).hexdigest() if not hmac.compare_digest(expected_hash, received_hash): raise WebAppDataMismatch("Hash mismatch") return data