Files
Swarm/DysonNetwork.Sphere/Pages/Auth/Login.cshtml.cs
2025-07-08 23:55:31 +08:00

87 lines
3.0 KiB
C#

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.ComponentModel.DataAnnotations;
using DysonNetwork.Shared.Models;
using DysonNetwork.Pass.Auth;
using DysonNetwork.Shared.Services;
using DysonNetwork.Sphere.Connection;
using NodaTime;
using Microsoft.EntityFrameworkCore;
namespace DysonNetwork.Sphere.Pages.Auth
{
public class LoginModel(
DysonNetwork.Shared.Services.IAccountService accounts,
DysonNetwork.Pass.Auth.AuthService auth,
GeoIpService geo,
DysonNetwork.Shared.Services.IActionLogService als
) : PageModel
{
[BindProperty] [Required] public string Username { get; set; } = string.Empty;
[BindProperty]
[FromQuery]
public string? ReturnUrl { get; set; }
public void OnGet()
{
}
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
var account = await accounts.LookupAccount(Username);
if (account is null)
{
ModelState.AddModelError(string.Empty, "Account was not found.");
return Page();
}
// Store the return URL in TempData to preserve it during the login flow
if (!string.IsNullOrEmpty(ReturnUrl) && Url.IsLocalUrl(ReturnUrl))
{
TempData["ReturnUrl"] = ReturnUrl;
}
var ipAddress = HttpContext.Connection.RemoteIpAddress?.ToString();
var userAgent = HttpContext.Request.Headers.UserAgent.ToString();
var now = Instant.FromDateTimeUtc(DateTime.UtcNow);
var existingChallenge = await accounts.GetAuthChallenge(account.Id, ipAddress, userAgent, now);
if (existingChallenge is not null)
{
return RedirectToPage("Challenge", new { id = existingChallenge.Id });
}
var challenge = new Challenge
{
ExpiredAt = Instant.FromDateTimeUtc(DateTime.UtcNow.AddHours(1)),
StepTotal = await auth.DetectChallengeRisk(Request, account),
Platform = ChallengePlatform.Web,
Audiences = new List<string>(),
Scopes = new List<string>(),
IpAddress = ipAddress,
UserAgent = userAgent,
Location = geo.GetPointFromIp(ipAddress),
DeviceId = "web-browser",
AccountId = account.Id
}.Normalize();
await accounts.CreateAuthChallenge(challenge);
// If we have a return URL, pass it to the verify page
if (TempData.TryGetValue("ReturnUrl", out var returnUrl) && returnUrl is string url)
{
return RedirectToPage("SelectFactor", new { id = challenge.Id, returnUrl = url });
}
return RedirectToPage("SelectFactor", new { id = challenge.Id });
}
}
}