155 lines
5.5 KiB
C#
155 lines
5.5 KiB
C#
using System;
|
|
using System.Security.Claims;
|
|
using System.Threading.Tasks;
|
|
using BlueWest.Cryptography;
|
|
using BlueWest.Data.Application;
|
|
using Duende.IdentityServer.Extensions;
|
|
using Microsoft.AspNetCore.Authentication.Cookies;
|
|
using Microsoft.AspNetCore.Identity;
|
|
|
|
namespace BlueWest.WebApi.Context.Users
|
|
{
|
|
internal class AuthManager : IAuthManager
|
|
{
|
|
private readonly ApplicationUserManager _userManager;
|
|
private readonly IHasher _hasher;
|
|
private readonly IJwtFactory _jwtFactory;
|
|
private readonly ISessionCache _sessionCache;
|
|
|
|
/// <summary>
|
|
/// Auth manager constructor
|
|
/// </summary>
|
|
/// <param name="userManager"></param>
|
|
/// <param name="hasher"></param>
|
|
/// <param name="jwtFactory"></param>
|
|
/// <param name="sessionCache"></param>
|
|
public AuthManager(
|
|
ApplicationUserManager userManager,
|
|
IHasher hasher,
|
|
IJwtFactory jwtFactory,
|
|
ISessionCache sessionCache)
|
|
{
|
|
_userManager = userManager;
|
|
_hasher = hasher;
|
|
_jwtFactory = jwtFactory;
|
|
_sessionCache = sessionCache;
|
|
}
|
|
|
|
private async Task<SessionToken> GetSessionToken(LoginRequest loginRequest)
|
|
{
|
|
var uuid = loginRequest.GetUuid();
|
|
var hashUuid = GetHashFromUuid(uuid);
|
|
var sessionToken = await _sessionCache.GetSessionTokenByIdAsync(hashUuid);
|
|
if (sessionToken != null) return sessionToken;
|
|
return null;
|
|
}
|
|
|
|
private string GetHashFromUuid(string uuid)
|
|
{
|
|
return _hasher.CreateHash(uuid, BaseCryptoItem.HashAlgorithm.SHA2_512);
|
|
}
|
|
|
|
private SessionToken GetNewSessionToken(LoginRequest loginRequest, ApplicationUser user, string token)
|
|
{
|
|
long unixTime = ((DateTimeOffset)DateTimeOffset.Now).ToUnixTimeMilliseconds();;
|
|
var newToken = new SessionToken
|
|
{
|
|
Id = GetHashFromUuid(loginRequest.GetUuid()),
|
|
UserId = user.Id,
|
|
CreatedDate = unixTime,
|
|
IsValid = true,
|
|
AccessToken = token
|
|
};
|
|
return newToken;
|
|
}
|
|
|
|
public bool SessionTokenIsValid(SessionToken token)
|
|
{
|
|
var nowMilliseconds = DateTimeOffset.Now.ToUnixTimeMilliseconds();
|
|
|
|
var isExpired = token.CreatedDate + token.ValidFor > nowMilliseconds;
|
|
|
|
if (isExpired)
|
|
{
|
|
token.IsValid = false;
|
|
_sessionCache.SaveAsync();
|
|
}
|
|
|
|
return token.IsValid;
|
|
}
|
|
|
|
public async Task<(bool, string, ClaimsIdentity)> GetSessionTokenId(LoginRequest loginRequest)
|
|
{
|
|
var user = await _userManager.FindByEmailAsync(loginRequest.Email);
|
|
|
|
if (user == null) return (false, string.Empty, null);
|
|
|
|
if (!await _userManager.CheckPasswordAsync(user, loginRequest.Password)) return (false, string.Empty, null);
|
|
|
|
var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
|
|
identity.AddClaim(new Claim(ClaimTypes.Email, user.Email));
|
|
|
|
// Session
|
|
var sessionToken = await GetSessionToken(loginRequest);
|
|
|
|
if (sessionToken != null)
|
|
{
|
|
if (SessionTokenIsValid(sessionToken))
|
|
{
|
|
return (true, sessionToken.Id, identity);
|
|
}
|
|
}
|
|
|
|
var (success, bearerToken) = await GenerateBearerToken(identity, user);
|
|
|
|
var newSessionToken = GetNewSessionToken(loginRequest, user, bearerToken);
|
|
await _sessionCache.AddSessionToken(newSessionToken);
|
|
|
|
return (success, newSessionToken.Id, identity);
|
|
}
|
|
|
|
private async Task<(bool, string)> GenerateBearerToken(ClaimsIdentity identity, ApplicationUser user)
|
|
{
|
|
var jwtToken = await _jwtFactory.GenerateEncodedToken(user.Id, user.UserName);
|
|
var completed = await _userManager.SetAuthenticationTokenAsync(user, SessionConstants.ApiNamePolicy,
|
|
SessionConstants.ApiNamePolicy, jwtToken.Token);
|
|
return (completed == IdentityResult.Success, jwtToken.Token);
|
|
}
|
|
|
|
|
|
public async Task<(bool, string)> GetBearerTokenBySessionTokenId(string sessionId)
|
|
{
|
|
if (sessionId.IsNullOrEmpty()) return (false, string.Empty);
|
|
var bearer = await _sessionCache.GetBearerByAccessTokenId(sessionId);
|
|
return (bearer != string.Empty, bearer);
|
|
}
|
|
|
|
|
|
/// <inheritdoc />
|
|
public async Task<bool> VerifyLoginByEmailAsync(string email, string password)
|
|
{
|
|
var user = await _userManager.FindByEmailAsync(email);
|
|
|
|
if (user == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return await _userManager.CheckPasswordAsync(user, password);
|
|
}
|
|
|
|
private RegisterViewModel FromSignupToUser(RegisterViewModel signupDto)
|
|
{
|
|
var pwd = signupDto.Password;
|
|
var hash = _hasher.CreateHash(pwd, BaseCryptoItem.HashAlgorithm.SHA3_512);
|
|
signupDto.Password = hash;
|
|
return signupDto;
|
|
}
|
|
|
|
public async Task<IdentityResult> CreateUserAsync(RegisterViewModel userSignupDto)
|
|
{
|
|
RegisterViewModel userToCreate = FromSignupToUser(userSignupDto);
|
|
return await _userManager.CreateAsync(userToCreate.ToUser());
|
|
}
|
|
}
|
|
} |