/// <summary> /// Creates a new user. /// </summary> /// <param name="login">A login name for the user to create.</param> /// <param name="name">A display name for the user to create.</param> /// <param name="password">A password for the user.</param> /// <returns>Returns the newly created user.</returns> /// <exception cref="UserAlreadyExistsException">Thrown if the login name is already taken.</exception> public User CreateUser(string login, string name, string password) { if (UserRepository.GetUser(login) != null) { throw new UserAlreadyExistsException(login); } // Hash & salt password, create user! (string hash, byte[] salt) = PasswordHashingService.HashAndSaltPassword(password); return(UserRepository.CreateUser(login, name, hash, salt)); }
/// <summary> /// Sets up the authentication service. /// </summary> /// <param name="loggerFactroy">Logger factory to create a local logger from.</param> /// <param name="passwordHashingService">Provides hashing functionality.</param> /// <param name="userRepository">User repository for access to user data.</param> /// <param name="configuration">App configuration for JWT signing information.</param> public AuthService(ILoggerFactory loggerFactroy, PasswordHashingService passwordHashingService, IUserRepository userRepository, IConfiguration configuration) { Logger = loggerFactroy.CreateLogger <AuthService>(); PasswordHashingService = passwordHashingService; UserRepository = userRepository; // Generate signing credentials SymmetricSecurityKey securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration.GetValue <string>("Jwt:Secret"))); SigningCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256); JwtLifetime = TimeSpan.FromMinutes(configuration.GetValue <int>("Jwt:LifetimeInMinutes")); JwtIssuer = configuration.GetValue <string>("Jwt:Issuer"); }
/// <summary> /// Changes a user's password. /// </summary> /// <param name="login">The login name of the user to change the password for.</param> /// <param name="previousPassword">The user's previous password for verification purposes.</param> /// <param name="newPassword">The new password to hash and store.</param> /// <exception cref="UnauthorizedAccessException">Thrown if the submitted old password is wrong!</exception> public void ChangePassword(string login, string previousPassword, string newPassword) { if (string.IsNullOrWhiteSpace(login)) { throw new ArgumentException("No valid login name provided.", nameof(login)); } if (string.IsNullOrWhiteSpace(previousPassword)) { throw new ArgumentException("No valid old password provided.", nameof(previousPassword)); } if (string.IsNullOrWhiteSpace(newPassword)) { throw new ArgumentException("No valid new password provided.", nameof(newPassword)); } // Get user to change the password for User user = UserRepository.GetUser(login); if (user == null) { throw new UserNotFoundException(login); } // Verify old password if (user.Password != PasswordHashingService.HashAndSaltPassword(previousPassword, user.Salt)) { throw new UnauthorizedAccessException(); } // Hash and salt new password (string hashedPassword, byte[] salt) = PasswordHashingService.HashAndSaltPassword(newPassword); user.Password = hashedPassword; user.Salt = salt; UserRepository.UpdateUser(user); }
/// <summary> /// Attempts to authenticate a user with a password and returns whether authentication was successful. /// </summary> /// <param name="login">Login name of the user to authenticate.</param> /// <param name="password">Password to attempt authentication with.</param> /// <param name="user">Contains the authenticated user if authentication is successful, else contains null.</param> /// <returns>Returns whether authentication was successful.</returns> /// <exception cref="UserNotFoundException">Thrown if no user with this login name could be found.</exception> public bool TryAuthenticateUser(string login, string password, out User user) { user = UserRepository.GetUser(login); return(user != null && user.Password == PasswordHashingService.HashAndSaltPassword(password, user.Salt)); }
/// <summary> /// Sets up the service. /// </summary> /// <param name="loggerFactroy">Factory to create a logger from.</param> /// <param name="passwordHashingService">Provides hashing features.</param> /// <param name="userRepository">Repository for user data.</param> public UserService(ILoggerFactory loggerFactroy, PasswordHashingService passwordHashingService, IUserRepository userRepository) { Logger = loggerFactroy.CreateLogger <UserService>(); PasswordHashingService = passwordHashingService; UserRepository = userRepository; }