using Core.Abstractions;
using Core.DomainObjects;
using DataProviders.Collections;
using DomainResults.Common;
using ExtensionMethods;
using HashService;
using JWTService;
using WeatherForecast.Models.Requests;
namespace WeatherForecast.Services {
///
///
///
public interface IAuthenticationService {
///
///
///
///
///
///
(string?, IDomainResult) Post(Guid siteId, AuthenticationRequestModel requestData);
}
///
///
///
public class AutheticationService : ServiceBase, IAuthenticationService {
private readonly IUserDataProvider _userDataProvider;
private readonly IHashService _hashService;
private readonly IJWTService _jwtService;
///
///
///
///
///
///
///
public AutheticationService (
ILogger logger,
IUserDataProvider userDataProvider,
IHashService hashService,
IJWTService jwtService
) : base(logger) {
_userDataProvider = userDataProvider;
_hashService = hashService;
_jwtService = jwtService;
}
///
///
///
///
///
///
public (string?, IDomainResult) Post(Guid siteId, AuthenticationRequestModel requestData) {
var opId = Guid.NewGuid();
// Retrieve user from database by userName
var (user, getUserResult) = _userDataProvider.GetByNickName(requestData.Username);
if (!getUserResult.IsSuccess || user == null)
return IDomainResult.NotFound();
if (user.Passwords.Password == null)
return IDomainResult.Failed($"Opid = [{opId}] Password is not set, create new password.");
// Check provided password hash with the stored one
var (salt, hash) = _hashService.CreateSaltedHash(requestData.Password);
if (!_hashService.ValidateHash(requestData.Password, salt, hash))
return IDomainResult.Unauthorized();
// Check password expiration if enabled
if (user.Passwords.Expiration.Enabled && DateTime.UtcNow > user.Passwords.Password.Created.AddDays(user.Passwords.Expiration.Days)) {
user.Passwords.Expired.Add(user.Passwords.Password.Prototype());
user.Passwords.Password = null;
return IDomainResult.Failed();
}
// Creating JWT token
var claims = new List> {
new KeyValuePair("UserId", $"{user.Id}")
};
var created = DateTime.UtcNow;
var expires = created.AddDays(365);
var token = _jwtService.CreateJwtToken(expires, claims);
user.Tokens.Add(new Token {
Value = token,
Created = created,
Expires = expires,
});
return IDomainResult.Success(token);
}
///
///
///
///
///
public IDomainResult Get(string token) {
#region Retrieve user id from token claim
var (claims, getClaimsResult) = _jwtService.JwtTokenClaims(token);
if (!getClaimsResult.IsSuccess || claims == null)
return IDomainResult.Failed();
var userId = claims.SingleOrDefault(x => x.Key == "UserId").Value.ToGuid();
if(userId == Guid.Empty)
return IDomainResult.Failed();
#endregion
var (user, getUserRersult) = _userDataProvider.Get(userId);
if(!getUserRersult.IsSuccess || user == null)
return IDomainResult.Failed();
// remove expired tokens
user.Tokens = user.Tokens.Where(x => x.Expires < DateTime.UtcNow).ToList();
if (!user.Tokens.Any(x => x.Value == token))
return IDomainResult.Failed();
return IDomainResult.Success();
}
}
}