using System.Diagnostics; using System.Net; using System.Security.AccessControl; using System.Text; using System.Threading; using DigestAuthenticationOnWCF; using FrameworkBLL.EventLog; using FrameworkBLL.SessionStore; using FrameworkDAL.CustomCode.Authentication; using FrameworkDAL.CustomCode.User; using FrameworkDAL.DTO.EventLog; using FrameworkDAL.DTO.SessionStore; using FrameworkDAL.DTO.User; using GB5Shared.Connection; using GB5Shared.DTO.Framework.Authentication; using GB5Shared.DTO.Framework.CommonConfig; using GB5Shared.DTO.Framework.Enum; using GB5Shared.DTO.Framework.Logging; using GB5Shared.DTO.Framework.Login; using GB5Shared.DTO.Framework.ServerConfig; using GB5Shared.GB5Exception; using Microsoft.AspNetCore.Http; using Microsoft.Data.SqlClient; using Microsoft.Extensions.Options; using Org.BouncyCastle.Security; using static Azure.Core.HttpHeader; using static GB5Shared.DTO.Framework.Enum.FrameworkEnumDTO; namespace GoodBooks.FrameworkBLL.Authentication { public class AuthenticationBLL : IAuthenticationBLL { private readonly IAuthenticationDAL _AuthenticationDAL; private readonly IApplicationConnection _connection; private readonly IUserDAL _UserDAL; private readonly IOptionsSnapshot _DataBaseDTO; private readonly IEventLogBLL _EventLogBLL; private readonly ISessionStoreBLL _SessionStoreBLL; public AuthenticationBLL( IOptionsSnapshot DataBaseDTO, IAuthenticationDAL authenticationDAL, IApplicationConnection connection, IUserDAL IUserDAL, IEventLogBLL eventLogBLL, ISessionStoreBLL sessionStoreBLL) { _DataBaseDTO = DataBaseDTO; _AuthenticationDAL = authenticationDAL; _connection = connection; _UserDAL = IUserDAL; _EventLogBLL = eventLogBLL; _SessionStoreBLL = sessionStoreBLL; } //private static readonly Mutex _sessionMutexForLogin = new(); public async Task AuthenticateUser(string ConnectionName, string UserCode, AuthenticationDTO DigestHeader) { ServerConfigDTO ServerConfigDTO = new(); LoginDTO LoginDTO = new LoginDTO(); try { //_sessionMutexForLogin.WaitOne(); // string ISNHibernateProfilerNeeded = CommonFunctionDAL.ReadValueFromCommonConfig("ISNHibernateProfilerNeeded"); //if (ISNHibernateProfilerNeeded == null || ISNHibernateProfilerNeeded == "") //{ // throw new NotFoundException(ExceptionMessages.UNIB0174); //} //if (ISNHibernateProfilerNeeded.ToLower() == "yes") //{ // HibernatingRhinos.Profiler.Appender.NHibernate.NHibernateProfiler.Initialize(); //} // IGenericFrameDAL GenericDAL = new GenericNhibernateFrameDAL(); //LoggingDTO LoggingDTO = new LoggingDTO(); // //string Sql = ""; //Getting The Server Connection //First Log //LoggingDTO.Write("AuthenticateUser Bll Rquest Received of UserCode= " + UserCode, FrameworkEnumDTO.LogLevel.INFO, null); //DBConnectionString = await _connection.DBConnectionStringCached(ConnectionName); //await using (SqlConnection connection = new(DBConnectionString)) //{ // return await connection.QueryFirstOrDefaultAsync(ssql, new { CONNECTIONNAME = ConnectionName }); //} //ServerConfigDTO = _connection.DBConnectionStringCached(ConnectionName); ServerConfigDTO = await _connection.DatabaseConnectionObject(ConnectionName); //ServerConfigDTO.ClientId = LoginDTO.ClientId; DigestHeader.ServerId = ServerConfigDTO.ServerId; DigestHeader.ServerConfigId = ServerConfigDTO.ServerConfigId; DigestHeader.ConnectionDatabaseName = ServerConfigDTO.DatabaseName; DigestHeader.DatabaseName = ServerConfigDTO.DatabaseName; DigestHeader.ServerIP = ServerConfigDTO.ServerIP; DigestHeader.ServerMachineName = ServerConfigDTO.ServerMachineName; DigestHeader.ServerName = ServerConfigDTO.ServerName; DigestHeader.SourceType = Convert.ToByte(ServerConfigDTO.TypeOfDb); DigestHeader.DatabaseType = ServerConfigDTO.DbType; DigestHeader.ServerUniqueDetails = ServerConfigDTO.UniqueDetails; #region DigestHeader.ServerConfigOffset = ServerConfigDTO.Offset; DigestHeader.ServerConfigMaxValue = ServerConfigDTO.MaxValue; LoginDTO.DatabaseName = ConnectionName; LoginDTO.UserCode = UserCode; LoginDTO.ModeOfOperation = 3;//We dont want log at login Time.. LoginDTO.DatabaseType = ServerConfigDTO.DbType; LoginDTO.ClientId = ServerConfigDTO.ClientId; LoginDTO.DatabaseType = ServerConfigDTO.DbType; DigestHeader.ClientId = ServerConfigDTO.ClientId; LoginDTO.ModeOfWorking = DigestHeader.ModeOfWorking; #region Added by Vikash For Auto Logged Out if (DigestHeader.LoginEventLogId == -1) { // AutoLoggedOutSession(ServerConfigDTO, LoginDTO, 0); } #endregion #region Added by Vikash on 04 Apr 2021 for Redmine 31734 if (DigestHeader.ModeOfWorking == 1)//Mobile and ESS { // UpdatePeriodInUser(UserCode, LoginDTO); } #endregion //GenericLazy = new GenericNhibernateLazyLoadingFrameDAL(LoginDTO, true); //User User = AuthDAL.GetUserLogin(UserCode, LoginDTO, GenericLazy); UserDTO LoginUserDTO = await _AuthenticationDAL.GetUser(UserCode, LoginDTO); DigestHeader.AttachmentOption = LoginUserDTO.TempAttachmentOption; await GetLoginDetail(UserCode, ConnectionName, DigestHeader, ServerConfigDTO); DateTime Validtodate = DateTime.UtcNow; DigestHeader.ValidToTime = Base64Encode(Validtodate.ToString()); return DigestHeader; } catch (Exception) { throw; } } public async Task AuthenticateUserViaKeyCloak(string ConnectionName, string UserCode, AuthenticationDTO DigestHeader) { ServerConfigDTO ServerConfigDTO = new(); LoginDTO LoginDTO = new LoginDTO(); try { ServerConfigDTO = await _connection.DatabaseConnectionObject(ConnectionName); DigestHeader.ServerId = ServerConfigDTO.ServerId; DigestHeader.ServerConfigId = ServerConfigDTO.ServerConfigId; DigestHeader.ConnectionDatabaseName = ServerConfigDTO.DatabaseName; DigestHeader.DatabaseName = ServerConfigDTO.DatabaseName; DigestHeader.ServerIP = ServerConfigDTO.ServerIP; DigestHeader.ServerMachineName = ServerConfigDTO.ServerMachineName; DigestHeader.ServerName = ServerConfigDTO.ServerName; DigestHeader.SourceType = Convert.ToByte(ServerConfigDTO.TypeOfDb); DigestHeader.DatabaseType = ServerConfigDTO.DbType; DigestHeader.ServerUniqueDetails = ServerConfigDTO.UniqueDetails; DigestHeader.ServerConfigOffset = ServerConfigDTO.Offset; DigestHeader.ServerConfigMaxValue = ServerConfigDTO.MaxValue; LoginDTO.DatabaseName = ConnectionName; LoginDTO.UserCode = UserCode; LoginDTO.ModeOfOperation = 3;//We dont want log at login Time.. LoginDTO.DatabaseType = ServerConfigDTO.DbType; LoginDTO.ClientId = ServerConfigDTO.ClientId; LoginDTO.DatabaseType = ServerConfigDTO.DbType; DigestHeader.ClientId = ServerConfigDTO.ClientId; LoginDTO.ModeOfWorking = DigestHeader.ModeOfWorking; #region Added by Vikash For Auto Logged Out if (DigestHeader.LoginEventLogId == -1) { // AutoLoggedOutSession(ServerConfigDTO, LoginDTO, 0); } #endregion #region Added by Vikash on 04 Apr 2021 for Redmine 31734 if (DigestHeader.ModeOfWorking == 1)//Mobile and ESS { // UpdatePeriodInUser(UserCode, LoginDTO); } #endregion UserDTO LoginUserDTO = await _AuthenticationDAL.GetUser(UserCode, LoginDTO); DigestHeader.AttachmentOption = LoginUserDTO.TempAttachmentOption; await GetLoginDetailViaKeycloak(UserCode, ConnectionName, DigestHeader, ServerConfigDTO); DateTime Validtodate = DateTime.UtcNow; DigestHeader.ValidToTime = Base64Encode(Validtodate.ToString()); return DigestHeader; } catch (Exception) { throw; } } public async Task AuthenticateUserByGmail(string ConnectionName, string PrimaryMail, AuthenticationDTO DigestHeader) { ServerConfigDTO ServerConfigDTO = new(); LoginDTO LoginDTO = new LoginDTO(); try { ServerConfigDTO = await _connection.DatabaseConnectionObject(ConnectionName); DigestHeader.ServerId = ServerConfigDTO.ServerId; DigestHeader.ServerConfigId = ServerConfigDTO.ServerConfigId; DigestHeader.ConnectionDatabaseName = ServerConfigDTO.DatabaseName; DigestHeader.DatabaseName = ServerConfigDTO.DatabaseName; DigestHeader.ServerIP = ServerConfigDTO.ServerIP; DigestHeader.ServerMachineName = ServerConfigDTO.ServerMachineName; DigestHeader.ServerName = ServerConfigDTO.ServerName; DigestHeader.SourceType = Convert.ToByte(ServerConfigDTO.TypeOfDb); DigestHeader.DatabaseType = ServerConfigDTO.DbType; DigestHeader.ServerUniqueDetails = ServerConfigDTO.UniqueDetails; #region DigestHeader.ServerConfigOffset = ServerConfigDTO.Offset; DigestHeader.ServerConfigMaxValue = ServerConfigDTO.MaxValue; LoginDTO.DatabaseName = ConnectionName; LoginDTO.ModeOfOperation = 3;//We dont want log at login Time.. LoginDTO.DatabaseType = ServerConfigDTO.DbType; LoginDTO.ClientId = ServerConfigDTO.ClientId; DigestHeader.ClientId = ServerConfigDTO.ClientId; LoginDTO.ModeOfWorking = DigestHeader.ModeOfWorking; #region Added by Vikash For Auto Logged Out if (DigestHeader.LoginEventLogId == -1) { // AutoLoggedOutSession(ServerConfigDTO, LoginDTO, 0); } #endregion #region Added by Vikash on 04 Apr 2021 for Redmine 31734 if (DigestHeader.ModeOfWorking == 1)//Mobile and ESS { // UpdatePeriodInUser(UserCode, LoginDTO); } #endregion #endregion UserDTO LoginUserDTO = await _AuthenticationDAL.GetUserByGMail(PrimaryMail, LoginDTO); DigestHeader.AttachmentOption = LoginUserDTO.TempAttachmentOption; await GetLoginDetailByEMail(PrimaryMail, ConnectionName, DigestHeader, ServerConfigDTO); DateTime Validtodate = DateTime.UtcNow; DigestHeader.ValidToTime = Base64Encode(Validtodate.ToString()); return DigestHeader; } catch (Exception) { throw; } } public string Base64Encode(string data) => Convert.ToBase64String(Encoding.UTF8.GetBytes(data)); public async Task GetLoginDetailByEMail(string PrimaryMail, string ConnectionName, AuthenticationDTO AuthenticationDTO, ServerConfigDTO ServerConfigDTO) { LoginDTO LoginDTO = new LoginDTO(); ClientInformationDTO ClientInformationDTO = new ClientInformationDTO(); try { LoginDTO.DatabaseName = ConnectionName; LoginDTO.ModeOfOperation = 3; LoginDTO.IsTransactionBeginRequired = 1;//Since it is purtely get.. // LoginDTO.DatabaseType = ServerConfigDTO.DbType; LoginDTO.MachineIP = AuthenticationDTO.MachineIP!; LoginDTO.Geo = AuthenticationDTO.Geo!; LoginDTO.LoginEventLogId = AuthenticationDTO.LoginEventLogId; LoginDTO.ModeOfWorking = AuthenticationDTO.ModeOfWorking; LoginDTO.ClientId = AuthenticationDTO.ClientId; LoginDTO.DeveloperId = AuthenticationDTO.DeveloperId; UserDTO LoginUserDTO = await _AuthenticationDAL.GetUserByGMail(PrimaryMail, LoginDTO); Activity.Current?.SetTag("UserName", LoginUserDTO.UserName); if (LoginUserDTO == null) { throw new MethodNotAllowedException("User is not found"); } #region New Login Done by Vikash to Block Login for give MachineIp on 01st Nov 2022 --commneted for now in gb5 string UserMachineIp = LoginUserDTO.UserLoginIp; if (UserMachineIp.ToLower() == "none" || UserMachineIp.ToLower() == "" || UserMachineIp == null) { //No Issue Proceed ..No need to check } #endregion #endregion LoginUserDTO.DatabaseName = ConnectionName; AuthenticationDTO.UserId = LoginUserDTO.UserId; AuthenticationDTO.UserName = LoginUserDTO.UserName; AuthenticationDTO.RoleId = LoginUserDTO.RoleId; AuthenticationDTO.WorkOUId = LoginUserDTO.UserWorkOuId; AuthenticationDTO.WorkPeriodId = LoginUserDTO.UserWorkPeriodId; AuthenticationDTO.WorkPartyBranchId = LoginUserDTO.UserWorkPartyBranchId; AuthenticationDTO.WorkPartyId = LoginUserDTO.UserWorkPartyId; AuthenticationDTO.WorkStoreId = LoginUserDTO.UserWorkStoreId; AuthenticationDTO.WorkDate = LoginUserDTO.UserWorkDate; AuthenticationDTO.ModeOfOperation = Convert.ToByte(LoginUserDTO.CheckModeofOperation); #region Commented and Added by Vikash for Handling date Time Field on 30th July 2019 AuthenticationDTO.TimeZoneId = LoginUserDTO.TimeZoneId; double OffSet = (DateTime.UtcNow - DateTime.UtcNow).TotalMinutes; AuthenticationDTO.ServiceOffSet = Convert.ToInt32(OffSet); AuthenticationDTO.TimeZone = LoginUserDTO.TimeZone; AuthenticationDTO.TimeZoneDisplayName = LoginUserDTO.TimeZoneDisplayName; AuthenticationDTO.FinalOffSetValue = AuthenticationDTO.ServiceOffSet + AuthenticationDTO.TimeZone; #endregion AuthenticationDTO.UserCriteriaConfigId = LoginUserDTO.UserCriteriaConfigId; AuthenticationDTO.ClientId = LoginDTO.ClientId; LoginDTO.UserId = AuthenticationDTO.UserId; LoginDTO.LanguageId = LoginUserDTO.UserLanguageId; LoginDTO.UserCriteriaConfigId = LoginUserDTO.UserCriteriaConfigId; LoginDTO.ModeOfOperation = (byte)ModeOfOperation.LIVE; //Since Login Time we dont have to write Log AuthenticationDTO.UserPrimaryMailId = LoginUserDTO.UserPrimaryMail; AuthenticationDTO.DateFormat = LoginUserDTO.UserDateFormat; AuthenticationDTO.CurrencyFormat = LoginUserDTO.UserCurrencyFormat; AuthenticationDTO.TimeFormat = LoginUserDTO.UserTimeFormat; AuthenticationDTO.QuantityFormat = LoginUserDTO.UserQuantityFormat; AuthenticationDTO.Delimiter = LoginUserDTO.UserDelimiter; #region Added for MFA by Vikash on 26 Aug 2022 AuthenticationDTO.MFAUserSetting = LoginUserDTO.CheckUserMFAUserSetting; AuthenticationDTO.MFAUserAccountId = LoginUserDTO.UserMFAUserAccountId; // CRITICAL-7 fix: never echo the raw TOTP secret/QR payload back to the client in a // login response — no endpoint anywhere validates a submitted MFA code against this // secret, and no FE surface reads MFAUserSecretKey/MFAQRCode, so this was a pure leak. AuthenticationDTO.MFAUserSecretKey = null; AuthenticationDTO.MFAQRCode = null; AuthenticationDTO.ShowQRCode = LoginUserDTO.CheckUserShowQRCode; if (LoginUserDTO.UserPasswordChangedOn.Year <= 1900) { AuthenticationDTO.IsForcePasswordChange = 0; } else { AuthenticationDTO.IsForcePasswordChange = 1; } #endregion #region Added by Vikash on 29th Oct 2018 for redmine 22567 AuthenticationDTO.OuCode = LoginUserDTO.UserWorkOuCode; AuthenticationDTO.OuName = LoginUserDTO.UserWorkOuName; AuthenticationDTO.WorkFinanceBookId = LoginUserDTO.WorkFinanceBookId;//Added by Vikash on 30th July 2019 #endregion //Added by Balaji for PPT AuthenticationDTO.UserLoginName = LoginUserDTO.UserLoginName; LoginDTO.DatabaseOffset = AuthenticationDTO.DatabaseOffset; AuthenticationDTO.ServerDate = DateTime.UtcNow; LoginDTO.LoginEventLogId = AuthenticationDTO.LoginEventLogId; LoginDTO.WorkOUId = AuthenticationDTO.WorkOUId; LoginDTO.WorkPeriodId = AuthenticationDTO.WorkPeriodId; AuthenticationDTO.CounterOperationId = LoginUserDTO.CounterOperationId; AuthenticationDTO.IsDeveloperEncryptionRequired = LoginUserDTO.IsEncryptionRequired; AuthenticationDTO.AttachmentOption = LoginUserDTO.TempAttachmentOption; AuthenticationDTO.UserCode = LoginUserDTO.UserCode; int Count = await _UserDAL.CheckAdminRights(LoginDTO, ServerConfigDTO); if (Count > 0) { AuthenticationDTO.AdminRights = 0;//Yes } AuthenticationDTO.SelectlistOperationType = Convert.ToByte(LoginUserDTO.SelectlistOperationType); AuthenticationDTO.ExpiryTime = LoginUserDTO.ExpiryTime; AuthenticationDTO.GraceTime = LoginUserDTO.GraceTime; AuthenticationDTO.IsIpBasedCheckingRequired = LoginUserDTO.IsIpBasedCheckingRequired; AuthenticationDTO.LastLoginUsedTime = Base64Encode(DateTime.UtcNow.ToString()); AuthenticationDTO.ValidityOfSession = CreateValidityOfSession(AuthenticationDTO, AuthenticationDTO.BaseUri!, AuthenticationDTO.MachineIP!); #region Save SucessFulLogin ClientInformationDTO.ClientMachineIp = LoginDTO.MachineIP;// endpoint.Address; // ClientInformationDTO.ClientCountry = CommonFunctionDAL.GetUserCountryByIp(ClientInformationDTO.ClientMachineIp); #endregion string password = Encode(AuthenticationDTO, LoginUserDTO.UserPassword); if (AuthenticationDTO.Response != password) //password check { throw new MethodNotAllowedException("Incorrect password.."); } return AuthenticationDTO; } catch (Exception) { throw; } } public async Task GetLoginDetail(string UserCode, string ConnectionName, AuthenticationDTO AuthenticationDTO , ServerConfigDTO ServerConfigDTO) { LoginDTO LoginDTO = new LoginDTO(); ClientInformationDTO ClientInformationDTO = new ClientInformationDTO(); try { LoginDTO.DatabaseName = ConnectionName; LoginDTO.ModeOfOperation = 3; LoginDTO.UserCode = UserCode; LoginDTO.IsTransactionBeginRequired = 1;//Since it is purtely get.. LoginDTO.MachineIP = AuthenticationDTO.MachineIP!; LoginDTO.Geo = AuthenticationDTO.Geo!; LoginDTO.LoginEventLogId = AuthenticationDTO.LoginEventLogId; LoginDTO.ModeOfWorking = AuthenticationDTO.ModeOfWorking; LoginDTO.ClientId = AuthenticationDTO.ClientId; LoginDTO.DeveloperId = AuthenticationDTO.DeveloperId; LoginDTO.DatabaseType = ServerConfigDTO.DbType; UserDTO LoginUserDTO = await _AuthenticationDAL.GetUser(UserCode, LoginDTO); Activity.Current?.SetTag("UserName", LoginUserDTO.UserName); if (LoginUserDTO == null) { throw new MethodNotAllowedException("User is not found"); } #region New Login Done by Vikash to Block Login for give MachineIp on 01st Nov 2022 --commneted for now in gb5 string UserMachineIp = LoginUserDTO.UserLoginIp; if (UserMachineIp.ToLower()! == "none" || UserMachineIp.ToLower()! == "" || UserMachineIp == null) { //No Issue Proceed ..No need to check } //else //{ // WebHeaderCollection Header = WebOperationContext.Current.IncomingRequest.Headers; // string LoginHeaderMachineIp = Header.Get("SystemUniqueDetails"); // if (LoginHeaderMachineIp == null) // { // //No Issue Proceed ..No need to check // } // else // { // if (UserMachineIp.Contains(LoginHeaderMachineIp)) // { // //No Issue Proceed ..Since usere MachineIp contrains LoginHeaderMachineIp // } // else // { // throw new MethodNotAllowedException("User is allowed to login with given Ip(s) " + UserMachineIp + " but login is made from Ip " + LoginHeaderMachineIp + " ..Can not login contact administrator.."); // } // } //} #endregion LoginUserDTO.DatabaseName = ConnectionName; AuthenticationDTO.UserId = LoginUserDTO.UserId; AuthenticationDTO.UserName = LoginUserDTO.UserName; AuthenticationDTO.RoleId = LoginUserDTO.RoleId; AuthenticationDTO.WorkOUId = LoginUserDTO.UserWorkOuId; AuthenticationDTO.WorkPeriodId = LoginUserDTO.UserWorkPeriodId; AuthenticationDTO.WorkPartyBranchId = LoginUserDTO.UserWorkPartyBranchId; AuthenticationDTO.WorkPartyId = LoginUserDTO.UserWorkPartyId; AuthenticationDTO.WorkStoreId = LoginUserDTO.UserWorkStoreId; AuthenticationDTO.WorkDate = LoginUserDTO.UserWorkDate; AuthenticationDTO.ModeOfOperation = Convert.ToByte(LoginUserDTO.CheckModeofOperation); #region Commented and Added by Vikash for Handling date Time Field on 30th July 2019 AuthenticationDTO.DatabaseOffset = await _AuthenticationDAL.DatabaseOffset(LoginDTO, ServerConfigDTO.DbType); AuthenticationDTO.TimeZoneId = LoginUserDTO.TimeZoneId; double OffSet = (DateTime.UtcNow - DateTime.UtcNow).TotalMinutes; AuthenticationDTO.ServiceOffSet = Convert.ToInt32(OffSet); AuthenticationDTO.TimeZone = LoginUserDTO.TimeZone; AuthenticationDTO.TimeZoneDisplayName = LoginUserDTO.TimeZoneDisplayName; AuthenticationDTO.FinalOffSetValue = AuthenticationDTO.ServiceOffSet + AuthenticationDTO.TimeZone; #endregion //AuthenticationDTO.DatabaseType = ServerConfigDTO.DbType; AuthenticationDTO.UserCriteriaConfigId = LoginUserDTO.UserCriteriaConfigId; AuthenticationDTO.ClientId = LoginDTO.ClientId; // AuthenticationDTO.SourceType = Convert.ToByte(ServerConfigDTO.TypeOfDb); LoginDTO.UserId = AuthenticationDTO.UserId; LoginDTO.LanguageId = LoginUserDTO.UserLanguageId; LoginDTO.UserCriteriaConfigId = LoginUserDTO.UserCriteriaConfigId; LoginDTO.ModeOfOperation = (byte)ModeOfOperation.LIVE; //Since Login Time we dont have to write Log //if (LoginDTO.UserCriteriaConfigId != -1 && LoginDTO.UserCriteriaConfigId != 0) //{ // AuthenticationDTO.UserCriteriaDTO = CriteriaConfig.GetCriteria(LoginDTO); //} //else //{ // AuthenticationDTO.UserCriteriaDTO = null; //} AuthenticationDTO.UserPrimaryMailId = LoginUserDTO.UserPrimaryMail; // AuthenticationDTO.ClientId = ServerConfigDTO.ClientId; //Added by Vikash on 20th August 2014 AuthenticationDTO.DateFormat = LoginUserDTO.UserDateFormat; AuthenticationDTO.CurrencyFormat = LoginUserDTO.UserCurrencyFormat; AuthenticationDTO.TimeFormat = LoginUserDTO.UserTimeFormat; AuthenticationDTO.QuantityFormat = LoginUserDTO.UserQuantityFormat; AuthenticationDTO.Delimiter = LoginUserDTO.UserDelimiter; #region Added for MFA by Vikash on 26 Aug 2022 AuthenticationDTO.MFAUserSetting = LoginUserDTO.CheckUserMFAUserSetting; AuthenticationDTO.MFAUserAccountId = LoginUserDTO.UserMFAUserAccountId; // CRITICAL-7 fix: never echo the raw TOTP secret/QR payload back to the client in a // login response — no endpoint anywhere validates a submitted MFA code against this // secret, and no FE surface reads MFAUserSecretKey/MFAQRCode, so this was a pure leak. AuthenticationDTO.MFAUserSecretKey = null; AuthenticationDTO.MFAQRCode = null; AuthenticationDTO.ShowQRCode = LoginUserDTO.CheckUserShowQRCode; if (LoginUserDTO.UserPasswordChangedOn.Year <= 1900) { AuthenticationDTO.IsForcePasswordChange = 0; } else { AuthenticationDTO.IsForcePasswordChange = 1; } #endregion #region Added by Vikash on 29th Oct 2018 for redmine 22567 //AuthenticationDTO.ServerMachineName = ServerConfigDTO.ServerMachineName; //AuthenticationDTO.ServerName = ServerConfigDTO.ServerName; //AuthenticationDTO.ServerIP = ServerConfigDTO.ServerIP; //AuthenticationDTO.ServerUniqueDetails = ServerConfigDTO.UniqueDetails; //string OuQuery=UserQueryBuilder.GET_OU_INFORMATION; //OuQuery=OuQuery.Replace(":ouid",AuthenticationDTO.WorkOUId.ToString()); //IList OUAuthenticationDTOs = GenericLazy.ExceuteSelectQuery(OuQuery, LoginDTO); //if (OUAuthenticationDTOs.Count > 0) //{ // AuthenticationDTO.OuCode = OUAuthenticationDTOs[0].OuCode; // AuthenticationDTO.OuName = OUAuthenticationDTOs[0].OuName; //} //else //{ // throw new MethodNotAllowedException("Ou is not found in database..Contact Administrator.."); //} AuthenticationDTO.OuCode = LoginUserDTO.UserWorkOuCode; AuthenticationDTO.OuName = LoginUserDTO.UserWorkOuName; AuthenticationDTO.WorkFinanceBookId = LoginUserDTO.WorkFinanceBookId;//Added by Vikash on 30th July 2019 #endregion //Added by Balaji for PPT AuthenticationDTO.UserLoginName = LoginUserDTO.UserLoginName; LoginDTO.DatabaseOffset = AuthenticationDTO.DatabaseOffset; AuthenticationDTO.ServerDate = DateTime.UtcNow; LoginDTO.LoginEventLogId = AuthenticationDTO.LoginEventLogId; LoginDTO.WorkOUId = AuthenticationDTO.WorkOUId; LoginDTO.WorkPeriodId = AuthenticationDTO.WorkPeriodId; AuthenticationDTO.CounterOperationId = LoginUserDTO.CounterOperationId; AuthenticationDTO.IsDeveloperEncryptionRequired = LoginUserDTO.IsEncryptionRequired; AuthenticationDTO.AttachmentOption = LoginUserDTO.TempAttachmentOption; AuthenticationDTO.UserCode = UserCode; //if (AuthenticationDTO.IsSchedulerRun == 1 && AuthenticationDTO.UserCode.ToLower() != "gb4admin") // have to discuss with vv sir //{ // LoginLicenceFinding(ServerConfigDTO.ClientId, ServerConfigDTO.ClientsiteId, GenericLazy, LoginDTO, LoginUserDTO); //} int Count = await _UserDAL.CheckAdminRights(LoginDTO, ServerConfigDTO); if (Count > 0) { AuthenticationDTO.AdminRights = 0;//Yes } AuthenticationDTO.SelectlistOperationType = Convert.ToByte(LoginUserDTO.SelectlistOperationType); AuthenticationDTO.ExpiryTime = LoginUserDTO.ExpiryTime; AuthenticationDTO.GraceTime = LoginUserDTO.GraceTime; AuthenticationDTO.IsIpBasedCheckingRequired = LoginUserDTO.IsIpBasedCheckingRequired; AuthenticationDTO.LastLoginUsedTime = Base64Encode(DateTime.UtcNow.ToString()); AuthenticationDTO.ValidityOfSession = CreateValidityOfSession(AuthenticationDTO, AuthenticationDTO.BaseUri!, AuthenticationDTO.MachineIP!); #region Save SucessFulLogin //IncomingWebRequestContext Request = WebOperationContext.Current.IncomingRequest; //ClientInformationDTO.BrowserInfo = Request.UserAgent; //OperationContext context = OperationContext.Current; ////Getting Incoming Message details //MessageProperties prop = context.IncomingMessageProperties; //Getting client endpoint details from message header // RemoteEndpointMessageProperty endpoint = prop[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty; ClientInformationDTO.ClientMachineIp = LoginDTO.MachineIP;// endpoint.Address; // ClientInformationDTO.ClientCountry = CommonFunctionDAL.GetUserCountryByIp(ClientInformationDTO.ClientMachineIp); #endregion // EventLogDTO EventLogDTO = Fill.FillEventLog(LoginUserDTO.UserName + " " + "Logged In", "", -1, LoginUserDTO.UserId, "", "", CommonFunctionDAL.SerializeJosn(ClientInformationDTO), "", -1899999997, -1, -1, AuthenticationDTO.WorkPeriodId, -1, AuthenticationDTO.WorkOUId, LoginDTO); //Unisoft.FrameworkDAL.Poco.Event.EventLog EventLog= new FrameworkDAL.Poco.Event.EventLog(); //EventLog=CommonFunctionDAL.GenericConversionDToToPoco< Unisoft.FrameworkDAL.Poco.Event.EventLog>(EventLogDTO); //SaveEvent = new GenericNhibernateLazyLoadingFrameDAL(LoginDTO, true); //SaveEvent.SaveWithoutEvent(EventLog, LoginDTO); //SaveEvent.Commit(); //int LoginEventLogId = -1; //EventLogDTO.EventLogLogBookId = AuthenticationDTO.DeveloperId; string password = Encode(AuthenticationDTO, LoginUserDTO.UserPassword); if (AuthenticationDTO.Response != password) //password check { throw new MethodNotAllowedException("Incorrect password.."); } #region Save Login EventLog to TEVENTLOG (tenant DB) + Session to MSESSIONSTORE (GB5 system DB) var loginTime = DateTime.UtcNow; if (AuthenticationDTO.LoginEventLogId == -1) { // New login: write a login-success event row to TEVENTLOG in the tenant DB. // EVENTTYPEID -1899999997 = login-success (matches GB4 constant). // LOGINEVENTLOGID = -1 because this IS the root login event (self-anchor). var eventLogDTO = new EventLogDTO { EventLogEventText = $"{LoginUserDTO.UserName} Logged In", EventLogLink = string.Empty, SourceId = -1, UserId = LoginUserDTO.UserId, EventLogTags = string.Empty, EventLogEventValue = string.Empty, EventLogData = string.Empty, EventLogGeo = string.Empty, EventTypeId = -1899999997, EventClassId = -1, EventLogLogBookId = AuthenticationDTO.DeveloperId, EventLogDataId = -1, EventLogTimeStamp = loginTime, EventChannelId = -1, EventLogOUId = AuthenticationDTO.WorkOUId, EventLogMachineIp = AuthenticationDTO.MachineIP ?? string.Empty, EventLogModeOfWorking = AuthenticationDTO.ModeOfWorking, EventLogLoginEventLogId = -1, Login = LoginDTO }; int newLoginEventLogId = await _EventLogBLL.SaveLoginEventLog(eventLogDTO, LoginDTO).ConfigureAwait(false); AuthenticationDTO.LoginEventLogId = newLoginEventLogId; LoginDTO.LoginEventLogId = newLoginEventLogId; } // Write (or refresh) the session row in MSESSIONSTORE in the GB5 system DB. // Safe upsert: inserts on first login, updates LASTLOGINUSEDTIME on re-login. var sessionDTO = new SessionStoreDTO { ServerconfigId = AuthenticationDTO.ServerConfigId, LoginEventLogId = AuthenticationDTO.LoginEventLogId, LoginTime = loginTime, LastLoginUsedTime = loginTime, MachineIp = AuthenticationDTO.MachineIP ?? string.Empty, UserId = LoginUserDTO.UserId, UserCode = UserCode, UserName = LoginUserDTO.UserName ?? string.Empty, IsActive = 0 }; await _SessionStoreBLL.InsertSessionAsync(sessionDTO, LoginDTO).ConfigureAwait(false); #endregion return AuthenticationDTO; } catch (Exception) { throw; } } public async Task GetLoginDetailViaKeycloak(string UserCode, string ConnectionName, AuthenticationDTO AuthenticationDTO, ServerConfigDTO ServerConfigDTO) { LoginDTO LoginDTO = new LoginDTO(); ClientInformationDTO ClientInformationDTO = new ClientInformationDTO(); try { LoginDTO.DatabaseName = ConnectionName; LoginDTO.ModeOfOperation = 3; LoginDTO.UserCode = UserCode; LoginDTO.IsTransactionBeginRequired = 1;//Since it is purtely get.. LoginDTO.MachineIP = AuthenticationDTO.MachineIP!; LoginDTO.Geo = AuthenticationDTO.Geo!; LoginDTO.LoginEventLogId = AuthenticationDTO.LoginEventLogId; LoginDTO.ModeOfWorking = AuthenticationDTO.ModeOfWorking; LoginDTO.ClientId = AuthenticationDTO.ClientId; LoginDTO.DeveloperId = AuthenticationDTO.DeveloperId; LoginDTO.DatabaseType = ServerConfigDTO.DbType; UserDTO LoginUserDTO = await _AuthenticationDAL.GetUser(UserCode, LoginDTO); Activity.Current?.SetTag("UserName", LoginUserDTO.UserName); if (LoginUserDTO == null) { throw new MethodNotAllowedException("User is not found"); } #region New Login Done by Vikash to Block Login for give MachineIp on 01st Nov 2022 --commneted for now in gb5 string UserMachineIp = LoginUserDTO.UserLoginIp; #endregion LoginUserDTO.DatabaseName = ConnectionName; AuthenticationDTO.UserId = LoginUserDTO.UserId; AuthenticationDTO.UserName = LoginUserDTO.UserName; AuthenticationDTO.RoleId = LoginUserDTO.RoleId; AuthenticationDTO.WorkOUId = LoginUserDTO.UserWorkOuId; AuthenticationDTO.WorkPeriodId = LoginUserDTO.UserWorkPeriodId; AuthenticationDTO.WorkPartyBranchId = LoginUserDTO.UserWorkPartyBranchId; AuthenticationDTO.WorkPartyId = LoginUserDTO.UserWorkPartyId; AuthenticationDTO.WorkStoreId = LoginUserDTO.UserWorkStoreId; AuthenticationDTO.WorkDate = LoginUserDTO.UserWorkDate; AuthenticationDTO.ModeOfOperation = Convert.ToByte(LoginUserDTO.CheckModeofOperation); #region Commented and Added by Vikash for Handling date Time Field on 30th July 2019 AuthenticationDTO.TimeZoneId = LoginUserDTO.TimeZoneId; double OffSet = (DateTime.UtcNow - DateTime.UtcNow).TotalMinutes; AuthenticationDTO.ServiceOffSet = Convert.ToInt32(OffSet); AuthenticationDTO.TimeZone = LoginUserDTO.TimeZone; AuthenticationDTO.TimeZoneDisplayName = LoginUserDTO.TimeZoneDisplayName; AuthenticationDTO.FinalOffSetValue = AuthenticationDTO.ServiceOffSet + AuthenticationDTO.TimeZone; #endregion AuthenticationDTO.UserCriteriaConfigId = LoginUserDTO.UserCriteriaConfigId; AuthenticationDTO.ClientId = LoginDTO.ClientId; LoginDTO.UserId = AuthenticationDTO.UserId; LoginDTO.LanguageId = LoginUserDTO.UserLanguageId; LoginDTO.UserCriteriaConfigId = LoginUserDTO.UserCriteriaConfigId; LoginDTO.ModeOfOperation = (byte)ModeOfOperation.LIVE; //Since Login Time we dont have to write Log AuthenticationDTO.UserPrimaryMailId = LoginUserDTO.UserPrimaryMail; AuthenticationDTO.DateFormat = LoginUserDTO.UserDateFormat; AuthenticationDTO.CurrencyFormat = LoginUserDTO.UserCurrencyFormat; AuthenticationDTO.TimeFormat = LoginUserDTO.UserTimeFormat; AuthenticationDTO.QuantityFormat = LoginUserDTO.UserQuantityFormat; AuthenticationDTO.Delimiter = LoginUserDTO.UserDelimiter; #region Added for MFA by Vikash on 26 Aug 2022 AuthenticationDTO.MFAUserSetting = LoginUserDTO.CheckUserMFAUserSetting; AuthenticationDTO.MFAUserAccountId = LoginUserDTO.UserMFAUserAccountId; // CRITICAL-7 fix: never echo the raw TOTP secret/QR payload back to the client in a // login response — no endpoint anywhere validates a submitted MFA code against this // secret, and no FE surface reads MFAUserSecretKey/MFAQRCode, so this was a pure leak. AuthenticationDTO.MFAUserSecretKey = null; AuthenticationDTO.MFAQRCode = null; AuthenticationDTO.ShowQRCode = LoginUserDTO.CheckUserShowQRCode; if (LoginUserDTO.UserPasswordChangedOn.Year <= 1900) { AuthenticationDTO.IsForcePasswordChange = 0; } else { AuthenticationDTO.IsForcePasswordChange = 1; } #endregion AuthenticationDTO.OuCode = LoginUserDTO.UserWorkOuCode; AuthenticationDTO.OuName = LoginUserDTO.UserWorkOuName; AuthenticationDTO.WorkFinanceBookId = LoginUserDTO.WorkFinanceBookId; AuthenticationDTO.UserLoginName = LoginUserDTO.UserLoginName; LoginDTO.DatabaseOffset = AuthenticationDTO.DatabaseOffset; AuthenticationDTO.ServerDate = DateTime.UtcNow; LoginDTO.LoginEventLogId = AuthenticationDTO.LoginEventLogId; LoginDTO.WorkOUId = AuthenticationDTO.WorkOUId; LoginDTO.WorkPeriodId = AuthenticationDTO.WorkPeriodId; AuthenticationDTO.CounterOperationId = LoginUserDTO.CounterOperationId; AuthenticationDTO.IsDeveloperEncryptionRequired = LoginUserDTO.IsEncryptionRequired; AuthenticationDTO.AttachmentOption = LoginUserDTO.TempAttachmentOption; AuthenticationDTO.UserCode = UserCode; int Count = await _UserDAL.CheckAdminRights(LoginDTO, ServerConfigDTO); if (Count > 0) { AuthenticationDTO.AdminRights = 0;//Yes } AuthenticationDTO.SelectlistOperationType = Convert.ToByte(LoginUserDTO.SelectlistOperationType); AuthenticationDTO.ExpiryTime = LoginUserDTO.ExpiryTime; AuthenticationDTO.GraceTime = LoginUserDTO.GraceTime; AuthenticationDTO.IsIpBasedCheckingRequired = LoginUserDTO.IsIpBasedCheckingRequired; AuthenticationDTO.LastLoginUsedTime = Base64Encode(DateTime.UtcNow.ToString()); AuthenticationDTO.ValidityOfSession = CreateValidityOfSession(AuthenticationDTO, AuthenticationDTO.BaseUri!, AuthenticationDTO.MachineIP!); ClientInformationDTO.ClientMachineIp = LoginDTO.MachineIP; return AuthenticationDTO; } catch (Exception) { throw; } } public string GetMachineIP(HttpContext httpContext) { if (httpContext == null) return null!; string ip = httpContext.Request.Headers["X-Forwarded-For"].FirstOrDefault()!; if (string.IsNullOrEmpty(ip)) ip = httpContext.Connection.RemoteIpAddress?.ToString()!; return ip; } public string CreateValidityOfSession(AuthenticationDTO AuthenticationDTO, string BaseUri, string MachineIp) { string OutPut = ""; string ValidationSessionData = ""; try { if (AuthenticationDTO.IsIpBasedCheckingRequired == 0)//In case of Yes MachineIP will be there { ValidationSessionData = AuthenticationDTO.UserId + "" + AuthenticationDTO.ServerId + "" + AuthenticationDTO.RoleId + "" + AuthenticationDTO.AppId + "" + AuthenticationDTO.DeviceId + "" + AuthenticationDTO.ValidToTime + "" + BaseUri + "" + MachineIp + AuthenticationDTO.DeveloperId + "" + AuthenticationDTO.DeveloperAccessKeyId; } else//In case of No MachineIP will be there { ValidationSessionData = AuthenticationDTO.UserId + "" + AuthenticationDTO.ServerId + "" + AuthenticationDTO.RoleId + "" + AuthenticationDTO.AppId + "" + AuthenticationDTO.DeviceId + "" + AuthenticationDTO.ValidToTime + "" + BaseUri + "" + AuthenticationDTO.DeveloperId + "" + AuthenticationDTO.DeveloperAccessKeyId; } OutPut = Base64Encode(ValidationSessionData); return OutPut; } catch (Exception) { throw; } } public string Encode(AuthenticationDTO DigestHeader, string UserCode, string Password) { try { MD5Encoder md5Encoder = new MD5Encoder(); string ha1 = md5Encoder.Encode(UserCode + DigestHeader.Realm + Password); string ha2 = md5Encoder.Encode(DigestHeader.Method + DigestHeader.Uri); string ha3 = md5Encoder.Encode(ha1 + DigestHeader.Nonce + DigestHeader.NounceCounter + DigestHeader.Cnonce + DigestHeader.Qop + ha2); return ha3; } catch (Exception) { throw; } } public string Encode(AuthenticationDTO DigestHeader, string Ha1) { try { MD5Encoder md5Encoder = new MD5Encoder(); string ha1 = Ha1; string ha2 = md5Encoder.Encode(DigestHeader.Method + DigestHeader.Uri); string ha3 = md5Encoder.Encode(ha1 + DigestHeader.Nonce + DigestHeader.NounceCounter + DigestHeader.Cnonce + DigestHeader.Qop + ha2); return ha3; } catch (Exception) { throw; } } public string EncryptPassword(string UserCode, string PassWord, string Realm) { try { MD5Encoder md5Encoder = new MD5Encoder(); string ha1 = md5Encoder.Encode(UserCode + Realm + PassWord); return ha1; } catch (Exception) { throw; } } public string Base64Decode(string Data) { try { System.Text.UTF8Encoding encoder = new System.Text.UTF8Encoding(); System.Text.Decoder utf8Decode = encoder.GetDecoder(); byte[] todecode_byte = Convert.FromBase64String(Data); int charCount = utf8Decode.GetCharCount(todecode_byte, 0, todecode_byte.Length); char[] decoded_char = new char[charCount]; utf8Decode.GetChars(todecode_byte, 0, todecode_byte.Length, decoded_char, 0); string result = new String(decoded_char); return result; } catch (Exception e) { throw new Exception("Error in base64Decode" + e.Message); } } public async Task GetAuthorizeUser(string UserCode , string ConnectionName) { ServerConfigDTO ServerConfigDTO = new(); AuthenticationDTO AuthenticationDTO = new(); LoginDTO LoginDTO = new(); try { ServerConfigDTO = await _connection.DatabaseConnectionObject(ConnectionName); AuthenticationDTO.ClientId = ServerConfigDTO.ClientId; AuthenticationDTO.ServerId = ServerConfigDTO.ServerId; AuthenticationDTO.ServerConfigId = ServerConfigDTO.ServerConfigId; AuthenticationDTO.ConnectionDatabaseName = ServerConfigDTO.DatabaseName; AuthenticationDTO.DatabaseName = ServerConfigDTO.DatabaseName; AuthenticationDTO.ServerIP = ServerConfigDTO.ServerIP; AuthenticationDTO.ServerMachineName = ServerConfigDTO.ServerMachineName; AuthenticationDTO.ServerName = ServerConfigDTO.ServerName; AuthenticationDTO.SourceType = Convert.ToByte(ServerConfigDTO.TypeOfDb); AuthenticationDTO.DatabaseType = ServerConfigDTO.DbType; AuthenticationDTO.ServerUniqueDetails = ServerConfigDTO.UniqueDetails; AuthenticationDTO.ServerConfigOffset = ServerConfigDTO.Offset; AuthenticationDTO.ServerConfigMaxValue = ServerConfigDTO.MaxValue; LoginDTO.DatabaseName = ConnectionName; LoginDTO.UserCode = UserCode; LoginDTO.DatabaseType = ServerConfigDTO.DbType; LoginDTO.ClientId = ServerConfigDTO.ClientId; await _AuthenticationDAL.GetUser(UserCode, LoginDTO); // validates the user exists; throws if not found await GetLoginDetail(UserCode, ConnectionName, AuthenticationDTO, ServerConfigDTO); DateTime Validtodate = DateTime.UtcNow; AuthenticationDTO.ValidToTime = Base64Encode(Validtodate.ToString()); return AuthenticationDTO; } catch (Exception) { throw; } } public async Task LogoutAsync(LoginDTO login, CancellationToken ct = default) { await _SessionStoreBLL.DeleteSessionAsync( login.ServerConfigId, login.LoginEventLogId, login, ct).ConfigureAwait(false); return "Logged out successfully."; } } }