Index: ChapterX.Application/Auth/LoginHandler.cs
===================================================================
--- ChapterX.Application/Auth/LoginHandler.cs	(revision e294f7d2cedd462a923c69ae9f85c996b5377c69)
+++ ChapterX.Application/Auth/LoginHandler.cs	(revision e294f7d2cedd462a923c69ae9f85c996b5377c69)
@@ -0,0 +1,30 @@
+using ChapterX.Domain.Repositories;
+using MediatR;
+
+namespace ChapterX.Application.Auth
+{
+    public class LoginHandler : IRequestHandler<LoginRequest, LoginResponse>
+    {
+        private readonly IUserRepository _userRepository;
+        private readonly IJwtTokenService _jwtTokenService;
+
+        public LoginHandler(IUserRepository userRepository, IJwtTokenService jwtTokenService)
+        {
+            _userRepository = userRepository;
+            _jwtTokenService = jwtTokenService;
+        }
+
+        public async Task<LoginResponse> Handle(LoginRequest request, CancellationToken cancellationToken)
+        {
+            var user = await _userRepository.GetByEmailAsync(request.Email, cancellationToken)
+                ?? throw new UnauthorizedAccessException("Invalid email or password.");
+
+            if (!BCrypt.Net.BCrypt.Verify(request.Password, user.Password))
+                throw new UnauthorizedAccessException("Invalid email or password.");
+
+            var token = _jwtTokenService.GenerateToken(user);
+
+            return new LoginResponse(token, user.Id, user.Username, user.Email);
+        }
+    }
+}
