2026-02-02 04:48:42 -06:00
|
|
|
|
|
|
|
|
using FiscalOS.Core.Identity;
|
|
|
|
|
|
2026-02-01 04:27:06 -06:00
|
|
|
namespace FiscalOS.API.Login;
|
|
|
|
|
|
|
|
|
|
internal static class Endpoint
|
|
|
|
|
{
|
|
|
|
|
private const string Route = "/login";
|
|
|
|
|
|
|
|
|
|
public static RouteHandlerBuilder MapLoginEndpoint(this WebApplication app)
|
|
|
|
|
{
|
|
|
|
|
return app.MapPost(Route, HandleAsync);
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-01 08:07:23 -06:00
|
|
|
private static async Task<IResult> HandleAsync(
|
|
|
|
|
[FromBody] LoginRequest loginRequest,
|
2026-02-02 06:32:14 -06:00
|
|
|
[FromServices] HttpContext httpContext,
|
2026-02-02 04:48:42 -06:00
|
|
|
[FromServices] AppDbContext appDbContext,
|
2026-02-02 06:32:14 -06:00
|
|
|
[FromServices] IPasswordHasher passwordHasher,
|
|
|
|
|
[FromServices] TokenService tokenService
|
2026-02-01 08:07:23 -06:00
|
|
|
)
|
2026-02-01 04:27:06 -06:00
|
|
|
{
|
2026-02-01 08:07:23 -06:00
|
|
|
var user = await appDbContext.Users.SingleOrDefaultAsync(u => u.Username == loginRequest.Username);
|
|
|
|
|
|
|
|
|
|
if (user is null)
|
|
|
|
|
{
|
|
|
|
|
return Results.Unauthorized();
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-02 04:48:42 -06:00
|
|
|
var isCorrectPassword = passwordHasher.Verify(loginRequest.Password, user.HashedPassword);
|
|
|
|
|
|
|
|
|
|
if (isCorrectPassword is false)
|
|
|
|
|
{
|
|
|
|
|
return Results.Unauthorized();
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-02 06:32:14 -06:00
|
|
|
var accessToken = tokenService.GenerateAccessToken(user);
|
|
|
|
|
|
|
|
|
|
var refreshToken = tokenService.GenerateRefreshToken(user);
|
|
|
|
|
await appDbContext.RefreshTokens.AddAsync(refreshToken);
|
|
|
|
|
await appDbContext.SaveChangesAsync();
|
|
|
|
|
|
|
|
|
|
httpContext.Response.Cookies.Append(
|
|
|
|
|
"fiscalos_refresh_cookie",
|
|
|
|
|
refreshToken.Token,
|
|
|
|
|
new CookieOptions
|
|
|
|
|
{
|
|
|
|
|
HttpOnly = true,
|
|
|
|
|
Expires = refreshToken.ExpiresAt,
|
|
|
|
|
// TODO: Revisit when decided
|
|
|
|
|
// on hosting setup
|
|
|
|
|
SameSite = SameSiteMode.None,
|
|
|
|
|
Secure = true
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return Results.Ok(new Response(accessToken));
|
2026-02-01 04:27:06 -06:00
|
|
|
}
|
|
|
|
|
}
|