diff --git a/BlueWest.Api/BlueWest.Api.csproj b/BlueWest.Api/BlueWest.Api.csproj index a5a0f86..f5cc937 100644 --- a/BlueWest.Api/BlueWest.Api.csproj +++ b/BlueWest.Api/BlueWest.Api.csproj @@ -34,6 +34,7 @@ + diff --git a/BlueWest.Api/Controllers/ApplicationUserController.cs b/BlueWest.Api/Controllers/ApplicationUserController.cs index 7ac0d27..aefd8db 100644 --- a/BlueWest.Api/Controllers/ApplicationUserController.cs +++ b/BlueWest.Api/Controllers/ApplicationUserController.cs @@ -1,6 +1,6 @@ +using BlueWest.Data.Application.Users; using BlueWest.Domain; -using BlueWest.Data; -using BlueWest.WebApi.Context; + using BlueWest.WebApi.Context.Users; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.JwtBearer; diff --git a/BlueWest.Api/Controllers/AuthController.cs b/BlueWest.Api/Controllers/AuthController.cs index d794f3d..3ce2a23 100644 --- a/BlueWest.Api/Controllers/AuthController.cs +++ b/BlueWest.Api/Controllers/AuthController.cs @@ -1,7 +1,6 @@ -using System; -using System.Security.Claims; using System.Threading.Tasks; -using BlueWest.WebApi.Context.Users; +using BlueWest.Data.Auth; +using BlueWest.Data.Auth.Context.Users; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authorization; diff --git a/BlueWest.Api/Controllers/CountryController.cs b/BlueWest.Api/Controllers/CountryController.cs index 0e93597..306592d 100644 --- a/BlueWest.Api/Controllers/CountryController.cs +++ b/BlueWest.Api/Controllers/CountryController.cs @@ -1,5 +1,6 @@ using BlueWest.Domain; using BlueWest.Data; +using BlueWest.Data.Auth; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Http; diff --git a/BlueWest.Api/Session/ISessionCache.cs b/BlueWest.Api/Session/ISessionCache.cs deleted file mode 100644 index d1eee22..0000000 --- a/BlueWest.Api/Session/ISessionCache.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System.Threading.Tasks; -using BlueWest.Data.Application; -using BlueWest.WebApi.Context.Users; -using Microsoft.Extensions.Hosting; - -namespace BlueWest.WebApi -{ - /// - /// Methods for handling session cache data. - /// - public interface ISessionCache : IHostedService - { - /// - /// Gets a Session Token by Id. - /// - /// - /// - Task GetSessionTokenByIdAsync(string tokenId); - /// - /// Create a new session token - /// - /// - Task AddSessionToken(SessionToken token); - - /// - /// Check for validity of the session - /// - /// - /// - Task IsSessionValidAsync(string sessionTokenId); - - /// - /// Checks if the session is valid - /// - /// - /// - bool IsSessionValid(string sessionTokenId); - - - - /// - /// Save Cache - /// - /// - Task SaveAsync(); - - /// - /// Save Cache - /// - /// - void Save(); - - - } -} - diff --git a/BlueWest.Api/Session/LoginRequest.cs b/BlueWest.Api/Session/LoginRequest.cs deleted file mode 100644 index 02f9fa9..0000000 --- a/BlueWest.Api/Session/LoginRequest.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace BlueWest.WebApi.Context.Users -{ - // from: https://github.com/dotnet/aspnetcore/tree/main/src/Identity/samples/IdentitySample.Mvc/Models/AccountViewModels - /// - /// Login Request adata - /// - public class LoginRequest - { - /// - /// Email - /// - [Required] - [EmailAddress] - public string Email { get; set; } - - /// - /// Password - /// - [Required] - [DataType(DataType.Password)] - public string Password { get; set; } - - [Required] - public string Uuid { get; set; } - - /// - /// Gets Uuid for this login request - /// - /// - public string GetUuid() - { - return $"{Uuid}|{Email}"; - } - - } -} - diff --git a/BlueWest.Api/Session/RegisterViewModel.cs b/BlueWest.Api/Session/RegisterViewModel.cs deleted file mode 100644 index dc548a9..0000000 --- a/BlueWest.Api/Session/RegisterViewModel.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace BlueWest.WebApi.Context.Users; - -/// -/// -/// -public class RegisterViewModel -{ - /// - /// Email - /// - [Required] - [EmailAddress] - [Display(Name = "Email")] - public string Email { get; set; } - - /// - /// Password - /// - [Required] - [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] - [DataType(DataType.Password)] - [Display(Name = "Password")] - public string Password { get; set; } - /// - /// Username - /// - public string Username { get; set; } - - /// - /// ConfirmPassword - /// - [DataType(DataType.Password)] - [Display(Name = "Confirm password")] - [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] - public string ConfirmPassword { get; set; } - - - /// - /// ConfirmPassword - /// - [DataType(DataType.PhoneNumber)] - [Display(Name = "Phone Number")] - public string PhoneNumber { get; set; } - - - - /// - /// Convert RegisterViewModel to ApplicationUser - /// - /// - public ApplicationUser ToUser() - { - var newUser = new ApplicationUser(); - newUser.Email = Email; - newUser.PasswordHash = Password; - newUser.UserName = Username; - newUser.PhoneNumber = PhoneNumber; - return newUser; - } -} \ No newline at end of file diff --git a/BlueWest.Api/Session/SessionAuthorizationFilter.cs b/BlueWest.Api/Session/SessionAuthorizationFilter.cs index ab283ae..33138b3 100644 --- a/BlueWest.Api/Session/SessionAuthorizationFilter.cs +++ b/BlueWest.Api/Session/SessionAuthorizationFilter.cs @@ -1,5 +1,6 @@ using System; using System.Threading.Tasks; +using BlueWest.Data.Auth; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; diff --git a/BlueWest.Api/Session/SessionConstants.cs b/BlueWest.Api/Session/SessionConstants.cs deleted file mode 100644 index a9e4caf..0000000 --- a/BlueWest.Api/Session/SessionConstants.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; - -namespace BlueWest.WebApi -{ - internal static class SessionConstants - { - - public static TimeSpan DefaultSessionMaxAge = TimeSpan.FromHours(24); - public const string ApiNamePolicy = "ApiUser"; - public const string SessionTokenHeaderName = "x-bw2-auth"; - public const string CookieDomain = "http://localhost:5173"; - } -} - diff --git a/BlueWest.Api/Session/SessionExtensions.cs b/BlueWest.Api/Session/SessionExtensions.cs index 1cda1ed..9efa192 100644 --- a/BlueWest.Api/Session/SessionExtensions.cs +++ b/BlueWest.Api/Session/SessionExtensions.cs @@ -1,3 +1,4 @@ +using BlueWest.Data.Auth; using Microsoft.AspNetCore.Http; namespace BlueWest.WebApi.Controllers diff --git a/BlueWest.Api/Session/SessionManager.cs b/BlueWest.Api/Session/SessionManager.cs index adb9fd6..86ffe14 100644 --- a/BlueWest.Api/Session/SessionManager.cs +++ b/BlueWest.Api/Session/SessionManager.cs @@ -3,6 +3,7 @@ using System.Threading; using System.Threading.Tasks; using BlueWest.Cryptography; using BlueWest.Data.Application; +using BlueWest.Data.Auth; using Microsoft.Extensions.Hosting; using Redis.OM; using Redis.OM.Searching; diff --git a/BlueWest.Api/Startup.cs b/BlueWest.Api/Startup.cs index 41ba1a9..eb1419d 100644 --- a/BlueWest.Api/Startup.cs +++ b/BlueWest.Api/Startup.cs @@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using System.Text.Json.Serialization; +using BlueWest.Data.Auth; using BlueWest.Tools; using BlueWest.WebApi.Interceptors; using BlueWest.WebApi.Interfaces; diff --git a/BlueWest.Api/StartupExtensions.cs b/BlueWest.Api/StartupExtensions.cs index ba4fff2..7f59c3d 100644 --- a/BlueWest.Api/StartupExtensions.cs +++ b/BlueWest.Api/StartupExtensions.cs @@ -4,6 +4,9 @@ using System.Threading.Tasks; using BlueWest.Domain; using BlueWest.Domain; using BlueWest.Cryptography; +using BlueWest.Data.Application.Users; +using BlueWest.Data.Auth; +using BlueWest.Data.Auth.Context.Users; using BlueWest.WebApi.Configuration; using BlueWest.WebApi.Context.Users; using BlueWest.WebApi.Session; @@ -241,8 +244,8 @@ namespace BlueWest.WebApi services.AddAuthorization(options => { options.AddPolicy(SessionConstants.ApiNamePolicy, - policy => policy.RequireClaim(Context.Users.Constants.JwtClaimIdentifiers.Rol, - Context.Users.Constants.JwtClaims.ApiAccess)); + policy => policy.RequireClaim(Data.Auth.Context.Users.Constants.JwtClaimIdentifiers.Rol, + Data.Auth.Context.Users.Constants.JwtClaims.ApiAccess)); }); diff --git a/BlueWest.Api/Users/ApplicationUserManager.cs b/BlueWest.Api/Users/ApplicationUserManager.cs deleted file mode 100644 index c7592b5..0000000 --- a/BlueWest.Api/Users/ApplicationUserManager.cs +++ /dev/null @@ -1,114 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using BlueWest.Cryptography; -using BlueWest.Data.Application; -using Microsoft.AspNetCore.Identity; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; - -namespace BlueWest.WebApi.Context.Users; - -/// -/// User Manager Object -/// -internal class ApplicationUserManager : UserManager, IUserManager -{ - private readonly IHasher _hasher; - private readonly UserRepository _usersRepo; - public ApplicationUserManager( - UserRepository store, - IOptions optionsAccessor, - IHasher passwordHasher, - IEnumerable> userValidators, - IEnumerable> passwordValidators, - ILookupNormalizer keyNormalizer, - IdentityErrorDescriber errors, - IServiceProvider services, - ILogger> logger) : base(store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services, logger) - { - _hasher = passwordHasher; - _usersRepo = store; - } - - public override async Task CheckPasswordAsync(ApplicationUser user, string password) - { - ThrowIfDisposed(); - var passwordStore = GetPasswordStore(); - - var result = await VerifyPasswordAsync(passwordStore, user, password); - if (result == PasswordVerificationResult.SuccessRehashNeeded) - { - //Remove the IPasswordStore parameter so we can call the protected, not private, method - await UpdatePasswordHash(user, password, validatePassword: false); - await UpdateUserAsync(user); - } - - var success = result != PasswordVerificationResult.Failed; - if (!success) - { - var userId = user != null ? GetUserIdAsync(user).Result : "(null)"; - Logger.LogWarning(0, "Invalid password for user {userId}.", userId); - } - return success; - } - - - protected override async Task VerifyPasswordAsync(IUserPasswordStore store, ApplicationUser user, string password) - { - string existingHash; - - if (user != null) - existingHash = await store.GetPasswordHashAsync(user, CancellationToken); - else - existingHash = "not a real hash"; - - if (existingHash == null) - { - return PasswordVerificationResult.Failed; - } - return PasswordHasher.VerifyHashedPassword(user, existingHash, password); - } - - - - public override async Task ChangePasswordAsync(ApplicationUser user, string currentPassword, string newPassword) - { - ThrowIfDisposed(); - var passwordStore = GetPasswordStore(); - if (user == null) - { - throw new ArgumentNullException(nameof(user)); - } - - if (await VerifyPasswordAsync(passwordStore, user, currentPassword) != PasswordVerificationResult.Failed) - { - var result = await UpdatePasswordHash(user, newPassword, validatePassword: false); - if (!result.Succeeded) - { - return result; - } - - return await UpdateUserAsync(user); - } - Logger.LogWarning(2, "Change password failed for user {userId}.", await GetUserIdAsync(user)); - return IdentityResult.Failed(ErrorDescriber.PasswordMismatch()); - } - - public override Task SetAuthenticationTokenAsync(ApplicationUser user, string loginProvider, string tokenName, string tokenValue) - { - return base.SetAuthenticationTokenAsync(user, loginProvider, tokenName, tokenValue); - } - - private IUserPasswordStore GetPasswordStore() - { - if (Store is IUserPasswordStore passwordStore) - { - return passwordStore; - } - - return null; - } - -} \ No newline at end of file diff --git a/BlueWest.Api/Users/Auth/AuthConsts.cs b/BlueWest.Api/Users/Auth/AuthConsts.cs deleted file mode 100644 index 33a8106..0000000 --- a/BlueWest.Api/Users/Auth/AuthConsts.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Security.Claims; -using System.Threading.Tasks; -using BlueWest.Data.Application; - -namespace BlueWest.WebApi.Context.Users; - -public static class AuthConsts -{ - /// - /// Helper object to return a negative callback - /// - public static (bool, SessionTokenUnique, ClaimsIdentity) NegativeToken => (false, null, null); - - public static (bool, SessionTokenUnique, ClaimsIdentity) OkAuth(SessionTokenUnique sessionTokenUnique, ClaimsIdentity claimsIdentity, bool success = true) => (success, sessionTokenUnique, claimsIdentity); - - -} \ No newline at end of file diff --git a/BlueWest.Api/Users/Auth/AuthManager.cs b/BlueWest.Api/Users/Auth/AuthManager.cs deleted file mode 100644 index b9bfabc..0000000 --- a/BlueWest.Api/Users/Auth/AuthManager.cs +++ /dev/null @@ -1,130 +0,0 @@ -using System; -using System.Security.Claims; -using System.Threading.Tasks; -using BlueWest.Cryptography; -using BlueWest.Data.Application; -using Microsoft.AspNetCore.Authentication.JwtBearer; -using Microsoft.AspNetCore.Identity; -using static BlueWest.WebApi.Context.Users.AuthConsts; - -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; - - /// - /// Auth manager constructor - /// - /// - /// - /// - /// - public AuthManager( - ApplicationUserManager userManager, - IHasher hasher, - IJwtFactory jwtFactory, - ISessionCache sessionCache) - { - _userManager = userManager; - _hasher = hasher; - _jwtFactory = jwtFactory; - _sessionCache = sessionCache; - } - - private async Task GetSessionToken(LoginRequest loginRequest) - { - var uuid = loginRequest.GetUuid(); - var hashUuid = GetHashFromUuid(uuid); - var sessionToken = await _sessionCache.GetSessionTokenByIdAsync(hashUuid); - return sessionToken; - } - - private string GetHashFromUuid(string uuid) - { - return _hasher.CreateHash(uuid, BaseCryptoItem.HashAlgorithm.SHA2_512); - } - - private SessionToken GetNewSessionToken(LoginRequest loginRequest, ApplicationUser user, string token) - { - long timeNow = DateTimeOffset.Now.ToUnixTimeMilliseconds(); - - var newToken = new SessionToken - { - Id = GetHashFromUuid(loginRequest.GetUuid()), - UserId = user.Id, - CreatedDate = timeNow, - IsValid = true, - ValidFor = SessionConstants.DefaultSessionMaxAge.Milliseconds, - AccessToken = token - }; - - return newToken; - } - - public bool SessionTokenIsValid(SessionToken token) - { - var hasChanges = token.Validate(); - - if (hasChanges) - { - _sessionCache.SaveAsync(); - } - - return token.IsValid; - } - - public async Task<(bool, SessionTokenUnique, ClaimsIdentity)> GetSessionTokenIdByLoginRequest(LoginRequest loginRequest) - { - var user = await _userManager.FindByEmailAsync(loginRequest.Email); - - if (user == null) return NegativeToken; - - if (!await _userManager.CheckPasswordAsync(user, loginRequest.Password)) return NegativeToken; - - var identity = new ClaimsIdentity(JwtBearerDefaults.AuthenticationScheme); - identity.AddClaim(new Claim(ClaimTypes.Email, user.Email)); - - var sessionToken = await GetSessionToken(loginRequest); - - if (sessionToken == null || !SessionTokenIsValid(sessionToken)) - { - var (success, bearerToken) = await GenerateBearerToken(identity, user); - var newSessionToken = GetNewSessionToken(loginRequest, user, bearerToken); - await _sessionCache.AddSessionToken(newSessionToken); - var tokenUnique = new SessionTokenUnique(newSessionToken); - - return OkAuth(tokenUnique, identity, success); - } - - var response = new SessionTokenUnique(sessionToken); - return OkAuth(response, 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 VerifyLoginByEmailAsync(string email, string password) - { - var user = await _userManager.FindByEmailAsync(email); - return user != null && await _userManager.CheckPasswordAsync(user, password); - } - - - public async Task CreateUserAsync(RegisterViewModel userSignupDto) - { - userSignupDto.Password = _hasher.CreateHash(userSignupDto.Password, BaseCryptoItem.HashAlgorithm.SHA3_512);; - var newUser = userSignupDto.ToUser(); - return await _userManager.CreateAsync(newUser); - } - } -} \ No newline at end of file diff --git a/BlueWest.Api/Users/Auth/Crypto/BaseCryptoItem.cs b/BlueWest.Api/Users/Auth/Crypto/BaseCryptoItem.cs deleted file mode 100644 index 7494398..0000000 --- a/BlueWest.Api/Users/Auth/Crypto/BaseCryptoItem.cs +++ /dev/null @@ -1,98 +0,0 @@ -using System; -using System.Linq; -using System.Security.Cryptography; -using System.Text; - -namespace BlueWest.Cryptography -{ - internal abstract class BaseCryptoItem - { - public enum HashAlgorithm - { - // ReSharper disable once InconsistentNaming - SHA2_512 = 1, - - // ReSharper disable once InconsistentNaming - PBKDF2_SHA512 = 2, - - // ReSharper disable once InconsistentNaming - SHA3_512 = 3 - } - - /// - /// HexStringToByteArray - /// - /// - /// - protected byte[] HexStringToByteArray(string stringInHexFormat) - { - var converted = Enumerable.Range(0, stringInHexFormat.Length) - .Where(x => x % 2 == 0) - .Select(x => Convert.ToByte(stringInHexFormat.Substring(x, 2), 16)) - .ToArray(); - - return converted; - } - - /// - /// ByteArrayToString - /// - /// - /// - protected string ByteArrayToString(byte[] bytes) - { - var sb = new StringBuilder(); - - for (int i = 0; i < bytes.Length; i++) - { - sb.Append(bytes[i].ToString("X2")); - } - - return sb.ToString(); - } - - /// - /// Generates a random string - /// - /// The length of the random string - /// - protected string CreateRandomString(int length) - { - var rng = RandomNumberGenerator.Create(); - var buffer = new byte[length / 2]; - rng.GetBytes(buffer); - var randomString = BitConverter.ToString(buffer).Replace("-", ""); - return randomString; - } - - // TODO Refactor me - /// - /// Get Cryptographic algorithm - /// - /// - /// - /// - /// - protected void GetAlgorithm(string cipherText, out int? algorithm, out int? keyIndex, - out string trimmedCipherText) - { - algorithm = null; - keyIndex = null; - trimmedCipherText = cipherText; - - if (cipherText.Length <= 5 ) return; - - var cipherInfo = cipherText[0].ToString(); - - if (int.TryParse(cipherInfo, out int foundAlgorithm)) - { - algorithm = foundAlgorithm; - } - - if (int.TryParse(cipherInfo, out int foundKeyIndex)) - keyIndex = foundKeyIndex; - - trimmedCipherText = cipherText.Substring(cipherText.IndexOf(cipherInfo, StringComparison.Ordinal) + 1); - } - } -} \ No newline at end of file diff --git a/BlueWest.Api/Users/Auth/Crypto/Hasher.cs b/BlueWest.Api/Users/Auth/Crypto/Hasher.cs deleted file mode 100644 index f930403..0000000 --- a/BlueWest.Api/Users/Auth/Crypto/Hasher.cs +++ /dev/null @@ -1,114 +0,0 @@ - -using System; -using BlueWest.WebApi.Context.Users; -using Microsoft.AspNetCore.Identity; - - -namespace BlueWest.Cryptography -{ - - /// - /// Hasher - /// - internal class Hasher : BaseCryptoItem, IHasher - { - private const int SaltLength = 64; - - /// - /// CreateHash - /// - /// - /// - /// - public string CreateHash(string text, HashAlgorithm algorithm) - { - var salt = CreateRandomString(SaltLength); - return CreateHash(text, salt, algorithm, true); - } - - /// - /// CreateHash - /// - /// - /// - /// - /// - public string CreateHash(string text, string saltName, BaseCryptoItem.HashAlgorithm algorithm) - { - return CreateHash(text, saltName, algorithm, false); - } - - private string CreateHash(string text, string salt, HashAlgorithm algorithm, bool storeSalt) - { - string hash; - - switch (algorithm) - { - case HashAlgorithm.SHA2_512: - var sha2 = new SHA2_512(); - hash = sha2.Hash(text, salt, storeSalt); - break; - case HashAlgorithm.SHA3_512: - var sha3 = new SHA2_512(); - hash = sha3.Hash(text, salt, storeSalt); - break; - default: - throw new NotImplementedException(); - } - - return hash; - } - - /// - /// Check for a matching hash. - /// - /// - /// - /// - public bool MatchesHash(string text, string hash) - { - string salt = ""; - - GetAlgorithm(hash, out var algoAsInt, out _, out _, out salt); - - if (!algoAsInt.HasValue) return false; - - var hashAlgorithm = (HashAlgorithm) algoAsInt.Value; - var hashed = CreateHash(text, salt, hashAlgorithm, true); - return hashed == hash; - } - - /// - /// Hash password - /// - /// - /// - /// - public string HashPassword(ApplicationUser ApplicationUser, string password) - { - return CreateHash(password, HashAlgorithm.SHA3_512); - } - - public PasswordVerificationResult VerifyHashedPassword(ApplicationUser ApplicationUser, string hashedPassword, - string providedPassword) - { - var match = MatchesHash(providedPassword, hashedPassword); - return match ? PasswordVerificationResult.Success : PasswordVerificationResult.Failed; - } - - private void GetAlgorithm(string cipherText, out int? algorithm, out int? keyIndex, - out string trimmedCipherText, out string salt) - { - GetAlgorithm(cipherText, out algorithm, out keyIndex, out trimmedCipherText); - if (algorithm.HasValue && trimmedCipherText.Length > SaltLength) - { - salt = trimmedCipherText.Substring(0, SaltLength); - trimmedCipherText = trimmedCipherText.Substring(SaltLength); - } - else - { - salt = null; - } - } - } -} \ No newline at end of file diff --git a/BlueWest.Api/Users/Auth/Crypto/IHasher.cs b/BlueWest.Api/Users/Auth/Crypto/IHasher.cs deleted file mode 100644 index 0c473c8..0000000 --- a/BlueWest.Api/Users/Auth/Crypto/IHasher.cs +++ /dev/null @@ -1,33 +0,0 @@ -using BlueWest.WebApi.Context.Users; -using Microsoft.AspNetCore.Identity; - -namespace BlueWest.Cryptography; - -/// -/// IHasher contract -/// -internal interface IHasher : IPasswordHasher -{ - /// - /// Create hash - /// - /// - /// - /// - string CreateHash(string text, BaseCryptoItem.HashAlgorithm algorithm); - /// - /// Create hash - /// - /// - /// - /// - /// - string CreateHash(string text, string salt, BaseCryptoItem.HashAlgorithm algorithm); - /// - /// MatchesHash - /// - /// - /// - /// - bool MatchesHash(string text, string hash); -} \ No newline at end of file diff --git a/BlueWest.Api/Users/Auth/Crypto/IJwtFactory.cs b/BlueWest.Api/Users/Auth/Crypto/IJwtFactory.cs deleted file mode 100644 index 84f3aeb..0000000 --- a/BlueWest.Api/Users/Auth/Crypto/IJwtFactory.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System.Threading.Tasks; - -namespace BlueWest.WebApi.Context.Users; - -public interface IJwtFactory -{ - Task GenerateEncodedToken(string id, string userName); -} diff --git a/BlueWest.Api/Users/Auth/Crypto/IJwtTokenHandler.cs b/BlueWest.Api/Users/Auth/Crypto/IJwtTokenHandler.cs deleted file mode 100644 index a88b355..0000000 --- a/BlueWest.Api/Users/Auth/Crypto/IJwtTokenHandler.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.IdentityModel.Tokens.Jwt; -using System.Security.Claims; -using Microsoft.IdentityModel.Tokens; - -namespace BlueWest.WebApi.Context.Users -{ - public interface IJwtTokenHandler - { - string WriteToken(JwtSecurityToken jwt); - ClaimsPrincipal ValidateToken(string token, TokenValidationParameters tokenValidationParameters); - } -} \ No newline at end of file diff --git a/BlueWest.Api/Users/Auth/Crypto/ISessionHasher.cs b/BlueWest.Api/Users/Auth/Crypto/ISessionHasher.cs deleted file mode 100644 index 52525a0..0000000 --- a/BlueWest.Api/Users/Auth/Crypto/ISessionHasher.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace BlueWest.Cryptography -{ - public interface ISessionHasher - { - /// - /// Generates a token for the current session - /// - void GenerateSessionToken(); - - } -} - diff --git a/BlueWest.Api/Users/Auth/Crypto/ITokenFactory.cs b/BlueWest.Api/Users/Auth/Crypto/ITokenFactory.cs deleted file mode 100644 index 392e198..0000000 --- a/BlueWest.Api/Users/Auth/Crypto/ITokenFactory.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace BlueWest.WebApi.Context.Users; - -internal interface ITokenFactory -{ - string GenerateToken(int size= 32); -} \ No newline at end of file diff --git a/BlueWest.Api/Users/Auth/Crypto/JwtFactory.cs b/BlueWest.Api/Users/Auth/Crypto/JwtFactory.cs deleted file mode 100644 index a0dd1aa..0000000 --- a/BlueWest.Api/Users/Auth/Crypto/JwtFactory.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System; -using System.IdentityModel.Tokens.Jwt; -using System.Security.Claims; -using System.Security.Principal; -using System.Threading.Tasks; -using Microsoft.Extensions.Options; -using static BlueWest.WebApi.Context.Users.Constants; - -namespace BlueWest.WebApi.Context.Users; - -internal class JwtFactory : IJwtFactory -{ - private readonly IJwtTokenHandler _jwtTokenHandler; - private readonly JwtIssuerOptions _jwtOptions; - - public JwtFactory(IJwtTokenHandler jwtTokenHandler, IOptions jwtOptions) - { - _jwtTokenHandler = jwtTokenHandler; - _jwtOptions = jwtOptions.Value; - ThrowIfInvalidOptions(_jwtOptions); - } - - public async Task GenerateEncodedToken(string id, string userName) - { - var identity = GenerateClaimsIdentity(id, userName); - - var claims = new[] - { - new Claim(JwtRegisteredClaimNames.Sub, userName), - new Claim(JwtRegisteredClaimNames.Jti, await _jwtOptions.JtiGenerator()), - new Claim(JwtRegisteredClaimNames.Aud, _jwtOptions.Audience), - - new Claim(JwtRegisteredClaimNames.Iat, ToUnixEpochDate(_jwtOptions.IssuedAt).ToString(), - ClaimValueTypes.Integer64), - identity.FindFirst(JwtClaimIdentifiers.Rol), - identity.FindFirst(JwtClaimIdentifiers.Id) - }; - - // Create the JWT security token and encode it. - var jwt = new JwtSecurityToken( - _jwtOptions.Issuer, - _jwtOptions.Audience, - claims, - _jwtOptions.NotBefore, - _jwtOptions.Expiration, - _jwtOptions.SigningCredentials); - - return new AccessToken(_jwtTokenHandler.WriteToken(jwt), (int)_jwtOptions.ValidFor.TotalSeconds); - } - - private static ClaimsIdentity GenerateClaimsIdentity(string id, string userName) - { - return new ClaimsIdentity(new GenericIdentity(userName, "Token"), new[] - { - new Claim(JwtClaimIdentifiers.Id, id), - new Claim(JwtClaimIdentifiers.Rol, JwtClaims.ApiAccess) - }); - } - - /// Date converted to seconds since Unix epoch (Jan 1, 1970, midnight UTC). - private static long ToUnixEpochDate(DateTime date) - => (long)Math.Round((date.ToUniversalTime() - - new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero)) - .TotalSeconds); - - private static void ThrowIfInvalidOptions(JwtIssuerOptions options) - { - if (options == null) throw new ArgumentNullException(nameof(options)); - - if (options.ValidFor <= TimeSpan.Zero) - { - throw new ArgumentException("Must be a non-zero TimeSpan.", nameof(JwtIssuerOptions.ValidFor)); - } - - if (options.SigningCredentials == null) - { - throw new ArgumentNullException(nameof(JwtIssuerOptions.SigningCredentials)); - } - - if (options.JtiGenerator == null) - { - throw new ArgumentNullException(nameof(JwtIssuerOptions.JtiGenerator)); - } - } -} \ No newline at end of file diff --git a/BlueWest.Api/Users/Auth/Crypto/JwtIssuerOptions.cs b/BlueWest.Api/Users/Auth/Crypto/JwtIssuerOptions.cs deleted file mode 100644 index 336f7c7..0000000 --- a/BlueWest.Api/Users/Auth/Crypto/JwtIssuerOptions.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System; -using System.Threading.Tasks; -using Microsoft.IdentityModel.Tokens; - -namespace BlueWest.WebApi.Context.Users; - -internal class JwtIssuerOptions -{ - /// - /// 4.1.1. "iss" (Issuer) Claim - The "iss" (issuer) claim identifies the principal that issued the JWT. - /// - public string Issuer { get; set; } - - /// - /// 4.1.2. "sub" (Subject) Claim - The "sub" (subject) claim identifies the principal that is the subject of the JWT. - /// - public string Subject { get; set; } - - /// - /// 4.1.3. "aud" (Audience) Claim - The "aud" (audience) claim identifies the recipients that the JWT is intended for. - /// - public string Audience { get; set; } - - /// - /// 4.1.4. "exp" (Expiration Time) Claim - The "exp" (expiration time) claim identifies the expiration time on or after which the JWT MUST NOT be accepted for processing. - /// - public DateTime Expiration => IssuedAt.Add(ValidFor); - - /// - /// 4.1.5. "nbf" (Not Before) Claim - The "nbf" (not before) claim identifies the time before which the JWT MUST NOT be accepted for processing. - /// - public DateTime NotBefore => DateTime.UtcNow; - - /// - /// 4.1.6. "iat" (Issued At) Claim - The "iat" (issued at) claim identifies the time at which the JWT was issued. - /// - public DateTime IssuedAt => DateTime.UtcNow; - - /// - /// Set the timespan the token will be valid for (default is 120 min) - /// - public TimeSpan ValidFor { get; set; } = SessionConstants.DefaultSessionMaxAge; - - /// - /// "jti" (JWT ID) Claim (default ID is a GUID) - /// - public Func> JtiGenerator => - () => Task.FromResult(Guid.NewGuid().ToString()); - - /// - /// The signing key to use when generating tokens. - /// - public SigningCredentials SigningCredentials { get; set; } -} \ No newline at end of file diff --git a/BlueWest.Api/Users/Auth/Crypto/JwtTokenHandler.cs b/BlueWest.Api/Users/Auth/Crypto/JwtTokenHandler.cs deleted file mode 100644 index 54820c9..0000000 --- a/BlueWest.Api/Users/Auth/Crypto/JwtTokenHandler.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System; -using System.IdentityModel.Tokens.Jwt; -using System.Security.Claims; -using Microsoft.IdentityModel.Tokens; - -namespace BlueWest.WebApi.Context.Users; - -public class JwtTokenHandler : IJwtTokenHandler -{ - private readonly JwtSecurityTokenHandler _jwtSecurityTokenHandler; - - /// - /// JwtTokenHandler - /// - public JwtTokenHandler() - { - _jwtSecurityTokenHandler = new JwtSecurityTokenHandler(); - } - - /// - /// Write token - /// - /// - /// - public string WriteToken(JwtSecurityToken jwt) - { - return _jwtSecurityTokenHandler.WriteToken(jwt); - } - - /// - /// Validate Token - /// - /// - /// - /// - /// - public ClaimsPrincipal ValidateToken(string token, TokenValidationParameters tokenValidationParameters) - { - try - { - var principal = _jwtSecurityTokenHandler.ValidateToken(token, tokenValidationParameters, out var securityToken); - - if (!(securityToken is JwtSecurityToken jwtSecurityToken) || !jwtSecurityToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256, StringComparison.InvariantCultureIgnoreCase)) - throw new SecurityTokenException("Invalid token"); - - return principal; - } - catch (Exception e) - { - return null; - } - } -} \ No newline at end of file diff --git a/BlueWest.Api/Users/Auth/Crypto/SHA_512.cs b/BlueWest.Api/Users/Auth/Crypto/SHA_512.cs deleted file mode 100644 index e2523a6..0000000 --- a/BlueWest.Api/Users/Auth/Crypto/SHA_512.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System.Security.Cryptography; -using System.Text; -using Microsoft.AspNetCore.Cryptography.KeyDerivation; -namespace BlueWest.Cryptography -{ - /// - /// SHA2_512 : BaseCryptoItem - /// - internal class SHA2_512 : BaseCryptoItem - { - /// - /// Hash with the provided salt - /// - /// - /// - /// - /// - public string Hash(string text, string salt, bool storeSalt) - { - var fullText = string.Concat(text, salt); - var data = Encoding.UTF8.GetBytes(fullText); - string hash; - using SHA512 sha = SHA512.Create(); - var hashBytes = sha.ComputeHash(data); - var asString = ByteArrayToString(hashBytes); - - if (storeSalt) - { - hash = $"{(int)HashAlgorithm.SHA3_512}{salt}{asString}"; - return hash; - } - - hash = $"{(int)HashAlgorithm.SHA3_512}{asString}"; - return hash; - } - - - /// - /// Hash_PBKDF2 algorithm. - /// - /// - /// - /// - /// - public string Hash_PBKDF2(string plainText, string salt, bool saveSaltInResult) - { - var saltAsBytes = Encoding.ASCII.GetBytes(salt); - - string hashed = ByteArrayToString(KeyDerivation.Pbkdf2( - password: plainText, - salt: saltAsBytes, - prf: KeyDerivationPrf.HMACSHA512, //.NET 3.1 uses HMACSHA256 here - iterationCount: 100000, //.NET 3.1 uses 10,000 iterations here - numBytesRequested: 64)); //.NET 3.1 uses 32 bytes here - - if (saveSaltInResult) - return string.Format("[{0}]{1}{2}", (int)HashAlgorithm.PBKDF2_SHA512, salt, hashed); - else - return string.Format("[{0}]{1}", (int)HashAlgorithm.PBKDF2_SHA512, hashed); - } - } -} \ No newline at end of file diff --git a/BlueWest.Api/Users/Auth/IAuthManager.cs b/BlueWest.Api/Users/Auth/IAuthManager.cs deleted file mode 100644 index 42fbe7c..0000000 --- a/BlueWest.Api/Users/Auth/IAuthManager.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Security.Claims; -using System.Threading.Tasks; -using BlueWest.Data.Application; -using Microsoft.AspNetCore.Identity; - -namespace BlueWest.WebApi.Context.Users; - -/// -/// Auth manager contract interface. -/// -public interface IAuthManager -{ - /// - /// CreateUserAsync - /// - /// - /// - Task CreateUserAsync(RegisterViewModel registerViewModel); - - /// - /// Does Login - /// - /// - /// - public Task<(bool, SessionTokenUnique, ClaimsIdentity)> GetSessionTokenIdByLoginRequest(LoginRequest loginRequest); - - -} \ No newline at end of file diff --git a/BlueWest.Api/Users/Auth/SignInManager.cs b/BlueWest.Api/Users/Auth/SignInManager.cs deleted file mode 100644 index bae6ae4..0000000 --- a/BlueWest.Api/Users/Auth/SignInManager.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.Linq; -using System.Security.Claims; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Identity; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; - -namespace BlueWest.WebApi.Context.Users; - -/// -/// SignInManager -/// -internal class SignInManager : SignInManager -{ - public SignInManager( - UserManager userManager, - IHttpContextAccessor contextAccessor, - IUserClaimsPrincipalFactory claimsFactory, - IOptions optionsAccessor, - ILogger> logger, - IAuthenticationSchemeProvider schemes, - IUserConfirmation confirmation) : - base(userManager, contextAccessor, claimsFactory, optionsAccessor, logger, schemes, confirmation) - { - - } - - - -} \ No newline at end of file diff --git a/BlueWest.Api/Users/Constants.cs b/BlueWest.Api/Users/Constants.cs deleted file mode 100644 index 25d8b1e..0000000 --- a/BlueWest.Api/Users/Constants.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace BlueWest.WebApi.Context.Users; - -public static class Constants -{ - - /// - /// JwtClaimIdentifiers - /// - public static class JwtClaimIdentifiers - { - public const string Rol = "rol", Id = "id"; - } - - /// - /// JwtClaims - /// - public static class JwtClaims - { - /// - /// JwtClaims.ApiAccess - /// - public const string ApiAccess = "api_access"; - } -} \ No newline at end of file diff --git a/BlueWest.Api/Users/IUserManager.cs b/BlueWest.Api/Users/IUserManager.cs deleted file mode 100644 index 9db5b03..0000000 --- a/BlueWest.Api/Users/IUserManager.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Threading.Tasks; -using BlueWest.Data.Application; -using Microsoft.AspNetCore.Identity; - -namespace BlueWest.WebApi.Context.Users -{ - public interface IUserManager - { - /// - /// Create user. - /// - /// - /// - Task CreateAsync(ApplicationUser user); - - /// - /// Checks for user password - /// - /// - /// - /// - Task CheckPasswordAsync(ApplicationUser user, string password); - - /// - /// Find by email - /// - /// - /// - Task FindByEmailAsync(string email); - - - - } -} - diff --git a/BlueWest.Api/Users/UserRepository.cs b/BlueWest.Api/Users/UserRepository.cs deleted file mode 100644 index 36d384a..0000000 --- a/BlueWest.Api/Users/UserRepository.cs +++ /dev/null @@ -1,69 +0,0 @@ -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using BlueWest.Domain; -using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Identity.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore; - -namespace BlueWest.WebApi.Context.Users -{ - /// - /// Users Repository - /// - public class UserRepository : UserStore - { - private readonly ApplicationUserDbContext _context; - - /// - /// User repository - /// - /// - /// - public UserRepository(ApplicationUserDbContext context, IdentityErrorDescriber describer = null) : base(context, describer) - { - _context = context; - } - - /// - /// Get Application Users - /// - /// - public async Task> GetUsers() - { - var users = await _context.Users.ToListAsync(); - return users; - } - - /// - public override Task GetPasswordHashAsync(ApplicationUser user, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return Task.FromCanceled(cancellationToken); - } - - return Task.FromResult(user.PasswordHash); - } - - /// - public override Task HasPasswordAsync(ApplicationUser user, CancellationToken cancellationToken = default) - { - if (cancellationToken.IsCancellationRequested) - { - return Task.FromCanceled(cancellationToken); - } - - return Task.FromResult(!string.IsNullOrEmpty(user.PasswordHash)); - } - - } -} diff --git a/BlueWest.Data.Application/AccessToken.cs b/BlueWest.Data.Application/AccessToken.cs index 982d37c..9dec456 100644 --- a/BlueWest.Data.Application/AccessToken.cs +++ b/BlueWest.Data.Application/AccessToken.cs @@ -1,5 +1,5 @@ -namespace BlueWest.WebApi.Context.Users +namespace BlueWest.Data.Application.Users { public class AccessToken { diff --git a/BlueWest.Data.Application/ApplicationRole/ApplicationRole.cs b/BlueWest.Data.Application/ApplicationRole/ApplicationRole.cs index 5fb9d6b..48f3744 100644 --- a/BlueWest.Data.Application/ApplicationRole/ApplicationRole.cs +++ b/BlueWest.Data.Application/ApplicationRole/ApplicationRole.cs @@ -1,7 +1,7 @@ using MapTo; using Microsoft.AspNetCore.Identity; -namespace BlueWest.WebApi.Context.Users +namespace BlueWest.Data.Application.Users { /// [MapFrom(typeof(ApplicationRoleUnique))] diff --git a/BlueWest.Data.Application/ApplicationRole/ApplicationRoleUnique.cs b/BlueWest.Data.Application/ApplicationRole/ApplicationRoleUnique.cs index 1a23f0c..fa0d2d5 100644 --- a/BlueWest.Data.Application/ApplicationRole/ApplicationRoleUnique.cs +++ b/BlueWest.Data.Application/ApplicationRole/ApplicationRoleUnique.cs @@ -1,6 +1,6 @@ using MapTo; -namespace BlueWest.WebApi.Context.Users +namespace BlueWest.Data.Application.Users { [MapFrom(typeof(ApplicationRole))] public partial class ApplicationRoleUnique diff --git a/BlueWest.Data.Application/ApplicationRoleClaim/ApplicationRoleClaim.cs b/BlueWest.Data.Application/ApplicationRoleClaim/ApplicationRoleClaim.cs index be3b387..440caac 100644 --- a/BlueWest.Data.Application/ApplicationRoleClaim/ApplicationRoleClaim.cs +++ b/BlueWest.Data.Application/ApplicationRoleClaim/ApplicationRoleClaim.cs @@ -2,7 +2,7 @@ using System; using Microsoft.AspNetCore.Identity; using MapTo; -namespace BlueWest.WebApi.Context.Users +namespace BlueWest.Data.Application.Users { /// diff --git a/BlueWest.Data.Application/ApplicationRoleClaim/ApplicationRoleClaimUnique.cs b/BlueWest.Data.Application/ApplicationRoleClaim/ApplicationRoleClaimUnique.cs index 079ba9b..d792356 100644 --- a/BlueWest.Data.Application/ApplicationRoleClaim/ApplicationRoleClaimUnique.cs +++ b/BlueWest.Data.Application/ApplicationRoleClaim/ApplicationRoleClaimUnique.cs @@ -1,6 +1,6 @@ using MapTo; -namespace BlueWest.WebApi.Context.Users +namespace BlueWest.Data.Application.Users { [MapFrom(typeof(ApplicationRoleClaim))] public partial class ApplicationRoleClaimUnique diff --git a/BlueWest.Data.Application/ApplicationUser/ApplicationUser.cs b/BlueWest.Data.Application/ApplicationUser/ApplicationUser.cs index a53a8c8..9466596 100644 --- a/BlueWest.Data.Application/ApplicationUser/ApplicationUser.cs +++ b/BlueWest.Data.Application/ApplicationUser/ApplicationUser.cs @@ -7,7 +7,7 @@ using BlueWest.Data.Application; using MapTo; using Microsoft.AspNetCore.Identity; -namespace BlueWest.WebApi.Context.Users +namespace BlueWest.Data.Application.Users { /// /// Application User in the Identity System. diff --git a/BlueWest.Data.Application/ApplicationUser/ApplicationUserUnique.cs b/BlueWest.Data.Application/ApplicationUser/ApplicationUserUnique.cs index 02094dc..eb38e7f 100644 --- a/BlueWest.Data.Application/ApplicationUser/ApplicationUserUnique.cs +++ b/BlueWest.Data.Application/ApplicationUser/ApplicationUserUnique.cs @@ -1,7 +1,7 @@ using System; using MapTo; -namespace BlueWest.WebApi.Context.Users +namespace BlueWest.Data.Application.Users { [MapFrom(typeof(ApplicationUser))] public partial class ApplicationUserUnique diff --git a/BlueWest.Data.Application/ApplicationUserClaim/ApplicationUserClaim.cs b/BlueWest.Data.Application/ApplicationUserClaim/ApplicationUserClaim.cs index 9d2b3c8..7bc5c6d 100644 --- a/BlueWest.Data.Application/ApplicationUserClaim/ApplicationUserClaim.cs +++ b/BlueWest.Data.Application/ApplicationUserClaim/ApplicationUserClaim.cs @@ -1,7 +1,7 @@ using Microsoft.AspNetCore.Identity; using MapTo; -namespace BlueWest.WebApi.Context.Users +namespace BlueWest.Data.Application.Users { [MapFrom(typeof(ApplicationUserClaimUnique))] diff --git a/BlueWest.Data.Application/ApplicationUserClaim/ApplicationUserClaimUnique.cs b/BlueWest.Data.Application/ApplicationUserClaim/ApplicationUserClaimUnique.cs index 29d5411..d02aad7 100644 --- a/BlueWest.Data.Application/ApplicationUserClaim/ApplicationUserClaimUnique.cs +++ b/BlueWest.Data.Application/ApplicationUserClaim/ApplicationUserClaimUnique.cs @@ -1,6 +1,6 @@ using MapTo; -namespace BlueWest.WebApi.Context.Users +namespace BlueWest.Data.Application.Users { [MapFrom(typeof(ApplicationUserClaim))] public partial class ApplicationUserClaimUnique diff --git a/BlueWest.Data.Application/ApplicationUserLogin/ApplicationUserLogin.cs b/BlueWest.Data.Application/ApplicationUserLogin/ApplicationUserLogin.cs index 50596e5..b2b8cdc 100644 --- a/BlueWest.Data.Application/ApplicationUserLogin/ApplicationUserLogin.cs +++ b/BlueWest.Data.Application/ApplicationUserLogin/ApplicationUserLogin.cs @@ -1,6 +1,6 @@ using Microsoft.AspNetCore.Identity; -namespace BlueWest.WebApi.Context.Users; +namespace BlueWest.Data.Application.Users; /// public class ApplicationUserLogin : IdentityUserLogin { } \ No newline at end of file diff --git a/BlueWest.Data.Application/ApplicationUserRole/ApplicationUserRole.cs b/BlueWest.Data.Application/ApplicationUserRole/ApplicationUserRole.cs index c6314aa..b6d25d4 100644 --- a/BlueWest.Data.Application/ApplicationUserRole/ApplicationUserRole.cs +++ b/BlueWest.Data.Application/ApplicationUserRole/ApplicationUserRole.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using Microsoft.AspNetCore.Identity; using MapTo; -namespace BlueWest.WebApi.Context.Users +namespace BlueWest.Data.Application.Users { /// diff --git a/BlueWest.Data.Application/ApplicationUserRole/ApplicationUserRoleUnique.cs b/BlueWest.Data.Application/ApplicationUserRole/ApplicationUserRoleUnique.cs index b7389ee..879d03e 100644 --- a/BlueWest.Data.Application/ApplicationUserRole/ApplicationUserRoleUnique.cs +++ b/BlueWest.Data.Application/ApplicationUserRole/ApplicationUserRoleUnique.cs @@ -1,6 +1,6 @@ using MapTo; -namespace BlueWest.WebApi.Context.Users +namespace BlueWest.Data.Application.Users { [MapFrom(typeof(ApplicationUserRole))] public partial class ApplicationUserRoleUnique diff --git a/BlueWest.Data.Application/ApplicationUserToken/ApplicationUserToken.cs b/BlueWest.Data.Application/ApplicationUserToken/ApplicationUserToken.cs index 6aefa55..dbdf31a 100644 --- a/BlueWest.Data.Application/ApplicationUserToken/ApplicationUserToken.cs +++ b/BlueWest.Data.Application/ApplicationUserToken/ApplicationUserToken.cs @@ -1,6 +1,6 @@ using Microsoft.AspNetCore.Identity; -namespace BlueWest.WebApi.Context.Users; +namespace BlueWest.Data.Application.Users; /// public class ApplicationUserToken : IdentityUserToken diff --git a/BlueWest.Data.Application/Crypto/Jwt/IJwtTokenHandler.cs b/BlueWest.Data.Application/Crypto/Jwt/IJwtTokenHandler.cs deleted file mode 100644 index a88b355..0000000 --- a/BlueWest.Data.Application/Crypto/Jwt/IJwtTokenHandler.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.IdentityModel.Tokens.Jwt; -using System.Security.Claims; -using Microsoft.IdentityModel.Tokens; - -namespace BlueWest.WebApi.Context.Users -{ - public interface IJwtTokenHandler - { - string WriteToken(JwtSecurityToken jwt); - ClaimsPrincipal ValidateToken(string token, TokenValidationParameters tokenValidationParameters); - } -} \ No newline at end of file diff --git a/BlueWest.Data.Application/Crypto/Jwt/ITokenFactory.cs b/BlueWest.Data.Application/Crypto/Jwt/ITokenFactory.cs deleted file mode 100644 index 392e198..0000000 --- a/BlueWest.Data.Application/Crypto/Jwt/ITokenFactory.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace BlueWest.WebApi.Context.Users; - -internal interface ITokenFactory -{ - string GenerateToken(int size= 32); -} \ No newline at end of file diff --git a/BlueWest.Data.Application/Crypto/Jwt/JwtIssuerOptions.cs b/BlueWest.Data.Application/Crypto/Jwt/JwtIssuerOptions.cs deleted file mode 100644 index 530e5a5..0000000 --- a/BlueWest.Data.Application/Crypto/Jwt/JwtIssuerOptions.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System; -using System.Threading.Tasks; -using Microsoft.IdentityModel.Tokens; - -namespace BlueWest.WebApi.Context.Users; - -internal class JwtIssuerOptions -{ - /// - /// 4.1.1. "iss" (Issuer) Claim - The "iss" (issuer) claim identifies the principal that issued the JWT. - /// - public string Issuer { get; set; } - - /// - /// 4.1.2. "sub" (Subject) Claim - The "sub" (subject) claim identifies the principal that is the subject of the JWT. - /// - public string Subject { get; set; } - - /// - /// 4.1.3. "aud" (Audience) Claim - The "aud" (audience) claim identifies the recipients that the JWT is intended for. - /// - public string Audience { get; set; } - - /// - /// 4.1.4. "exp" (Expiration Time) Claim - The "exp" (expiration time) claim identifies the expiration time on or after which the JWT MUST NOT be accepted for processing. - /// - public DateTime Expiration => IssuedAt.Add(ValidFor); - - /// - /// 4.1.5. "nbf" (Not Before) Claim - The "nbf" (not before) claim identifies the time before which the JWT MUST NOT be accepted for processing. - /// - public DateTime NotBefore => DateTime.UtcNow; - - /// - /// 4.1.6. "iat" (Issued At) Claim - The "iat" (issued at) claim identifies the time at which the JWT was issued. - /// - public DateTime IssuedAt => DateTime.UtcNow; - - /// - /// Set the timespan the token will be valid for (default is 120 min) - /// - public TimeSpan ValidFor { get; set; } = TimeSpan.FromMinutes(120); - - /// - /// "jti" (JWT ID) Claim (default ID is a GUID) - /// - public Func> JtiGenerator => - () => Task.FromResult(Guid.NewGuid().ToString()); - - /// - /// The signing key to use when generating tokens. - /// - public SigningCredentials SigningCredentials { get; set; } -} \ No newline at end of file diff --git a/BlueWest.Data.Application/Crypto/Jwt/JwtTokenHandler.cs b/BlueWest.Data.Application/Crypto/Jwt/JwtTokenHandler.cs deleted file mode 100644 index 54820c9..0000000 --- a/BlueWest.Data.Application/Crypto/Jwt/JwtTokenHandler.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System; -using System.IdentityModel.Tokens.Jwt; -using System.Security.Claims; -using Microsoft.IdentityModel.Tokens; - -namespace BlueWest.WebApi.Context.Users; - -public class JwtTokenHandler : IJwtTokenHandler -{ - private readonly JwtSecurityTokenHandler _jwtSecurityTokenHandler; - - /// - /// JwtTokenHandler - /// - public JwtTokenHandler() - { - _jwtSecurityTokenHandler = new JwtSecurityTokenHandler(); - } - - /// - /// Write token - /// - /// - /// - public string WriteToken(JwtSecurityToken jwt) - { - return _jwtSecurityTokenHandler.WriteToken(jwt); - } - - /// - /// Validate Token - /// - /// - /// - /// - /// - public ClaimsPrincipal ValidateToken(string token, TokenValidationParameters tokenValidationParameters) - { - try - { - var principal = _jwtSecurityTokenHandler.ValidateToken(token, tokenValidationParameters, out var securityToken); - - if (!(securityToken is JwtSecurityToken jwtSecurityToken) || !jwtSecurityToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256, StringComparison.InvariantCultureIgnoreCase)) - throw new SecurityTokenException("Invalid token"); - - return principal; - } - catch (Exception e) - { - return null; - } - } -} \ No newline at end of file diff --git a/BlueWest.Data.Application/SessionToken/SessionData.cs b/BlueWest.Data.Application/SessionToken/SessionData.cs index 49a6a77..e37830c 100644 --- a/BlueWest.Data.Application/SessionToken/SessionData.cs +++ b/BlueWest.Data.Application/SessionToken/SessionData.cs @@ -1,4 +1,4 @@ -using BlueWest.WebApi.Context.Users; +using BlueWest.Data.Application.Users; namespace BlueWest.Data.Application { diff --git a/BlueWest.Data.Application/SessionToken/SessionToken.cs b/BlueWest.Data.Application/SessionToken/SessionToken.cs index 9f8e052..68fa944 100644 --- a/BlueWest.Data.Application/SessionToken/SessionToken.cs +++ b/BlueWest.Data.Application/SessionToken/SessionToken.cs @@ -1,4 +1,4 @@ -using BlueWest.WebApi.Context.Users; +using BlueWest.Data.Application.Users; using MapTo; using Redis.OM.Modeling; diff --git a/BlueWest.Data.Auth/Session/ISessionCache.cs b/BlueWest.Data.Auth/Session/ISessionCache.cs index d1eee22..c230d39 100644 --- a/BlueWest.Data.Auth/Session/ISessionCache.cs +++ b/BlueWest.Data.Auth/Session/ISessionCache.cs @@ -1,9 +1,9 @@ using System.Threading.Tasks; using BlueWest.Data.Application; -using BlueWest.WebApi.Context.Users; +using BlueWest.Data.Auth.Context.Users; using Microsoft.Extensions.Hosting; -namespace BlueWest.WebApi +namespace BlueWest.Data.Auth { /// /// Methods for handling session cache data. diff --git a/BlueWest.Data.Auth/Session/LoginRequest.cs b/BlueWest.Data.Auth/Session/LoginRequest.cs index 02f9fa9..8beadb5 100644 --- a/BlueWest.Data.Auth/Session/LoginRequest.cs +++ b/BlueWest.Data.Auth/Session/LoginRequest.cs @@ -1,6 +1,6 @@ using System.ComponentModel.DataAnnotations; -namespace BlueWest.WebApi.Context.Users +namespace BlueWest.Data.Auth.Context.Users { // from: https://github.com/dotnet/aspnetcore/tree/main/src/Identity/samples/IdentitySample.Mvc/Models/AccountViewModels /// diff --git a/BlueWest.Data.Auth/Session/RegisterViewModel.cs b/BlueWest.Data.Auth/Session/RegisterViewModel.cs index dc548a9..b3348c1 100644 --- a/BlueWest.Data.Auth/Session/RegisterViewModel.cs +++ b/BlueWest.Data.Auth/Session/RegisterViewModel.cs @@ -1,6 +1,7 @@ using System.ComponentModel.DataAnnotations; +using BlueWest.Data.Application.Users; -namespace BlueWest.WebApi.Context.Users; +namespace BlueWest.Data.Auth.Context.Users; /// /// diff --git a/BlueWest.Data.Auth/Session/SessionConstants.cs b/BlueWest.Data.Auth/Session/SessionConstants.cs index a9e4caf..16fa5ef 100644 --- a/BlueWest.Data.Auth/Session/SessionConstants.cs +++ b/BlueWest.Data.Auth/Session/SessionConstants.cs @@ -1,8 +1,8 @@ using System; -namespace BlueWest.WebApi +namespace BlueWest.Data.Auth { - internal static class SessionConstants + public static class SessionConstants { public static TimeSpan DefaultSessionMaxAge = TimeSpan.FromHours(24); diff --git a/BlueWest.Data.Auth/Users/ApplicationUserManager.cs b/BlueWest.Data.Auth/Users/ApplicationUserManager.cs index c7592b5..3be389c 100644 --- a/BlueWest.Data.Auth/Users/ApplicationUserManager.cs +++ b/BlueWest.Data.Auth/Users/ApplicationUserManager.cs @@ -1,19 +1,16 @@ -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; + using BlueWest.Cryptography; -using BlueWest.Data.Application; +using BlueWest.Data.Application.Users; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -namespace BlueWest.WebApi.Context.Users; +namespace BlueWest.Data.Auth.Context.Users; /// /// User Manager Object /// -internal class ApplicationUserManager : UserManager, IUserManager +public class ApplicationUserManager : UserManager, IUserManager { private readonly IHasher _hasher; private readonly UserRepository _usersRepo; diff --git a/BlueWest.Data.Auth/Users/Auth/AuthConsts.cs b/BlueWest.Data.Auth/Users/Auth/AuthConsts.cs index 33a8106..0706d45 100644 --- a/BlueWest.Data.Auth/Users/Auth/AuthConsts.cs +++ b/BlueWest.Data.Auth/Users/Auth/AuthConsts.cs @@ -2,7 +2,7 @@ using System.Security.Claims; using System.Threading.Tasks; using BlueWest.Data.Application; -namespace BlueWest.WebApi.Context.Users; +namespace BlueWest.Data.Auth.Context.Users; public static class AuthConsts { diff --git a/BlueWest.Data.Auth/Users/Auth/AuthManager.cs b/BlueWest.Data.Auth/Users/Auth/AuthManager.cs index b9bfabc..0d3b8db 100644 --- a/BlueWest.Data.Auth/Users/Auth/AuthManager.cs +++ b/BlueWest.Data.Auth/Users/Auth/AuthManager.cs @@ -1,15 +1,14 @@ -using System; using System.Security.Claims; -using System.Threading.Tasks; using BlueWest.Cryptography; using BlueWest.Data.Application; +using BlueWest.Data.Application.Users; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Identity; -using static BlueWest.WebApi.Context.Users.AuthConsts; +using static BlueWest.Data.Auth.Context.Users.AuthConsts; -namespace BlueWest.WebApi.Context.Users +namespace BlueWest.Data.Auth.Context.Users { - internal class AuthManager : IAuthManager + public class AuthManager : IAuthManager { private readonly ApplicationUserManager _userManager; private readonly IHasher _hasher; diff --git a/BlueWest.Data.Auth/Users/Auth/Crypto/BaseCryptoItem.cs b/BlueWest.Data.Auth/Users/Auth/Crypto/BaseCryptoItem.cs index 7494398..a66e7e5 100644 --- a/BlueWest.Data.Auth/Users/Auth/Crypto/BaseCryptoItem.cs +++ b/BlueWest.Data.Auth/Users/Auth/Crypto/BaseCryptoItem.cs @@ -5,7 +5,7 @@ using System.Text; namespace BlueWest.Cryptography { - internal abstract class BaseCryptoItem + public abstract class BaseCryptoItem { public enum HashAlgorithm { diff --git a/BlueWest.Data.Auth/Users/Auth/Crypto/Hasher.cs b/BlueWest.Data.Auth/Users/Auth/Crypto/Hasher.cs index f930403..60c1203 100644 --- a/BlueWest.Data.Auth/Users/Auth/Crypto/Hasher.cs +++ b/BlueWest.Data.Auth/Users/Auth/Crypto/Hasher.cs @@ -1,6 +1,6 @@ - using System; -using BlueWest.WebApi.Context.Users; +using BlueWest.Data.Application.Users; +using BlueWest.Data.Auth.Context.Users; using Microsoft.AspNetCore.Identity; @@ -10,7 +10,7 @@ namespace BlueWest.Cryptography /// /// Hasher /// - internal class Hasher : BaseCryptoItem, IHasher + public class Hasher : BaseCryptoItem, IHasher { private const int SaltLength = 64; diff --git a/BlueWest.Data.Auth/Users/Auth/Crypto/IHasher.cs b/BlueWest.Data.Auth/Users/Auth/Crypto/IHasher.cs index 0c473c8..8c58f31 100644 --- a/BlueWest.Data.Auth/Users/Auth/Crypto/IHasher.cs +++ b/BlueWest.Data.Auth/Users/Auth/Crypto/IHasher.cs @@ -1,4 +1,5 @@ -using BlueWest.WebApi.Context.Users; +using BlueWest.Data.Application.Users; +using BlueWest.Data.Auth.Context.Users; using Microsoft.AspNetCore.Identity; namespace BlueWest.Cryptography; @@ -6,7 +7,7 @@ namespace BlueWest.Cryptography; /// /// IHasher contract /// -internal interface IHasher : IPasswordHasher +public interface IHasher : IPasswordHasher { /// /// Create hash diff --git a/BlueWest.Data.Auth/Users/Auth/Crypto/IJwtFactory.cs b/BlueWest.Data.Auth/Users/Auth/Crypto/IJwtFactory.cs index 84f3aeb..cd1c45a 100644 --- a/BlueWest.Data.Auth/Users/Auth/Crypto/IJwtFactory.cs +++ b/BlueWest.Data.Auth/Users/Auth/Crypto/IJwtFactory.cs @@ -1,6 +1,7 @@ using System.Threading.Tasks; +using BlueWest.Data.Application.Users; -namespace BlueWest.WebApi.Context.Users; +namespace BlueWest.Data.Auth.Context.Users; public interface IJwtFactory { diff --git a/BlueWest.Data.Auth/Users/Auth/Crypto/IJwtTokenHandler.cs b/BlueWest.Data.Auth/Users/Auth/Crypto/IJwtTokenHandler.cs index a88b355..aced078 100644 --- a/BlueWest.Data.Auth/Users/Auth/Crypto/IJwtTokenHandler.cs +++ b/BlueWest.Data.Auth/Users/Auth/Crypto/IJwtTokenHandler.cs @@ -2,7 +2,7 @@ using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using Microsoft.IdentityModel.Tokens; -namespace BlueWest.WebApi.Context.Users +namespace BlueWest.Data.Auth.Context.Users { public interface IJwtTokenHandler { diff --git a/BlueWest.Data.Auth/Users/Auth/Crypto/ITokenFactory.cs b/BlueWest.Data.Auth/Users/Auth/Crypto/ITokenFactory.cs index 392e198..91eb892 100644 --- a/BlueWest.Data.Auth/Users/Auth/Crypto/ITokenFactory.cs +++ b/BlueWest.Data.Auth/Users/Auth/Crypto/ITokenFactory.cs @@ -1,4 +1,4 @@ -namespace BlueWest.WebApi.Context.Users; +namespace BlueWest.Data.Auth.Context.Users; internal interface ITokenFactory { diff --git a/BlueWest.Data.Auth/Users/Auth/Crypto/JwtFactory.cs b/BlueWest.Data.Auth/Users/Auth/Crypto/JwtFactory.cs index a0dd1aa..26d2910 100644 --- a/BlueWest.Data.Auth/Users/Auth/Crypto/JwtFactory.cs +++ b/BlueWest.Data.Auth/Users/Auth/Crypto/JwtFactory.cs @@ -2,13 +2,13 @@ using System; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Security.Principal; -using System.Threading.Tasks; +using BlueWest.Data.Application.Users; using Microsoft.Extensions.Options; -using static BlueWest.WebApi.Context.Users.Constants; +using static BlueWest.Data.Auth.Context.Users.Constants; -namespace BlueWest.WebApi.Context.Users; +namespace BlueWest.Data.Auth.Context.Users; -internal class JwtFactory : IJwtFactory +public class JwtFactory : IJwtFactory { private readonly IJwtTokenHandler _jwtTokenHandler; private readonly JwtIssuerOptions _jwtOptions; diff --git a/BlueWest.Data.Auth/Users/Auth/Crypto/JwtIssuerOptions.cs b/BlueWest.Data.Auth/Users/Auth/Crypto/JwtIssuerOptions.cs index 336f7c7..858189d 100644 --- a/BlueWest.Data.Auth/Users/Auth/Crypto/JwtIssuerOptions.cs +++ b/BlueWest.Data.Auth/Users/Auth/Crypto/JwtIssuerOptions.cs @@ -2,9 +2,9 @@ using System; using System.Threading.Tasks; using Microsoft.IdentityModel.Tokens; -namespace BlueWest.WebApi.Context.Users; +namespace BlueWest.Data.Auth.Context.Users; -internal class JwtIssuerOptions +public class JwtIssuerOptions { /// /// 4.1.1. "iss" (Issuer) Claim - The "iss" (issuer) claim identifies the principal that issued the JWT. diff --git a/BlueWest.Data.Auth/Users/Auth/Crypto/JwtTokenHandler.cs b/BlueWest.Data.Auth/Users/Auth/Crypto/JwtTokenHandler.cs index 54820c9..df8b6d5 100644 --- a/BlueWest.Data.Auth/Users/Auth/Crypto/JwtTokenHandler.cs +++ b/BlueWest.Data.Auth/Users/Auth/Crypto/JwtTokenHandler.cs @@ -3,7 +3,7 @@ using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using Microsoft.IdentityModel.Tokens; -namespace BlueWest.WebApi.Context.Users; +namespace BlueWest.Data.Auth.Context.Users; public class JwtTokenHandler : IJwtTokenHandler { diff --git a/BlueWest.Data.Auth/Users/Auth/IAuthManager.cs b/BlueWest.Data.Auth/Users/Auth/IAuthManager.cs index 42fbe7c..7743f93 100644 --- a/BlueWest.Data.Auth/Users/Auth/IAuthManager.cs +++ b/BlueWest.Data.Auth/Users/Auth/IAuthManager.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using BlueWest.Data.Application; using Microsoft.AspNetCore.Identity; -namespace BlueWest.WebApi.Context.Users; +namespace BlueWest.Data.Auth.Context.Users; /// /// Auth manager contract interface. diff --git a/BlueWest.Data.Auth/Users/Auth/SignInManager.cs b/BlueWest.Data.Auth/Users/Auth/SignInManager.cs index bae6ae4..a55e057 100644 --- a/BlueWest.Data.Auth/Users/Auth/SignInManager.cs +++ b/BlueWest.Data.Auth/Users/Auth/SignInManager.cs @@ -1,14 +1,12 @@ -using System; -using System.Linq; -using System.Security.Claims; -using System.Threading.Tasks; + +using BlueWest.Data.Application.Users; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -namespace BlueWest.WebApi.Context.Users; +namespace BlueWest.Data.Auth.Context.Users; /// /// SignInManager diff --git a/BlueWest.Data.Auth/Users/Constants.cs b/BlueWest.Data.Auth/Users/Constants.cs index 25d8b1e..9a70796 100644 --- a/BlueWest.Data.Auth/Users/Constants.cs +++ b/BlueWest.Data.Auth/Users/Constants.cs @@ -1,4 +1,4 @@ -namespace BlueWest.WebApi.Context.Users; +namespace BlueWest.Data.Auth.Context.Users; public static class Constants { diff --git a/BlueWest.Data.Auth/Users/IUserManager.cs b/BlueWest.Data.Auth/Users/IUserManager.cs index 9db5b03..981eccc 100644 --- a/BlueWest.Data.Auth/Users/IUserManager.cs +++ b/BlueWest.Data.Auth/Users/IUserManager.cs @@ -1,8 +1,8 @@ -using System.Threading.Tasks; -using BlueWest.Data.Application; + +using BlueWest.Data.Application.Users; using Microsoft.AspNetCore.Identity; -namespace BlueWest.WebApi.Context.Users +namespace BlueWest.Data.Auth.Context.Users { public interface IUserManager { diff --git a/BlueWest.Data.Auth/Users/UserRepository.cs b/BlueWest.Data.Auth/Users/UserRepository.cs index 36d384a..3004f07 100644 --- a/BlueWest.Data.Auth/Users/UserRepository.cs +++ b/BlueWest.Data.Auth/Users/UserRepository.cs @@ -1,12 +1,10 @@ -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; +using BlueWest.Data.Application.Users; using BlueWest.Domain; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; -namespace BlueWest.WebApi.Context.Users +namespace BlueWest.Data.Auth.Context.Users { /// /// Users Repository diff --git a/BlueWest.Domain/ApplicationUserDbContext.cs b/BlueWest.Domain/ApplicationUserDbContext.cs index 1a228d8..c863195 100644 --- a/BlueWest.Domain/ApplicationUserDbContext.cs +++ b/BlueWest.Domain/ApplicationUserDbContext.cs @@ -1,6 +1,6 @@ +using BlueWest.Data.Application.Users; using BlueWest.EfMethods; using BlueWest.Domain.Model; -using BlueWest.WebApi.Context.Users; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; diff --git a/BlueWest.Domain/Extensions/ModelBuilderExtensions.cs b/BlueWest.Domain/Extensions/ModelBuilderExtensions.cs index 1a1295d..7ca47bd 100644 --- a/BlueWest.Domain/Extensions/ModelBuilderExtensions.cs +++ b/BlueWest.Domain/Extensions/ModelBuilderExtensions.cs @@ -1,6 +1,6 @@ using BlueWest.Data; using BlueWest.Data.Application; -using BlueWest.WebApi.Context.Users; +using BlueWest.Data.Application.Users; using Microsoft.EntityFrameworkCore; namespace BlueWest.Domain.Model diff --git a/BlueWest.Views/BlueWest.Views.csproj b/BlueWest.Views/BlueWest.Views.csproj index 2a7bff8..8d45718 100644 --- a/BlueWest.Views/BlueWest.Views.csproj +++ b/BlueWest.Views/BlueWest.Views.csproj @@ -11,8 +11,10 @@ + + diff --git a/BlueWest.Views/Program.cs b/BlueWest.Views/Program.cs index 8e2c1ce..8fde92b 100644 --- a/BlueWest.Views/Program.cs +++ b/BlueWest.Views/Program.cs @@ -1,5 +1,6 @@ using BlueWest.Views.Utils; using System.Globalization; +using BlueWest.Data.Auth; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Localization; using Microsoft.Extensions.Options; @@ -21,6 +22,16 @@ builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationSc cookieOptions.LoginPath = "/"; }); +builder.Services.AddLogging(builder => +{ + builder.AddSimpleConsole(); +}); + +builder.Services.AddSession(options => +{ + options.Cookie.Domain = SessionConstants.CookieDomain; + options.Cookie.HttpOnly = true; +}); builder.Services.AddControllersWithViews(); var app = builder.Build(); diff --git a/BlueWest.Views/SessionManager.cs b/BlueWest.Views/SessionManager.cs new file mode 100644 index 0000000..532c283 --- /dev/null +++ b/BlueWest.Views/SessionManager.cs @@ -0,0 +1,130 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using BlueWest.Data.Application; +using BlueWest.Data.Auth; +using Microsoft.Extensions.Hosting; +using Redis.OM; +using Redis.OM.Searching; + +namespace BlueWest.Views; + +/// +/// Session Provider Context +/// +public sealed class SessionManager : ISessionCache +{ + private readonly RedisConnectionProvider _provider; + private readonly RedisCollection _sessionTokens; + + /// + /// Index Creation Device + /// + /// Redis connection + public SessionManager( + RedisConnectionProvider provider) + { + _provider = provider; + _sessionTokens = (RedisCollection) provider.RedisCollection(); + } + + /// + /// Empty constructor + /// + public SessionManager() + { + } + + /// + /// Get a session token by the respective Id. + /// + /// + /// + public async Task GetSessionTokenByIdAsync(string tokenId) + { + return await _sessionTokens.Where(x => x.Id == tokenId) + .FirstOrDefaultAsync(); + } + + /// + /// Create a new session token + /// + /// + public async Task AddSessionToken(SessionToken token) + { + await _sessionTokens.InsertAsync(token); + } + + /// + public async Task SaveAsync() + { + await _sessionTokens.SaveAsync(); + } + + + /// + /// Save session data + /// + public void Save() + { + _sessionTokens.Save(); + } + + /// + /// Gets a Bearer By Access Token Id + /// + /// + public async Task IsSessionValidAsync(string sessionTokenId) + { + var accessToken = await _sessionTokens + .Where(t => t.Id == sessionTokenId) + .FirstOrDefaultAsync(); + + if (accessToken == null) return false; + + if (accessToken.IsValid) + { + // Check if it's not expired + var expirationDate = accessToken.CreatedDate + accessToken.ValidFor; + var timeNow = DateTimeOffset.Now.ToUnixTimeMilliseconds(); + if (expirationDate >= timeNow) return accessToken.IsValid; + accessToken.IsValid = false; + await _sessionTokens.SaveAsync(); + } + + return accessToken.IsValid; + } + + /// + /// Checks if a session is valid + /// + /// + /// + public bool IsSessionValid(string sessionTokenId) + { + var accessToken = _sessionTokens + .FirstOrDefault(t => t.Id == sessionTokenId); + + if (accessToken == null) return false; + + if (!accessToken.IsValid) return accessToken.IsValid; + + accessToken.Validate(); + _sessionTokens.Save(); + + return accessToken.IsValid; + } + + + /// + public async Task StartAsync(CancellationToken cancellationToken) + { + await _provider.Connection.CreateIndexAsync(typeof(SessionToken)); + } + + /// + public Task StopAsync(CancellationToken cancellationToken) + { + return Task.CompletedTask; + } +} \ No newline at end of file