68 lines
1.8 KiB
JavaScript
68 lines
1.8 KiB
JavaScript
const crypto = require('crypto');
|
|
const config = require('../config');
|
|
|
|
const MAX_AUTH_AGE_SECONDS = 5 * 60;
|
|
|
|
function validateAndParseInitData(initData, req) {
|
|
if (!config.telegramBotToken) {
|
|
throw new Error('TELEGRAM_BOT_TOKEN не настроен');
|
|
}
|
|
|
|
const params = new URLSearchParams(initData);
|
|
const hash = params.get('hash');
|
|
const authDate = Number(params.get('auth_date'));
|
|
|
|
if (!hash) {
|
|
throw new Error('Отсутствует hash в initData');
|
|
}
|
|
|
|
if (!authDate) {
|
|
throw new Error('Отсутствует auth_date в initData');
|
|
}
|
|
|
|
const dataCheck = [];
|
|
for (const [key, value] of params.entries()) {
|
|
if (key === 'hash') continue;
|
|
dataCheck.push(`${key}=${value}`);
|
|
}
|
|
|
|
dataCheck.sort((a, b) => a.localeCompare(b));
|
|
const dataCheckString = dataCheck.join('\n');
|
|
|
|
const secretKey = crypto.createHmac('sha256', 'WebAppData').update(config.telegramBotToken).digest();
|
|
const calculatedHash = crypto.createHmac('sha256', secretKey).update(dataCheckString).digest('hex');
|
|
|
|
if (calculatedHash !== hash) {
|
|
throw new Error('Неверная подпись initData');
|
|
}
|
|
|
|
const now = Math.floor(Date.now() / 1000);
|
|
if (Math.abs(now - authDate) > MAX_AUTH_AGE_SECONDS) {
|
|
throw new Error('Данные авторизации устарели');
|
|
}
|
|
|
|
const userParam = params.get('user');
|
|
|
|
if (!userParam) {
|
|
throw new Error('Отсутствует пользователь в initData');
|
|
}
|
|
|
|
let telegramUser;
|
|
try {
|
|
telegramUser = JSON.parse(userParam);
|
|
} catch (error) {
|
|
throw new Error('Некорректный формат user в initData');
|
|
}
|
|
|
|
if (!telegramUser || !telegramUser.id) {
|
|
throw new Error('Отсутствует ID пользователя в initData');
|
|
}
|
|
|
|
return { params, telegramUser };
|
|
}
|
|
|
|
module.exports = {
|
|
validateAndParseInitData
|
|
};
|
|
|