From 951500ca91c4b05799dbabb0dc60fdd78b52f7ce Mon Sep 17 00:00:00 2001 From: Oliver Booth Date: Sat, 24 Feb 2024 15:04:03 +0000 Subject: [PATCH] refactor: validate session separately --- OliverBooth/Controllers/AdminController.cs | 2 +- OliverBooth/Pages/Admin/Index.cshtml.cs | 8 +++++- OliverBooth/Services/ISessionService.cs | 21 ++++++++++---- OliverBooth/Services/SessionService.cs | 33 +++++++++++----------- 4 files changed, 40 insertions(+), 24 deletions(-) diff --git a/OliverBooth/Controllers/AdminController.cs b/OliverBooth/Controllers/AdminController.cs index 6fa83c3..84d4f24 100644 --- a/OliverBooth/Controllers/AdminController.cs +++ b/OliverBooth/Controllers/AdminController.cs @@ -69,7 +69,7 @@ public sealed class AdminController : ControllerBase [HttpGet("logout")] public IActionResult Logout() { - if (_sessionService.TryGetSession(Request, out ISession? session, true)) + if (_sessionService.TryGetSession(Request, out ISession? session)) _sessionService.DeleteSession(session); return _sessionService.DeleteSessionCookie(Response); diff --git a/OliverBooth/Pages/Admin/Index.cshtml.cs b/OliverBooth/Pages/Admin/Index.cshtml.cs index e2be20a..64ac6d1 100644 --- a/OliverBooth/Pages/Admin/Index.cshtml.cs +++ b/OliverBooth/Pages/Admin/Index.cshtml.cs @@ -23,12 +23,18 @@ public class Index : PageModel public IActionResult OnGet() { - if (!_sessionService.TryGetSession(HttpContext.Request, out ISession? session)) + if (!_sessionService.TryGetSession(Request, out ISession? session)) { _logger.LogDebug("Session not found; redirecting"); return _sessionService.DeleteSessionCookie(Response); } + if (!_sessionService.ValidateSession(Request, session)) + { + _logger.LogDebug("Session invalid; redirecting"); + return _sessionService.DeleteSessionCookie(Response); + } + if (!_userService.TryGetUser(session.UserId, out IUser? user)) { _logger.LogDebug("User not found; redirecting"); diff --git a/OliverBooth/Services/ISessionService.cs b/OliverBooth/Services/ISessionService.cs index e087bcb..166002e 100644 --- a/OliverBooth/Services/ISessionService.cs +++ b/OliverBooth/Services/ISessionService.cs @@ -1,4 +1,5 @@ using System.Diagnostics.CodeAnalysis; +using Microsoft.AspNetCore.Mvc; using OliverBooth.Data.Web; using ISession = OliverBooth.Data.Blog.ISession; @@ -47,10 +48,20 @@ public interface ISessionService /// When this method returns, contains the session with the specified request, if the user is found; otherwise, /// . /// - /// - /// to include invalid sessions in the search; otherwise, . - /// /// if the session was found; otherwise, . /// is . - bool TryGetSession(HttpRequest request, [NotNullWhen(true)] out ISession? session, bool includeInvalid = false); -} \ No newline at end of file + bool TryGetSession(HttpRequest request, [NotNullWhen(true)] out ISession? session); + + /// + /// Validates the session with the incoming HTTP request. + /// + /// The HTTP request. + /// The session. + /// if the session is valid; otherwise, . + /// + /// is . + /// -or- + /// is . + /// + bool ValidateSession(HttpRequest request, ISession session); +} diff --git a/OliverBooth/Services/SessionService.cs b/OliverBooth/Services/SessionService.cs index 84340af..faa1290 100644 --- a/OliverBooth/Services/SessionService.cs +++ b/OliverBooth/Services/SessionService.cs @@ -1,5 +1,6 @@ using System.Diagnostics.CodeAnalysis; using System.Net; +using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.ChangeTracking; using OliverBooth.Data.Blog; @@ -71,8 +72,7 @@ internal sealed class SessionService : ISessionService } /// - public bool TryGetSession(HttpRequest request, [NotNullWhen(true)] out ISession? session, - bool includeInvalid = false) + public bool TryGetSession(HttpRequest request, [NotNullWhen(true)] out ISession? session) { if (request is null) throw new ArgumentNullException(nameof(request)); @@ -88,12 +88,20 @@ internal sealed class SessionService : ISessionService return false; var sessionId = new Guid(bytes); - if (!TryGetSession(sessionId, out session)) - return false; + return TryGetSession(sessionId, out session); + } - if (!includeInvalid && session.Expires >= DateTimeOffset.UtcNow) + /// + public bool ValidateSession(HttpRequest request, ISession session) + { + if (request is null) throw new ArgumentNullException(nameof(request)); + if (session is null) throw new ArgumentNullException(nameof(session)); + + IPAddress? remoteIpAddress = request.HttpContext.Connection.RemoteIpAddress; + if (remoteIpAddress is null) return false; + + if (session.Expires >= DateTimeOffset.UtcNow) { - session = null; return false; } @@ -101,22 +109,13 @@ internal sealed class SessionService : ISessionService Span sessionAddressBytes = stackalloc byte[16]; if (!remoteIpAddress.TryWriteBytes(remoteAddressBytes, out _) || !session.IpAddress.TryWriteBytes(sessionAddressBytes, out _)) - { - session = null; return false; - } - if (!includeInvalid && !remoteAddressBytes.SequenceEqual(sessionAddressBytes)) - { - session = null; + if (!remoteAddressBytes.SequenceEqual(sessionAddressBytes)) return false; - } - if (!includeInvalid && _userService.TryGetUser(session.UserId, out _)) - { - session = null; + if (_userService.TryGetUser(session.UserId, out _)) return false; - } return true; }