fix: stabilize mini app login and safe area
Deploy Telegram Bot / build-and-push (push) Successful in 3m53s
Deploy Telegram Bot / deploy (push) Successful in 17s

This commit is contained in:
2026-04-28 20:25:18 +03:00
parent 57c8714889
commit 2a76ec0fb8
14 changed files with 459 additions and 39 deletions
@@ -1,5 +1,6 @@
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using GmRelay.Web.Services;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
@@ -135,6 +136,125 @@ public sealed class TelegramAuthServiceTests
Assert.False(verified);
}
[Fact]
public void VerifyLoginPayload_ShouldAcceptValidTelegramWidgetCallbackPayload()
{
const string botToken = "test-bot-token";
var authDate = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
var values = new Dictionary<string, string>
{
["auth_date"] = authDate.ToString(),
["first_name"] = "Ada",
["id"] = "424242",
["last_name"] = "Lovelace",
["photo_url"] = "https://t.me/i/userpic/320/ada.jpg",
["username"] = "ada"
};
var payload = new TelegramLoginPayload(
424242,
"Ada",
"Lovelace",
"ada",
"https://t.me/i/userpic/320/ada.jpg",
authDate,
ComputeTelegramHash(botToken, values));
var service = new TelegramAuthService(CreateConfiguration(botToken));
var verified = service.VerifyLoginPayload(payload, out var telegramId, out var name);
Assert.True(verified);
Assert.Equal(424242L, telegramId);
Assert.Equal("Ada Lovelace", name);
}
[Fact]
public void VerifyLoginPayload_ShouldRejectTamperedCallbackHash()
{
var payload = new TelegramLoginPayload(
424242,
"Ada",
null,
null,
null,
DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
"00");
var service = new TelegramAuthService(CreateConfiguration("test-bot-token"));
var verified = service.VerifyLoginPayload(payload, out _, out _);
Assert.False(verified);
}
[Fact]
public void VerifyLoginPayload_ShouldRejectExpiredCallbackPayload()
{
const string botToken = "test-bot-token";
var authDate = DateTimeOffset.UtcNow.AddDays(-2).ToUnixTimeSeconds();
var values = new Dictionary<string, string>
{
["auth_date"] = authDate.ToString(),
["first_name"] = "Ada",
["id"] = "424242"
};
var payload = new TelegramLoginPayload(
424242,
"Ada",
null,
null,
null,
authDate,
ComputeTelegramHash(botToken, values));
var service = new TelegramAuthService(CreateConfiguration(botToken));
var verified = service.VerifyLoginPayload(payload, out _, out _);
Assert.False(verified);
}
[Fact]
public void VerifyLoginPayload_ShouldRejectMissingRequiredCallbackFields()
{
var payload = new TelegramLoginPayload(
0,
"",
null,
null,
null,
DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
"");
var service = new TelegramAuthService(CreateConfiguration("test-bot-token"));
var verified = service.VerifyLoginPayload(payload, out _, out _);
Assert.False(verified);
}
[Fact]
public void TelegramLoginPayload_ShouldDeserializeTelegramWidgetSnakeCaseJson()
{
var payload = JsonSerializer.Deserialize<TelegramLoginPayload>(
"""
{
"id": 424242,
"first_name": "Ada",
"last_name": "Lovelace",
"username": "ada",
"photo_url": "https://t.me/i/userpic/320/ada.jpg",
"auth_date": 1714300000,
"hash": "abcdef"
}
""");
Assert.NotNull(payload);
Assert.Equal(424242L, payload.Id);
Assert.Equal("Ada", payload.FirstName);
Assert.Equal("Lovelace", payload.LastName);
Assert.Equal("ada", payload.Username);
Assert.Equal("https://t.me/i/userpic/320/ada.jpg", payload.PhotoUrl);
Assert.Equal(1714300000L, payload.AuthDate);
Assert.Equal("abcdef", payload.Hash);
}
private static IConfiguration CreateConfiguration(string botToken) =>
new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string?>