diff --git a/apps/sync_mobile.php b/apps/sync_mobile.php new file mode 100644 index 0000000..f05c58e --- /dev/null +++ b/apps/sync_mobile.php @@ -0,0 +1,63 @@ + [ + "sync mobile" => "Sync Mobile App", + "scan sync qrcode" => "Scan this code with the mobile app or enter the code manually.", + "sync explained" => "Access your account and apps on the go. Use a sync code to securely connect your phone or tablet to Portal with the Netsyms Business mobile app.", + "generate sync" => "Create new sync code", + "active sync codes" => "Active codes", + "no active codes" => "No active codes.", + "done adding sync code" => "Done adding code" + ] +]); + +$APPS["sync_mobile"]["title"] = lang("sync mobile", false); +$APPS["sync_mobile"]["icon"] = "mobile"; + +if (!is_empty($_GET['delsynccode'])) { + if ($database->has("mobile_codes", ["AND" => ["uid" => $_SESSION['uid'], "codeid" => $_GET['delsynccode']]])) { + $database->delete("mobile_codes", ["AND" => ["uid" => $_SESSION['uid'], "codeid" => $_GET['delsynccode']]]); + } +} + +if ($_GET['mobilecode'] == "generate") { + if (!is_empty($_GET['showsynccode']) && $database->has("mobile_codes", ["AND" => ["uid" => $_SESSION['uid'], "codeid" => $_GET['showsynccode']]])) { + $code = $database->get("mobile_codes", 'code', ["AND" => ["uid" => $_SESSION['uid'], "codeid" => $_GET['showsynccode']]]); + } else { + $code = strtoupper(substr(md5(mt_rand() . uniqid("", true)), 0, 20)); + $database->insert('mobile_codes', ['uid' => $_SESSION['uid'], 'code' => $code]); + } + $url = str_replace("/", "\\", URL); + $codeuri = "bizsync://" . $url . "/" . $_SESSION['username'] . "/" . $code; + $qrCode = new QrCode($codeuri); + $qrCode->setSize(200); + $qrCode->setErrorCorrection("H"); + $qrcode = $qrCode->getDataUri(); + $chunk_code = trim(chunk_split($code, 5, ' ')); + $lang_done = lang("done adding sync code", false); + $APPS["sync_mobile"]["content"] = '
' . lang("scan sync qrcode", false) . '
' . << +
$chunk_code
+$lang_done +END; +} else { + $activecodes = $database->select("mobile_codes", ["codeid", "code"], ["uid" => $_SESSION['uid']]); + $content = '
' . lang("sync explained", false) . '
' + . '' + . lang("generate sync", false) . ''; + $content .= "
" . lang("active sync codes", false) . ":
"; + $content .= "
"; + if (count($activecodes) > 0) { + foreach ($activecodes as $c) { + $content .= "
" . trim(chunk_split($c['code'], 5, ' ')) . "
"; + } + } else { + $content .= "
" . lang("no active codes", false) . "
"; + } + $content .= "
"; + $APPS["sync_mobile"]["content"] = $content; +} \ No newline at end of file diff --git a/database.mwb b/database.mwb index df11b7e..e7161c3 100644 Binary files a/database.mwb and b/database.mwb differ diff --git a/lang/en_us.php b/lang/en_us.php index 802532b..56eec98 100644 --- a/lang/en_us.php +++ b/lang/en_us.php @@ -49,5 +49,7 @@ $STRINGS = [ "password complexity insufficent" => "The new password does not meet the minumum requirements defined by your system administrator.", "error loading widget" => "There was a problem loading this app.", "open app" => "Open App", - "sign in again" => "Please sign in again to continue." + "sign in again" => "Please sign in again to continue.", + "login failed try on web" => "There is a problem with your account. Visit Portal via a web browser for more information.", + "mobile login disabled" => "Mobile login has been disabled by your system administrator. Contact technical support for more information." ]; diff --git a/mobile/index.php b/mobile/index.php new file mode 100644 index 0000000..d8bc1ad --- /dev/null +++ b/mobile/index.php @@ -0,0 +1,63 @@ + "OK"])); +} + +if (MOBILE_ENABLED !== TRUE) { + exit(json_encode(["status" => "ERROR", "msg" => lang("mobile login disabled", false)])); +} + +// Make sure we have a username and access key +if (is_empty($VARS['username']) || is_empty($VARS['key'])) { + http_response_code(401); + die(json_encode(["status" => "ERROR", "msg" => "Missing username and/or access key."])); +} + +// Make sure the username and key are actually legit +$user_key_valid = $database->has('mobile_codes', ['[>]accounts' => ['uid' => 'uid']], ["AND" => ['mobile_codes.code' => $VARS['key'], 'accounts.username' => $VARS['username']]]); +if ($user_key_valid !== TRUE) { + http_response_code(401); + insertAuthLog(21, null, "Username: " . $VARS['username'] . ", Key: " . $VARS['key']); + die(json_encode(["status" => "ERROR", "msg" => "Invalid username and/or access key."])); +} + +// Process the action +switch ($VARS['action']) { + case "check_key": + // Check if the username/key combo is valid. + // If we get this far, it is, so return success. + exit(json_encode(["status" => "OK"])); + case "check_password": + if (get_account_status($VARS['username']) != "NORMAL") { + insertAuthLog(20, null, "Username: " . $VARS['username'] . ", Key: " . $VARS['key']); + exit(json_encode(["status" => "ERROR", "msg" => lang("login failed try on web", false)])); + } + if (authenticate_user($VARS['username'], $VARS['password'], $autherror)) { + $uid = $database->get("accounts", "uid", ["username" => $VARS['username']]); + insertAuthLog(19, $uid, "Key: " . $VARS['key']); + exit(json_encode(["status" => "OK", "uid" => $uid])); + } else { + if (!is_empty($autherror)) { + insertAuthLog(20, null, "Username: " . $VARS['username'] . ", Key: " . $VARS['key']); + exit(json_encode(["status" => "ERROR", "msg" => $autherror])); + } else { + insertAuthLog(20, null, "Username: " . $VARS['username'] . ", Key: " . $VARS['key']); + exit(json_encode(["status" => "ERROR", "msg" => lang("login incorrect", false)])); + } + } + default: + http_response_code(404); + die(json_encode(["status" => "ERROR", "msg" => "The requested action is not available."])); +} \ No newline at end of file diff --git a/pages.php b/pages.php index a00e280..deebc7b 100644 --- a/pages.php +++ b/pages.php @@ -22,6 +22,7 @@ define("APPS", [ "account_security" ], "security" => [ + "sync_mobile", "change_password", "setup_2fa" ], diff --git a/settings.template.php b/settings.template.php index 7aa48a0..09a13f5 100644 --- a/settings.template.php +++ b/settings.template.php @@ -44,6 +44,9 @@ define("SYSTEM_NAME", "Netsyms SSO Demo"); // For supported values, see http://php.net/manual/en/timezones.php define("TIMEZONE", "America/Denver"); +// Allow or prevent users from logging in via the mobile app. +define("MOBILE_ENABLED", TRUE); + // Base URL for site links. define('URL', 'http://localhost:8000/');