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/');