using System.IdentityModel.Tokens.Jwt; using AyCode.Core.Helpers; using AyCode.Interfaces.Addresses; using AyCode.Interfaces.Logins; using AyCode.Interfaces.Profiles; using AyCode.Interfaces.Server.Logins; using AyCode.Interfaces.ServiceProviders; using AyCode.Interfaces.Users; using AyCode.Services.Logins; using System.Runtime.InteropServices; using System.Security; using System.Security.Claims; using System.Security.Cryptography; using System.Text; using Microsoft.IdentityModel.Tokens; using AyCode.Database.DataLayers; using Microsoft.EntityFrameworkCore; using AyCode.Database.DbContexts; using AyCode.Core.Consts; using AyCode.Core.Extensions; using AyCode.Database.DataLayers.Users; using AyCode.Database.DbContexts.Users; using AyCode.Models.Logins; using AyCode.Models.Server.Logins; using AyCode.Utils.Extensions; using AyCode.Utils.Helpers; using Microsoft.Extensions.Configuration; namespace AyCode.Services.Server.Logins; public class AcLoginServiceServer(TDal userDal, IConfiguration configuration) : AcLoginServiceBase, IAcLoginServiceServer where TResultLoggedInModel: class, IAcLoggedInModelBase where TDal : AcUserDalBase where TDbContext : AcDbContextBase, IAcUserDbContextBase where TUser : class, IAcUser where TUserToken : class, IAcUserTokenBase where TProfile : class, IAcProfile where TServiceProvider : class, IAcServiceProviderBase where TUserToServiceProvider : class, IAcUserToServiceProviderBase where TProfileAddress : class, IAcAddress { public virtual TUser? Login(string email, string password, out string accessToken) { accessToken = string.Empty; //var loginModel = Activator.CreateInstance(); if (!AcValidate.IsValidEmailAndPasswordFormat(email, password, out var errorCode)) return null;//return loginModel; var user = userDal.GetUserByEmail(email); if (user is not { EmailConfirmed: true } || !string.Equals(user.EmailAddress, email, StringComparison.CurrentCultureIgnoreCase) || !PasswordHasher.VerifyPassword(password, user.Password, GenerateDynamicSalt(user.Id))) return null; //loginModel.LoggedInUser = user; return LoggedInUser = user; } public virtual Task LoginAsync(string email, string password) { return TaskHelper.ToThreadPoolTask(() => Login(email, password, out _)); } public virtual bool Logout() { LoggedInUser = null; return true; } public virtual Task LogoutAsync() { return TaskHelper.ToThreadPoolTask(Logout); } public virtual TUser? Registration(string email, string password, string? phoneNumber = null) => Registration(Guid.NewGuid(), email, password, phoneNumber); public virtual TUser? Registration(Guid userId, string email, string password, string? phoneNumber = null) { if ((phoneNumber != null && !AcValidate.IsValidPhoneNumberFormat(phoneNumber, out var errorCode)) || !AcValidate.IsValidEmailAndPasswordFormat(email, password, out errorCode)) return null; var user = Activator.CreateInstance(); user.Id = userId; user.EmailAddress = email; user.EmailConfirmed = true; user.Password = PasswordHasher.HashPassword(password, GenerateDynamicSalt(userId)); var address = Activator.CreateInstance(); address.Id = Guid.NewGuid(); var userName = email.Split('@')[0]; //TODO: generálni egy nevet... - J. return userDal.AddUser(user, userName, address) ? null : userDal.GetUserById(userId); } public virtual Task RegistrationAsync(string email, string password, string? phoneNumber = null) => RegistrationAsync(Guid.NewGuid(), email, password, phoneNumber); public virtual Task RegistrationAsync(Guid userId, string email, string password, string? phoneNumber = null) { return TaskHelper.ToThreadPoolTask(() => Registration(userId, email, password, phoneNumber)); } //SEMMILYEN KÖRÜLMÉNYEK KÖZÖTT SE VÁLTOZTASD MEG METÓDUS LOGIKÁJÁT!!! Különben senki sem fog tudni Login-olni! - J. public virtual string GenerateDynamicSalt(Guid userId) => userId.ToString("N").ToLower().Reverse().MixCharacters(AcConst.ProjectSalt); private string GenerateAccessToken(TUser user) { var tokenHandler = new JwtSecurityTokenHandler(); Console.WriteLine("----------------------------------------------------------"); if (configuration["JWT:Key"] == null) throw new SecurityTokenException("Token is null"); var keyDetail = Encoding.UTF8.GetBytes(configuration["JWT:Key"] ?? string.Empty); Console.WriteLine(configuration["JWT:Key"]); var claims = new List { new(ClaimTypes.NameIdentifier, user.Id.ToString()), new(ClaimTypes.Email, user.EmailAddress) }; var tokenDescriptor = new SecurityTokenDescriptor { Audience = configuration["JWT:Audience"], Issuer = configuration["JWT:Issuer"], Expires = DateTime.UtcNow.AddMinutes(30), Subject = new ClaimsIdentity(claims), SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(keyDetail), SecurityAlgorithms.HmacSha256Signature) }; var token = tokenHandler.CreateToken(tokenDescriptor) as JwtSecurityToken; var writtenToken = tokenHandler.WriteToken(token); Console.WriteLine(writtenToken); return writtenToken; } private ClaimsPrincipal GetPrincipalFromExpiredToken(string token) { var tokenHandler = new JwtSecurityTokenHandler(); if (configuration["JWT:Key"] == null) throw new SecurityTokenException("Token is null"); var keyDetail = Encoding.UTF8.GetBytes(configuration["JWT:Key"] ?? string.Empty); var tokenValidationParameter = new TokenValidationParameters { ValidateIssuer = false, ValidateAudience = false, ValidateLifetime = false, ValidateIssuerSigningKey = true, ValidIssuer = configuration["JWT:Issuer"], ValidAudience = configuration["JWT:Audience"], IssuerSigningKey = new SymmetricSecurityKey(keyDetail), }; var principal = tokenHandler.ValidateToken(token, tokenValidationParameter, out var securityToken); if (securityToken is not JwtSecurityToken jwtSecurityToken || !jwtSecurityToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256, StringComparison.InvariantCultureIgnoreCase)) throw new SecurityTokenException("Invalid token"); return principal; } private string GenerateRefreshToken() { var randomNumber = new byte[32]; using (var rng = RandomNumberGenerator.Create()) { rng.GetBytes(randomNumber); return Convert.ToBase64String(randomNumber); } } }