do sessions in memory and also fix glaring security hole

This commit is contained in:
john 2025-06-01 23:28:00 +02:00
parent 7b6c155a73
commit f48b421500
31 changed files with 441 additions and 440 deletions

View file

@ -1,13 +1,10 @@
using Femto.Api.Auth;
using Femto.Api.Sessions;
using Femto.Common;
using Femto.Modules.Auth.Application;
using Femto.Modules.Auth.Application.Dto;
using Femto.Modules.Auth.Application.Interface.CreateSignupCode;
using Femto.Modules.Auth.Application.Interface.GetSignupCodesQuery;
using Femto.Modules.Auth.Application.Interface.Login;
using Femto.Modules.Auth.Application.Interface.RefreshUserSession;
using Femto.Modules.Auth.Application.Interface.Register;
using Femto.Modules.Auth.Application.Services;
using Femto.Modules.Auth.Contracts;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
@ -21,79 +18,85 @@ public class AuthController(
IAuthModule authModule,
IOptions<CookieSettings> cookieSettings,
ICurrentUserContext currentUserContext,
ILogger<AuthController> logger
ILogger<AuthController> logger,
IAuthService authService
) : ControllerBase
{
[HttpPost("login")]
public async Task<ActionResult<LoginResponse>> Login([FromBody] LoginRequest request)
public async Task<ActionResult<LoginResponse>> Login(
[FromBody] LoginRequest request,
CancellationToken cancellationToken
)
{
var result = await authModule.Command(new LoginCommand(request.Username, request.Password));
HttpContext.SetSession(result.SessionDto, result.User, logger);
return new LoginResponse(
result.User.Id,
result.User.Username,
result.User.Roles.Any(r => r == Role.SuperUser)
var user = await authService.GetUserWithCredentials(
request.Username,
request.Password,
cancellationToken
);
if (user is null)
return Forbid();
var session = await authService.CreateStrongSession(user.Id);
HttpContext.SetSession(session, user);
return new LoginResponse(user.Id, user.Username, user.Roles.Any(r => r == Role.SuperUser));
}
[HttpPost("register")]
public async Task<ActionResult<RegisterResponse>> Register([FromBody] RegisterRequest request)
{
var result = await authModule.Command(
var user = await authModule.Command(
new RegisterCommand(request.Username, request.Password, request.SignupCode)
);
HttpContext.SetSession(result.SessionDto, result.User, logger);
var session = await authService.CreateStrongSession(user.Id);
HttpContext.SetSession(session, user);
return new RegisterResponse(
result.User.Id,
result.User.Username,
result.User.Roles.Any(r => r == Role.SuperUser)
user.Id,
user.Username,
user.Roles.Any(r => r == Role.SuperUser)
);
}
[HttpDelete("session")]
public async Task<ActionResult> DeleteSession()
{
var currentUser = currentUserContext.CurrentUser;
var (sessionId, userId) = HttpContext.GetSessionInfo();
if (sessionId is not null)
{
await authService.DeleteSession(sessionId);
HttpContext.DeleteSession();
}
if (currentUser != null)
await authModule.Command(new DeauthenticateCommand(currentUser.Id, currentUser.SessionId, currentUser.RememberMeToken));
HttpContext.DeleteSession();
return Ok(new { });
}
[HttpGet("user/{userId}")]
[Authorize]
public async Task<ActionResult<RefreshUserResult>> RefreshUser(
public async Task<ActionResult<GetUserInfoResult>> GetUserInfo(
Guid userId,
CancellationToken cancellationToken
)
{
var currentUser = currentUserContext.CurrentUser!;
var currentUser = currentUserContext.CurrentUser;
try
{
var result = await authModule.Command(
new RefreshUserCommand(userId, currentUser),
cancellationToken
);
if (currentUser is null || currentUser.Id != userId)
return this.BadRequest();
return new RefreshUserResult(
result.User.Id,
result.User.Username,
result.User.Roles.Any(r => r == Role.SuperUser)
);
}
catch (Exception)
{
HttpContext.DeleteSession();
return this.Forbid();
}
var user = await authService.GetUserWithId(userId, cancellationToken);
if (user is null)
return this.BadRequest();
return new GetUserInfoResult(
user.Id,
user.Username,
user.Roles.Any(r => r == Role.SuperUser)
);
}
[HttpPost("signup-codes")]

View file

@ -0,0 +1,3 @@
namespace Femto.Api.Controllers.Auth;
public record GetUserInfoResult(Guid UserId, string Username, bool IsSuperUser);

View file

@ -1,3 +0,0 @@
namespace Femto.Api.Controllers.Auth;
public record RefreshUserResult(Guid UserId, string Username, bool IsSuperUser);