ensureCorrectTime(array(new \RobThree\Auth\Providers\Time\HttpTimeProvider())); } catch (\RobThree\Auth\TwoFactorAuthException $e) { hesk_error(sprintf($hesklang['mfa_server_time_issue'], $e->getMessage())); } if ($secret === null) { $res = hesk_dbQuery("SELECT `mfa_secret` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users` WHERE `id` = " . intval($user_id)); $row = hesk_dbFetchAssoc($res); $secret = $row['mfa_secret']; } return $tfa->verifyCode($secret, $verification_code); } // endregion // region Backup Codes function generate_and_store_mfa_backup_codes($user_id, $delete_old_codes = true) { global $hesk_settings; if ($delete_old_codes) { delete_mfa_backup_codes($user_id); } $codes = array(); for ($code_index = 0; $code_index < 10; $code_index++) { $unique_code_generated = false; do { $code = generate_backup_code(); if (!in_array($code, $codes)) { $codes[] = $code; $unique_code_generated = true; store_backup_code($user_id, $code); } } while (!$unique_code_generated); } return $codes; } function generate_backup_code() { $valid_chars = '0123456789abcdef'; $code = ''; for ($char_index = 0; $char_index < 8; $char_index++) { $code .= $valid_chars[random_int(0, strlen($valid_chars) - 1)]; } return $code; } function store_backup_code($user_id, $code) { global $hesk_settings; $hashed_code = hesk_password_hash($code); hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."mfa_backup_codes` (`user_id`, `code`) VALUES (".intval($user_id).", '".hesk_dbEscape($hashed_code)."')"); } function delete_mfa_backup_codes($user_id) { global $hesk_settings; hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."mfa_backup_codes` WHERE `user_id` = ".intval($user_id)); } function delete_mfa_backup_code($user_id, $hashed_code) { global $hesk_settings; hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."mfa_backup_codes` WHERE `user_id` = ".intval($user_id)." AND `code` = '".hesk_dbEscape($hashed_code)."'"); } function verify_mfa_backup_code($user_id, $code) { global $hesk_settings; // Allow spaces, dashes, etc... in the backup code for easier printout $code = preg_replace('/[^0-9a-f]/', '', strtolower($code)); $res = hesk_dbQuery("SELECT `code` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."mfa_backup_codes` WHERE `user_id` = ".intval($user_id)); while ($row = hesk_dbFetchAssoc($res)) { if (hesk_password_verify($code, $row['code'])) { delete_mfa_backup_code($user_id, $row['code']); return true; } } return false; } // endregion