Files
ospab.host/ospabhost/backend/src/modules/auth/turnstile.validator.ts
2026-01-01 16:56:34 +03:00

71 lines
2.0 KiB
TypeScript

import axios from 'axios';
import { logger } from '../../utils/logger';
const TURNSTILE_SECRET_KEY = process.env.TURNSTILE_SECRET_KEY;
const TURNSTILE_VERIFY_URL = 'https://challenges.cloudflare.com/turnstile/v0/siteverify';
export interface TurnstileValidationResult {
success: boolean;
errorCodes?: string[];
message?: string;
}
/**
* Валидирует токен Cloudflare Turnstile на стороне сервера
* @param token - токен, полученный от клиента
* @param remoteip - IP-адрес клиента (опционально)
* @returns результат валидации
*/
export async function validateTurnstileToken(
token: string,
remoteip?: string
): Promise<TurnstileValidationResult> {
if (!TURNSTILE_SECRET_KEY) {
logger.error('TURNSTILE_SECRET_KEY не найден в переменных окружения');
return {
success: false,
message: 'Turnstile не настроен на сервере',
};
}
if (!token) {
return {
success: false,
message: 'Токен капчи не предоставлен',
};
}
try {
const formData = new URLSearchParams();
formData.append('secret', TURNSTILE_SECRET_KEY);
formData.append('response', token);
if (remoteip) {
formData.append('remoteip', remoteip);
}
const response = await axios.post(TURNSTILE_VERIFY_URL, formData, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
});
const data = response.data;
if (data.success) {
return { success: true };
} else {
return {
success: false,
errorCodes: data['error-codes'],
message: 'Проверка капчи не прошла',
};
}
} catch (error) {
logger.error('Ошибка при валидации Turnstile:', error);
return {
success: false,
message: 'Ошибка при проверке капчи',
};
}
}