/// <summary> Function holding client Login validation and recording</summary> /// <param name="user"> Username to login as </param> /// <param name="pass"> password provided by client </param> /// <param name="remoteIP"> IP of client </param> /// <param name="version"> Version of Client</param> /// <returns> <see cref="LoginOutcome"/> containing result information </returns> private LoginOutcome Login(string user, string pass, string remoteIP, string version = null) { Credentials creds = null; LoginResult result = LoginResult.Failed_Unspecified; string reason = "none"; UserLoginInfo userInfo = userDB.Get(user); if (version != versionCode) { Log.Debug($"{nameof(LoginService)}: Version mismatch {version}, expected {versionCode}"); reason = VERSION_MISMATCH; result = LoginResult.Failed_VersionMismatch; } else if (!usernameValidator(user)) { Log.Debug($"{nameof(LoginService)}: Bad username {user}"); reason = "Invalid Username"; result = LoginResult.Failed_BadUsername; } else if (userInfo == null) { Log.Debug($"{nameof(LoginService)}: User {user} not found, creating them now. "); userInfo = CreateNewUser(user, pass, remoteIP); if (userInfo != null) { result = LoginResult.Success_Created; string token = EncodeJWT(new JsonObject("user", user), "Reee", 60 * 60 * 24); creds = new Credentials(user, token, userInfo.guid); } else { result = LoginResult.Failed_CreationCooldown; reason = "Too many account creations"; } } else { // Check credentials against existing credentials. if (loginsByUserId.ContainsKey(userInfo.guid)) { reason = "Already logged in"; result = LoginResult.Failed_UserAlreadyLoggedIn; } else if (!Verify(userInfo.hash, pass)) { reason = "Bad credentials"; result = LoginResult.Failed_BadCredentials; } else // normal existing user login { string token = EncodeJWT(new JsonObject("user", user), "Reee", 60 * 60 * 24); creds = new Credentials(user, token, userInfo.guid); result = LoginResult.Success; } } LoginAttempt attempt = new LoginAttempt(); attempt.result = result; attempt.result_desc = result.ToString(); attempt.timestamp = DateTime.UtcNow; //string hash = Hash(pass); //attempt.hash = hash; attempt.userName = user; attempt.ip = remoteIP; if (userInfo != null) { attempt.success = true; attempt.creation = result == LoginResult.Success_Created; } else { attempt.success = attempt.creation = false; } loginAttemptDB.Save($"{attempt.timestamp.UnixTimestamp()}-{attempt.userName}", attempt); LoginOutcome outcome; outcome.creds = creds; outcome.result = result; outcome.reason = reason;; outcome.userInfo = userInfo; return(outcome); }