|
|
|
@ -29,7 +29,9 @@ using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Security.Cryptography;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using AutoMapper;
|
|
|
|
|
using Microsoft.AspNetCore.Cryptography.KeyDerivation;
|
|
|
|
|
using Ombi.Core.Models;
|
|
|
|
|
using Ombi.Store.Entities;
|
|
|
|
|
using Ombi.Store.Repository;
|
|
|
|
|
|
|
|
|
@ -37,38 +39,43 @@ namespace Ombi.Core.IdentityResolver
|
|
|
|
|
{
|
|
|
|
|
public class UserIdentityManager : IUserIdentityManager
|
|
|
|
|
{
|
|
|
|
|
public UserIdentityManager(IUserRepository userRepository)
|
|
|
|
|
public UserIdentityManager(IUserRepository userRepository, IMapper mapper)
|
|
|
|
|
{
|
|
|
|
|
UserRepository = userRepository;
|
|
|
|
|
Mapper = mapper;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private IMapper Mapper { get; }
|
|
|
|
|
private IUserRepository UserRepository { get; }
|
|
|
|
|
|
|
|
|
|
public async Task<bool> CredentialsValid(string username, string password)
|
|
|
|
|
{
|
|
|
|
|
var user = await UserRepository.GetUser(username);
|
|
|
|
|
var hashedPass = HashPassword(password);
|
|
|
|
|
var hash = HashPassword(password, user.Salt);
|
|
|
|
|
|
|
|
|
|
return hashedPass.Equals(user.Password);
|
|
|
|
|
return hash.HashedPass.Equals(user.Password);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task<User> GetUser(string username)
|
|
|
|
|
public async Task<UserDto> GetUser(string username)
|
|
|
|
|
{
|
|
|
|
|
return await UserRepository.GetUser(username);
|
|
|
|
|
return Mapper.Map<UserDto>(await UserRepository.GetUser(username));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task<IEnumerable<User>> GetUsers()
|
|
|
|
|
public async Task<IEnumerable<UserDto>> GetUsers()
|
|
|
|
|
{
|
|
|
|
|
return await UserRepository.GetUsers();
|
|
|
|
|
return Mapper.Map<List<UserDto>>(await UserRepository.GetUsers());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task CreateUser(User user)
|
|
|
|
|
public async Task CreateUser(UserDto userDto)
|
|
|
|
|
{
|
|
|
|
|
user.Password = HashPassword(user.Password);
|
|
|
|
|
var user = Mapper.Map<User>(userDto);
|
|
|
|
|
var result = HashPassword(user.Password);
|
|
|
|
|
user.Password = result.HashedPass;
|
|
|
|
|
user.Salt = result.Salt;
|
|
|
|
|
await UserRepository.CreateUser(user);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private string HashPassword(string password)
|
|
|
|
|
private UserHash HashPassword(string password)
|
|
|
|
|
{
|
|
|
|
|
// generate a 128-bit salt using a secure PRNG
|
|
|
|
|
byte[] salt = new byte[128 / 8];
|
|
|
|
@ -76,6 +83,12 @@ namespace Ombi.Core.IdentityResolver
|
|
|
|
|
{
|
|
|
|
|
rng.GetBytes(salt);
|
|
|
|
|
}
|
|
|
|
|
return HashPassword(password, salt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private UserHash HashPassword(string password, byte[] salt)
|
|
|
|
|
{
|
|
|
|
|
// derive a 256-bit subkey (use HMACSHA1 with 10,000 iterations)
|
|
|
|
|
var hashed = Convert.ToBase64String(KeyDerivation.Pbkdf2(
|
|
|
|
|
password: password,
|
|
|
|
@ -84,7 +97,13 @@ namespace Ombi.Core.IdentityResolver
|
|
|
|
|
iterationCount: 10000,
|
|
|
|
|
numBytesRequested: 256 / 8));
|
|
|
|
|
|
|
|
|
|
return hashed;
|
|
|
|
|
return new UserHash { HashedPass = hashed, Salt = salt };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private class UserHash
|
|
|
|
|
{
|
|
|
|
|
public string HashedPass { get; set; }
|
|
|
|
|
public byte[] Salt { get; set; }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|