♻️ No idea, but errors all gone
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using DysonNetwork.Pass.Auth;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using DysonNetwork.Shared.Models;
|
||||
using DysonNetwork.Pass.Auth;
|
||||
using DysonNetwork.Sphere.Developer;
|
||||
using DysonNetwork.Pass.Auth.OidcProvider.Responses;
|
||||
|
||||
namespace DysonNetwork.Sphere.Pages.Auth;
|
||||
|
||||
|
||||
@@ -11,13 +11,13 @@ using Microsoft.EntityFrameworkCore;
|
||||
namespace DysonNetwork.Sphere.Pages.Auth
|
||||
{
|
||||
public class LoginModel(
|
||||
AppDatabase db,
|
||||
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]
|
||||
@@ -52,13 +52,7 @@ namespace DysonNetwork.Sphere.Pages.Auth
|
||||
var userAgent = HttpContext.Request.Headers.UserAgent.ToString();
|
||||
var now = Instant.FromDateTimeUtc(DateTime.UtcNow);
|
||||
|
||||
var existingChallenge = await db.AuthChallenges
|
||||
.Where(e => e.Account == account)
|
||||
.Where(e => e.IpAddress == ipAddress)
|
||||
.Where(e => e.UserAgent == userAgent)
|
||||
.Where(e => e.StepRemain > 0)
|
||||
.Where(e => e.ExpiredAt != null && now < e.ExpiredAt)
|
||||
.FirstOrDefaultAsync();
|
||||
var existingChallenge = await accounts.GetAuthChallenge(account.Id, ipAddress, userAgent, now);
|
||||
|
||||
if (existingChallenge is not null)
|
||||
{
|
||||
@@ -79,8 +73,7 @@ namespace DysonNetwork.Sphere.Pages.Auth
|
||||
AccountId = account.Id
|
||||
}.Normalize();
|
||||
|
||||
await db.AuthChallenges.AddAsync(challenge);
|
||||
await db.SaveChangesAsync();
|
||||
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)
|
||||
|
||||
@@ -8,10 +8,8 @@ using DysonNetwork.Pass.Account;
|
||||
namespace DysonNetwork.Sphere.Pages.Auth;
|
||||
|
||||
public class SelectFactorModel(
|
||||
AppDatabase db,
|
||||
AccountService accounts
|
||||
)
|
||||
: PageModel
|
||||
DysonNetwork.Shared.Services.IAccountService accounts
|
||||
) : PageModel
|
||||
{
|
||||
[BindProperty(SupportsGet = true)] public Guid Id { get; set; }
|
||||
[BindProperty(SupportsGet = true)] public string? ReturnUrl { get; set; }
|
||||
@@ -31,13 +29,11 @@ public class SelectFactorModel(
|
||||
|
||||
public async Task<IActionResult> OnPostSelectFactorAsync()
|
||||
{
|
||||
var challenge = await db.AuthChallenges
|
||||
.Include(e => e.Account)
|
||||
.FirstOrDefaultAsync(e => e.Id == Id);
|
||||
var challenge = await accounts.GetAuthChallenge(Id);
|
||||
|
||||
if (challenge == null) return NotFound();
|
||||
|
||||
var factor = await db.AccountAuthFactors.FindAsync(SelectedFactorId);
|
||||
var factor = await accounts.GetAccountAuthFactor(SelectedFactorId, challenge.Account.Id);
|
||||
if (factor?.EnabledAt == null || factor.Trustworthy <= 0)
|
||||
return BadRequest("Invalid authentication method.");
|
||||
|
||||
@@ -81,16 +77,11 @@ public class SelectFactorModel(
|
||||
|
||||
private async Task LoadChallengeAndFactors()
|
||||
{
|
||||
AuthChallenge = await db.AuthChallenges
|
||||
.Include(e => e.Account)
|
||||
.FirstOrDefaultAsync(e => e.Id == Id);
|
||||
AuthChallenge = await accounts.GetAuthChallenge(Id);
|
||||
|
||||
if (AuthChallenge != null)
|
||||
{
|
||||
AuthFactors = await db.AccountAuthFactors
|
||||
.Where(e => e.AccountId == AuthChallenge.Account.Id)
|
||||
.Where(e => e.EnabledAt != null && e.Trustworthy >= 1)
|
||||
.ToListAsync();
|
||||
AuthFactors = await accounts.GetAccountAuthFactors(AuthChallenge.Account.Id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
@page "/web/auth/challenge/{id:guid}/verify/{factorId:guid}"
|
||||
@using DysonNetwork.Shared.Models
|
||||
@using DysonNetwork.Shared.Models
|
||||
@model DysonNetwork.Sphere.Pages.Auth.VerifyFactorModel
|
||||
@{
|
||||
ViewData["Title"] = "Verify Your Identity";
|
||||
|
||||
@@ -4,20 +4,17 @@ using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using DysonNetwork.Shared.Services;
|
||||
using DysonNetwork.Shared.Services;
|
||||
using NodaTime;
|
||||
|
||||
namespace DysonNetwork.Sphere.Pages.Auth
|
||||
{
|
||||
public class VerifyFactorModel(
|
||||
AppDatabase db,
|
||||
DysonNetwork.Shared.Services.IAccountService accountService,
|
||||
IAccountService accountService,
|
||||
DysonNetwork.Pass.Auth.AuthService authService,
|
||||
DysonNetwork.Shared.Services.IActionLogService actionLogService,
|
||||
IConfiguration configuration,
|
||||
IHttpClientFactory httpClientFactory
|
||||
)
|
||||
: PageModel
|
||||
IActionLogService actionLogService,
|
||||
IConfiguration configuration
|
||||
) : PageModel
|
||||
{
|
||||
[BindProperty(SupportsGet = true)] public Guid Id { get; set; }
|
||||
|
||||
@@ -55,30 +52,36 @@ namespace DysonNetwork.Sphere.Pages.Auth
|
||||
|
||||
try
|
||||
{
|
||||
if (await accounts.VerifyFactorCode(Factor, Code))
|
||||
if (await accountService.VerifyFactorCode(Factor, Code))
|
||||
{
|
||||
AuthChallenge.StepRemain -= Factor.Trustworthy;
|
||||
AuthChallenge.StepRemain = Math.Max(0, AuthChallenge.StepRemain);
|
||||
AuthChallenge.BlacklistFactors.Add(Factor.Id);
|
||||
db.Update(AuthChallenge);
|
||||
|
||||
als.CreateActionLogFromRequest(ActionLogType.ChallengeSuccess,
|
||||
await actionLogService.CreateActionLogFromRequest(ActionLogType.ChallengeSuccess,
|
||||
new Dictionary<string, object>
|
||||
{
|
||||
{ "challenge_id", AuthChallenge.Id },
|
||||
{ "factor_id", Factor?.Id.ToString() ?? string.Empty }
|
||||
}, Request, AuthChallenge.Account);
|
||||
},
|
||||
Request.HttpContext.Connection.RemoteIpAddress?.ToString(),
|
||||
Request.Headers.UserAgent.ToString(),
|
||||
AuthChallenge.Account
|
||||
);
|
||||
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
if (AuthChallenge.StepRemain == 0)
|
||||
{
|
||||
als.CreateActionLogFromRequest(ActionLogType.NewLogin,
|
||||
await actionLogService.CreateActionLogFromRequest(ActionLogType.NewLogin,
|
||||
new Dictionary<string, object>
|
||||
{
|
||||
{ "challenge_id", AuthChallenge.Id },
|
||||
{ "account_id", AuthChallenge.AccountId }
|
||||
}, Request, AuthChallenge.Account);
|
||||
},
|
||||
Request.HttpContext.Connection.RemoteIpAddress?.ToString(),
|
||||
Request.Headers.UserAgent.ToString(),
|
||||
AuthChallenge.Account
|
||||
);
|
||||
|
||||
return await ExchangeTokenAndRedirect();
|
||||
}
|
||||
@@ -98,16 +101,18 @@ namespace DysonNetwork.Sphere.Pages.Auth
|
||||
{
|
||||
if (AuthChallenge != null)
|
||||
{
|
||||
AuthChallenge.FailedAttempts++;
|
||||
db.Update(AuthChallenge);
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
als.CreateActionLogFromRequest(ActionLogType.ChallengeFailure,
|
||||
await actionLogService.CreateActionLogFromRequest(ActionLogType.ChallengeFailure,
|
||||
new Dictionary<string, object>
|
||||
{
|
||||
{ "challenge_id", AuthChallenge.Id },
|
||||
{ "factor_id", Factor?.Id.ToString() ?? string.Empty }
|
||||
}, Request, AuthChallenge.Account);
|
||||
},
|
||||
Request.HttpContext.Connection.RemoteIpAddress?.ToString(),
|
||||
Request.Headers.UserAgent.ToString(),
|
||||
AuthChallenge.Account
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -118,47 +123,30 @@ namespace DysonNetwork.Sphere.Pages.Auth
|
||||
|
||||
private async Task LoadChallengeAndFactor()
|
||||
{
|
||||
AuthChallenge = await db.AuthChallenges
|
||||
.Include(e => e.Account)
|
||||
.FirstOrDefaultAsync(e => e.Id == Id);
|
||||
AuthChallenge = await accountService.GetAuthChallenge(Id);
|
||||
|
||||
if (AuthChallenge?.Account != null)
|
||||
{
|
||||
Factor = await db.AccountAuthFactors
|
||||
.FirstOrDefaultAsync(e => e.Id == FactorId &&
|
||||
e.AccountId == AuthChallenge.Account.Id &&
|
||||
e.EnabledAt != null &&
|
||||
e.Trustworthy > 0);
|
||||
Factor = await accountService.GetAccountAuthFactor(FactorId, AuthChallenge.Account.Id);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<IActionResult> ExchangeTokenAndRedirect()
|
||||
{
|
||||
var challenge = await db.AuthChallenges
|
||||
.Include(e => e.Account)
|
||||
.FirstOrDefaultAsync(e => e.Id == Id);
|
||||
var challenge = await accountService.GetAuthChallenge(Id);
|
||||
|
||||
if (challenge == null) return BadRequest("Authorization code not found or expired.");
|
||||
if (challenge.StepRemain != 0) return BadRequest("Challenge not yet completed.");
|
||||
|
||||
var session = await db.AuthSessions
|
||||
.FirstOrDefaultAsync(e => e.ChallengeId == challenge.Id);
|
||||
var session = await accountService.CreateSession(
|
||||
Instant.FromDateTimeUtc(DateTime.UtcNow),
|
||||
Instant.FromDateTimeUtc(DateTime.UtcNow.AddDays(30)),
|
||||
challenge.Account,
|
||||
challenge
|
||||
);
|
||||
|
||||
if (session == null)
|
||||
{
|
||||
session = new Session
|
||||
{
|
||||
LastGrantedAt = Instant.FromDateTimeUtc(DateTime.UtcNow),
|
||||
ExpiredAt = Instant.FromDateTimeUtc(DateTime.UtcNow.AddDays(30)),
|
||||
Account = challenge.Account,
|
||||
Challenge = challenge,
|
||||
};
|
||||
db.AuthSessions.Add(session);
|
||||
await db.SaveChangesAsync();
|
||||
}
|
||||
|
||||
var token = auth.CreateToken(session);
|
||||
Response.Cookies.Append(AuthConstants.CookieTokenName, token, new CookieOptions
|
||||
var token = authService.CreateToken(session);
|
||||
Response.Cookies.Append(accountService.GetAuthCookieTokenName(), token, new CookieOptions
|
||||
{
|
||||
HttpOnly = true,
|
||||
Secure = !configuration.GetValue<bool>("Debug"),
|
||||
|
||||
Reference in New Issue
Block a user