feat(API): Adds Password hashing
This commit is contained in:
@@ -2,6 +2,8 @@ using Lactose.Dtos;
|
|||||||
using Lactose.Models;
|
using Lactose.Models;
|
||||||
using Lactose.Repositories;
|
using Lactose.Repositories;
|
||||||
using Lactose.Services;
|
using Lactose.Services;
|
||||||
|
using Lactose.Types;
|
||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace Lactose.Controllers;
|
namespace Lactose.Controllers;
|
||||||
@@ -10,7 +12,7 @@ namespace Lactose.Controllers;
|
|||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/[controller]")]
|
[Route("api/[controller]")]
|
||||||
|
|
||||||
public class AuthController(ILogger<AuthController> logger,LactoseAuthenticationService authService, IUserRepository userRepository) : ControllerBase{
|
public class AuthController(ILogger<AuthController> logger,LactoseAuthenticationService authService, IUserRepository userRepository, PasswordHasher<User> passwordHasher) : ControllerBase{
|
||||||
|
|
||||||
//TODO: Reply with Authentication Result
|
//TODO: Reply with Authentication Result
|
||||||
[HttpPost("login")]
|
[HttpPost("login")]
|
||||||
@@ -28,8 +30,18 @@ public class AuthController(ILogger<AuthController> logger,LactoseAuthentication
|
|||||||
return NotFound("User or Password was wrong");
|
return NotFound("User or Password was wrong");
|
||||||
}
|
}
|
||||||
|
|
||||||
//check password with
|
PasswordVerificationResult result = passwordHasher.VerifyHashedPassword(user, user.Password, userDto.Password);
|
||||||
|
|
||||||
|
switch(result) {
|
||||||
|
case PasswordVerificationResult.Failed:
|
||||||
|
return NotFound("User or Password was wrong");
|
||||||
|
case PasswordVerificationResult.SuccessRehashNeeded:
|
||||||
|
user.Password = passwordHasher.HashPassword(user,userDto.Password);
|
||||||
|
userRepository.Save();
|
||||||
|
break;
|
||||||
|
case PasswordVerificationResult.Success:
|
||||||
|
break;
|
||||||
|
}
|
||||||
return authService.GenerateToken(user);
|
return authService.GenerateToken(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,16 +57,19 @@ public class AuthController(ILogger<AuthController> logger,LactoseAuthentication
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (userRepository.FindByEmail(userDto.Email)!=null || userRepository.FindByUsername(userDto.Username)!=null) {
|
if (userRepository.FindByEmail(userDto.Email)!=null || userRepository.FindByUsername(userDto.Username)!=null) {
|
||||||
//search for user in database (by email)
|
|
||||||
return Conflict("User already exists");
|
return Conflict("User already exists");
|
||||||
}
|
}
|
||||||
|
|
||||||
var user = new User {
|
var user = new User {
|
||||||
Username = userDto.Username,
|
Username = userDto.Username,
|
||||||
Email = userDto.Email,
|
Email = userDto.Email,
|
||||||
Password = userDto.Password
|
AccessLevel = EAccessLevel.User,
|
||||||
|
CreatedAt = DateTime.Now,
|
||||||
|
UpdatedAt = DateTime.Now
|
||||||
};
|
};
|
||||||
|
|
||||||
|
user.Password = passwordHasher.HashPassword(user, userDto.Password);
|
||||||
|
|
||||||
userRepository.Insert(user);
|
userRepository.Insert(user);
|
||||||
userRepository.Save();
|
userRepository.Save();
|
||||||
return Ok(user.Id);
|
return Ok(user.Id);
|
||||||
@@ -63,6 +78,7 @@ public class AuthController(ILogger<AuthController> logger,LactoseAuthentication
|
|||||||
[HttpPost()]
|
[HttpPost()]
|
||||||
public ActionResult<LactoseAuthenticationService> Check() {
|
public ActionResult<LactoseAuthenticationService> Check() {
|
||||||
// this.User;
|
// this.User;
|
||||||
|
|
||||||
var principal = this.User;
|
var principal = this.User;
|
||||||
var identity = authService.GetUserData(this.User);
|
var identity = authService.GetUserData(this.User);
|
||||||
return Ok(identity);
|
return Ok(identity);
|
||||||
@@ -70,6 +86,9 @@ public class AuthController(ILogger<AuthController> logger,LactoseAuthentication
|
|||||||
|
|
||||||
[HttpPost("logout")]
|
[HttpPost("logout")]
|
||||||
public ActionResult Logout(){
|
public ActionResult Logout(){
|
||||||
return Unauthorized();
|
var identity = authService.GetUserData(this.User);
|
||||||
|
if (identity == null) return Unauthorized();
|
||||||
|
authService.RevokeAccess(identity.Id);
|
||||||
|
return Ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,19 +1,15 @@
|
|||||||
using Lactose.Configuration;
|
using Lactose.Configuration;
|
||||||
using Lactose.Models;
|
using Lactose.Models;
|
||||||
using Lactose.Types;
|
using Lactose.Types;
|
||||||
using Microsoft.AspNetCore.Authentication;
|
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
using System.IdentityModel.Tokens.Jwt;
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using System.Security.Principal;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace Lactose.Services;
|
namespace Lactose.Services;
|
||||||
|
|
||||||
public class LactoseAuthenticationService(ILogger<LactoseAuthenticationService> logger,IOptions<SignKeyConfiguration> keyOption) {
|
public class LactoseAuthenticationService(ILogger<LactoseAuthenticationService> logger,IOptions<SignKeyConfiguration> keyOption) {
|
||||||
|
|
||||||
|
|
||||||
public string GenerateToken(User user) {
|
public string GenerateToken(User user) {
|
||||||
var handler = new JwtSecurityTokenHandler();
|
var handler = new JwtSecurityTokenHandler();
|
||||||
|
|
||||||
@@ -64,7 +60,10 @@ public class LactoseAuthenticationService(ILogger<LactoseAuthenticationService>
|
|||||||
email,
|
email,
|
||||||
(EAccessLevel)Enum.Parse(typeof(EAccessLevel),eAccessLevel)
|
(EAccessLevel)Enum.Parse(typeof(EAccessLevel),eAccessLevel)
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RevokeAccess(Guid id) {
|
||||||
|
//Revoke access for user
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
using Lactose.Models;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
|
|
||||||
namespace Lactose.Services;
|
|
||||||
|
|
||||||
public class PasswordHasher(PasswordHasher<string> passwordHasher) : IPasswordHasher<User> {
|
|
||||||
public string HashPassword(User user, string password) {
|
|
||||||
string salt = GetSalt(user);
|
|
||||||
return passwordHasher.HashPassword(salt, password);
|
|
||||||
}
|
|
||||||
|
|
||||||
static string GetSalt(User user) {
|
|
||||||
return user.Password.Substring(user.Password.LastIndexOf('.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
public PasswordVerificationResult VerifyHashedPassword(User user, string hashedPassword, string providedPassword) {
|
|
||||||
string salt = GetSalt(user);
|
|
||||||
return passwordHasher.HashPassword(salt, providedPassword) == hashedPassword?
|
|
||||||
PasswordVerificationResult.Success : PasswordVerificationResult.Failed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user