fix: SameSite=Lax for auth cookie + bidirectional identity linking
- Change cookie auth SameSite from Strict to Lax so Discord OAuth callback can see existing Telegram auth session and perform linking instead of creating a new standalone Discord session (root cause of broken linking). - Add linking logic to /auth/telegram endpoint for Discord→Telegram linking. - Add Telegram Login Widget in Profile.razor for Discord users. - Add CookieAuthOptionsTests to verify Lax SameSite configuration. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+29
-10
@@ -61,7 +61,7 @@ builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationSc
|
||||
options.AccessDeniedPath = "/access-denied";
|
||||
options.Cookie.HttpOnly = true;
|
||||
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
|
||||
options.Cookie.SameSite = SameSiteMode.Strict;
|
||||
options.Cookie.SameSite = SameSiteMode.Lax;
|
||||
options.ExpireTimeSpan = TimeSpan.FromDays(7);
|
||||
options.SlidingExpiration = true;
|
||||
});
|
||||
@@ -123,19 +123,38 @@ app.MapHealthChecks("/alive", new HealthCheckOptions
|
||||
});
|
||||
|
||||
// Endpoint to handle Telegram Login callback
|
||||
app.MapGet("/auth/telegram", async (HttpContext context, TelegramAuthService authService) =>
|
||||
app.MapGet("/auth/telegram", async (HttpContext context, TelegramAuthService authService, ISessionStore sessionStore) =>
|
||||
{
|
||||
if (authService.Verify(context.Request.Query, out var telegramId, out var name))
|
||||
if (!authService.Verify(context.Request.Query, out var telegramId, out var name))
|
||||
return Results.Redirect("/login?error=auth_failed");
|
||||
|
||||
await sessionStore.UpsertPlayerAsync("Telegram", telegramId.ToString(System.Globalization.CultureInfo.InvariantCulture), name, null);
|
||||
|
||||
// If already authenticated via another platform, link instead of replacing session
|
||||
if (context.User.Identity?.IsAuthenticated == true
|
||||
&& context.User.TryGetPlatformIdentity(out var currentPlatform, out var currentExternalUserId)
|
||||
&& currentPlatform != "Telegram")
|
||||
{
|
||||
var authProperties = new AuthenticationProperties { IsPersistent = true };
|
||||
await context.SignInAsync(
|
||||
CookieAuthenticationDefaults.AuthenticationScheme,
|
||||
CreateTelegramPrincipal(telegramId, name),
|
||||
authProperties);
|
||||
return Results.Redirect("/");
|
||||
try
|
||||
{
|
||||
await sessionStore.LinkIdentityAsync(
|
||||
currentPlatform, currentExternalUserId,
|
||||
"Telegram", telegramId.ToString(System.Globalization.CultureInfo.InvariantCulture),
|
||||
name);
|
||||
return Results.Redirect("/profile?linked=telegram");
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
return Results.Redirect($"/profile?link_error={Uri.EscapeDataString(ex.Message)}");
|
||||
}
|
||||
}
|
||||
|
||||
return Results.Redirect("/login?error=auth_failed");
|
||||
var authProperties = new AuthenticationProperties { IsPersistent = true };
|
||||
await context.SignInAsync(
|
||||
CookieAuthenticationDefaults.AuthenticationScheme,
|
||||
CreateTelegramPrincipal(telegramId, name),
|
||||
authProperties);
|
||||
return Results.Redirect("/");
|
||||
});
|
||||
|
||||
app.MapPost("/auth/telegram-webapp", async (
|
||||
|
||||
Reference in New Issue
Block a user