Files
GmRelayBot/src/GmRelay.Web/Services/TelegramAuthService.cs
T
Toutsu 176f1105ab
Deploy Telegram Bot / build-and-push (push) Successful in 5m19s
Deploy Telegram Bot / deploy (push) Successful in 10s
v1.1.0: Полный редизайн фронтенда, усиление безопасности и обновление версии
2026-04-21 15:21:18 +03:00

59 lines
2.0 KiB
C#

using System.Security.Cryptography;
using System.Text;
namespace GmRelay.Web.Services;
public sealed class TelegramAuthService(IConfiguration configuration)
{
public bool Verify(IQueryCollection query, out long telegramId, out string name)
{
telegramId = 0;
name = string.Empty;
if (!query.TryGetValue("hash", out var hash))
return false;
var token = configuration["Telegram__BotToken"] ?? configuration["Telegram:BotToken"];
if (string.IsNullOrEmpty(token))
return false;
// 1. Sort and join
var dataCheckList = query
.Where(x => x.Key != "hash")
.OrderBy(x => x.Key)
.Select(x => $"{x.Key}={x.Value}")
.ToList();
var dataCheckString = string.Join("\n", dataCheckList);
// 2. Compute Secret Key (static method — no IDisposable needed)
var secretKey = SHA256.HashData(Encoding.UTF8.GetBytes(token));
// 3. Compute Hash (static method — no IDisposable needed)
var computedHashBytes = HMACSHA256.HashData(secretKey, Encoding.UTF8.GetBytes(dataCheckString));
// 4. Timing-safe comparison to prevent timing attacks
var hashBytes = Convert.FromHexString(hash.ToString());
if (!CryptographicOperations.FixedTimeEquals(computedHashBytes, hashBytes))
return false;
// 5. Check expiration (auth_date)
if (query.TryGetValue("auth_date", out var authDateStr) && long.TryParse(authDateStr, out var authDate))
{
var now = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
if (now - authDate > 86400) // 24 hours
return false;
}
if (query.TryGetValue("id", out var idStr) && long.TryParse(idStr, out telegramId))
{
var firstName = query["first_name"].ToString();
var lastName = query["last_name"].ToString();
name = string.IsNullOrWhiteSpace(lastName) ? firstName : $"{firstName} {lastName}";
return true;
}
return false;
}
}