Issue:
I’m trying to verify the integrity of the hash provided by the Telegram WebApp authentication flow using Node.js, but the calculated hash never matches the provided hash. I’m using the correct bot token, and the parameters (userId
, username
, authDate
) seem to be correct and properly formatted. Despite this, the hash mismatch persists.
Telegram Parameters:
Here are the values I’m receiving from Telegram’s WebApp (logged from my frontend):
- User ID:
1234567890
- Username:
random_user123
- Auth Date:
1727134170
- Provided Hash:
55f0a395c4851512b31a797e33494801f4ff3f31ad99da3d92f13dfcccf678f0
Telegram Bot Token:
I’m using a bot token generated in the testnet environment, defined in
TELEGRAM_BOT_TOKEN
My Approach:
Following Telegram’s official documentation, I’m constructing the data_check_string
and calculating the HMAC-SHA256 hash as follows:
Node.js Code:
const crypto = require('crypto');
function verifyTelegramHash({ userId, username, authDate, hash }) {
if (!userId || !username || !authDate || !hash) {
throw new Error('Missing required parameters');
}
// Log parameters for debugging
console.log('Verifying Telegram hash with:', { userId, username, authDate, hash });
// Create the secret key using SHA-256 with the Telegram bot token
const secretKey = crypto.createHash('sha256')
.update('process.env.TELEGRAM_BOT_TOKEN', 'utf8')
.digest();
// Construct the dataCheckString in alphabetical order of the keys
const dataCheckString = `auth_date=${authDate}&id=${userId}&username=${username}`;
console.log('Data Check String:', dataCheckString);
// Calculate the hash using HMAC-SHA256
const calculatedHash = crypto
.createHmac('sha256', secretKey)
.update(dataCheckString)
.digest('hex');
console.log('Calculated Hash:', calculatedHash);
console.log('Provided Hash:', hash);
// Return whether the hashes match
return calculatedHash === hash;
}
// Example usage:
const isValid = verifyTelegramHash({
userId: '1234567890',
username: 'random_user123',
authDate: '1727134170',
hash: '55f0a395c4851512b31a797e33494801f4ff3f31ad99da3d92f13dfcccf678f0'
});
console.log('Is the hash valid?', isValid);
Output:
Here’s the output I’m seeing:
Verifying Telegram hash with: {
userId: '1234567890',
username: 'random_user123',
authDate: '1727134170',
hash: '55f0a395c4851512b31a797e33494801f4ff3f31ad99da3d92f13dfcccf678f0'
}
Data Check String: auth_date=1727134170&id=1234567890&username=random_user123
Calculated Hash: a97dc385905f5e09258ec19276751ab7fff55bc6bfe5e48a74151a502ac73b09
Provided Hash: 55f0a395c4851512b31a797e33494801f4ff3f31ad99da3d92f13dfcccf678f0
Is the hash valid? false
What I’ve Tried:
- Environment variables: I’ve hardcoded the bot token in the code to eliminate issues with environment variables.
- String formatting: I’ve ensured that the
dataCheckString
is correctly ordered and formatted (alphabetically by keys and no extra spaces). - Bot token: Double-checked that the bot token is correct (it’s the same one used in my Telegram bot, currently in test mode. I also tried the main one).
- Checked Telegram docs: I followed Telegram’s documentation to calculate the hash using HMAC-SHA256 and verify the signature.
Expected Behavior:
The calculated hash should match the hash provided by Telegram, but this is not happening.
Question:
What could be causing the mismatch between the calculated and provided hash? Is there something I’m missing in the way Telegram WebApp hashes should be calculated?