@@ -4,6 +4,8 @@ using Microsoft.Extensions.Configuration;
|
||||
using ROLAC.API.Data;
|
||||
using ROLAC.API.DTOs.Auth;
|
||||
using ROLAC.API.Entities;
|
||||
using ROLAC.API.Entities.Logging;
|
||||
using ROLAC.API.Services.Logging;
|
||||
|
||||
namespace ROLAC.API.Services;
|
||||
|
||||
@@ -13,6 +15,7 @@ public class AuthService : IAuthService
|
||||
private readonly ITokenService _tokenService;
|
||||
private readonly AppDbContext _db;
|
||||
private readonly IPermissionService _permissions;
|
||||
private readonly IAuditLogger _audit;
|
||||
private readonly int _refreshTokenExpiryDays;
|
||||
|
||||
public AuthService(
|
||||
@@ -20,12 +23,14 @@ public class AuthService : IAuthService
|
||||
ITokenService tokenService,
|
||||
AppDbContext db,
|
||||
IPermissionService permissions,
|
||||
IAuditLogger audit,
|
||||
IConfiguration config)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_tokenService = tokenService;
|
||||
_db = db;
|
||||
_permissions = permissions;
|
||||
_audit = audit;
|
||||
_refreshTokenExpiryDays = int.Parse(config["Jwt:RefreshTokenExpiryDays"] ?? "30");
|
||||
}
|
||||
|
||||
@@ -38,13 +43,22 @@ public class AuthService : IAuthService
|
||||
{
|
||||
var user = await _userManager.FindByEmailAsync(request.Email);
|
||||
if (user is null)
|
||||
{
|
||||
AuditLoginFailed(request.Email, "Unknown email", ipAddress);
|
||||
throw new UnauthorizedAccessException("Invalid credentials.");
|
||||
}
|
||||
|
||||
if (!await _userManager.CheckPasswordAsync(user, request.Password))
|
||||
{
|
||||
AuditLoginFailed(request.Email, "Wrong password", ipAddress, user.Id);
|
||||
throw new UnauthorizedAccessException("Invalid credentials.");
|
||||
}
|
||||
|
||||
if (!user.IsActive)
|
||||
{
|
||||
AuditLoginFailed(request.Email, "Account inactive", ipAddress, user.Id);
|
||||
throw new UnauthorizedAccessException("Account is inactive.");
|
||||
}
|
||||
|
||||
var roles = await _userManager.GetRolesAsync(user);
|
||||
var accessToken = _tokenService.GenerateAccessToken(user, roles);
|
||||
@@ -65,9 +79,22 @@ public class AuthService : IAuthService
|
||||
await _userManager.UpdateAsync(user);
|
||||
await _db.SaveChangesAsync();
|
||||
|
||||
_audit.Write(
|
||||
AuditActions.Login, AuditCategories.Security, LogLevelEnum.Information,
|
||||
entityName: nameof(AppUser), entityId: user.Id,
|
||||
summary: $"Login succeeded: {user.Email}",
|
||||
userId: user.Id, userEmail: user.Email, ipAddress: ipAddress);
|
||||
|
||||
return (await BuildResponseAsync(accessToken, user, roles), rawRefresh);
|
||||
}
|
||||
|
||||
private void AuditLoginFailed(string email, string reason, string? ipAddress, string? userId = null)
|
||||
=> _audit.Write(
|
||||
AuditActions.LoginFailed, AuditCategories.Security, LogLevelEnum.Warning,
|
||||
entityName: nameof(AppUser), entityId: userId,
|
||||
summary: $"Login failed ({reason}): {email}",
|
||||
userId: userId, userEmail: email, ipAddress: ipAddress);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Refresh
|
||||
// -------------------------------------------------------------------------
|
||||
@@ -124,6 +151,11 @@ public class AuthService : IAuthService
|
||||
{
|
||||
token.RevokedAt = DateTime.UtcNow;
|
||||
await _db.SaveChangesAsync();
|
||||
|
||||
_audit.Write(
|
||||
AuditActions.Logout, AuditCategories.Security, LogLevelEnum.Information,
|
||||
entityName: nameof(AppUser), entityId: token.UserId,
|
||||
summary: "Logout", userId: token.UserId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user