最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to properly verify data in Telegram's Web App? - Stack Overflow

programmeradmin5浏览0评论

I'm trying to implement data validation for a Telegram Web App in my NestJS application. The keys don't match for me at all. I can't figure out if it's due to the use of a work VPN (I can't check without it. The form's functionality that opens is tied to the VPN) or because of an error in my code. I'd appreciate any advice! Below is the code on how I perform the check.

async authorizationTest(@Body() authorizationData: AuthorizeUserDto) {
    console.log("Body received from Telegram", authorizationData);

    const botToken = this.configService.get("TELEGRAM_BOT_TOKEN");
    const data = querystring.parse(authorizationData.telegramId);
    console.log("Data before hash", data);
    const hash = data.hash as string;
    delete data.hash; // Remove hash from object to build the verification string

    // 2. Building the verification string.
    const dataCheckString = Object.keys(data)
      .sort()
      .map((key) => `${key}=${data[key]}`)
      .join("\n");

    console.log("dataCheckString", dataCheckString);

    // 3. Calculating the secret key.
    const secretKey = crypto
      .createHmac("sha256", botToken)
      .update("WebAppData")
      .digest();

    console.log("secretKey", secretKey);

    // 4. Computing HMAC for the verification string.
    const putedHash = crypto
      .createHmac("sha256", secretKey)
      .update(dataCheckString)
      .digest("hex");

    console.log("putedHash", putedHash);
    // 5. Comparing the puted HMAC with hash.
    if (putedHash !== hash) {
      console.log("Verification failed!");
    } else {
      console.log("Hooray! Verification succeeded!");
      // 6. Checking the auth_date for its validity.
      const CURRENT_UNIX_TIME = Math.floor(Date.now() / 1000);
      const TIMEOUT_SECONDS = 3600; // Approximately 1 hour
      if (CURRENT_UNIX_TIME - Number(data.auth_date) > TIMEOUT_SECONDS) {
        console.log("Verification failed due to timeout");
      }

      // If all checks are successful, return true.
      console.log("Verification successful");
    }
}

I'm trying to implement data validation for a Telegram Web App in my NestJS application. The keys don't match for me at all. I can't figure out if it's due to the use of a work VPN (I can't check without it. The form's functionality that opens is tied to the VPN) or because of an error in my code. I'd appreciate any advice! Below is the code on how I perform the check.

async authorizationTest(@Body() authorizationData: AuthorizeUserDto) {
    console.log("Body received from Telegram", authorizationData);

    const botToken = this.configService.get("TELEGRAM_BOT_TOKEN");
    const data = querystring.parse(authorizationData.telegramId);
    console.log("Data before hash", data);
    const hash = data.hash as string;
    delete data.hash; // Remove hash from object to build the verification string

    // 2. Building the verification string.
    const dataCheckString = Object.keys(data)
      .sort()
      .map((key) => `${key}=${data[key]}`)
      .join("\n");

    console.log("dataCheckString", dataCheckString);

    // 3. Calculating the secret key.
    const secretKey = crypto
      .createHmac("sha256", botToken)
      .update("WebAppData")
      .digest();

    console.log("secretKey", secretKey);

    // 4. Computing HMAC for the verification string.
    const putedHash = crypto
      .createHmac("sha256", secretKey)
      .update(dataCheckString)
      .digest("hex");

    console.log("putedHash", putedHash);
    // 5. Comparing the puted HMAC with hash.
    if (putedHash !== hash) {
      console.log("Verification failed!");
    } else {
      console.log("Hooray! Verification succeeded!");
      // 6. Checking the auth_date for its validity.
      const CURRENT_UNIX_TIME = Math.floor(Date.now() / 1000);
      const TIMEOUT_SECONDS = 3600; // Approximately 1 hour
      if (CURRENT_UNIX_TIME - Number(data.auth_date) > TIMEOUT_SECONDS) {
        console.log("Verification failed due to timeout");
      }

      // If all checks are successful, return true.
      console.log("Verification successful");
    }
}
Share Improve this question edited Jul 27, 2023 at 6:41 Roj 1,3521 gold badge11 silver badges24 bronze badges asked Jul 26, 2023 at 16:17 tron21tron21 351 silver badge6 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 6

According to the docs, the secret key is a HMAC-SHA-256 signature of the bot token with the literal "WebAppData" being the key, but you are doing exactly the opposite and calculating the secret key having the bot token as the key and the literal "WebAppData" as the payload.

This means everything should be fine if you calculate the secret key as follows:

const secretKey = crypto
  .createHmac("sha256", "WebAppData")
  .update(botToken)
  .digest();

You can also use the @twa.js collection of libraries that have already implemented this and other Web App logics for you.

发布评论

评论列表(0)

  1. 暂无评论