From ff33f9e6b35836fb98625ab0efe7ff9b80945bf1 Mon Sep 17 00:00:00 2001 From: Skylar Ittner Date: Fri, 16 Jun 2017 17:36:42 -0600 Subject: [PATCH] Add mobile API and pairing widget --- apps/sync_mobile.php | 63 ++++++++++++++++++++++++++++++++++++++++++ database.mwb | Bin 17006 -> 17873 bytes lang/en_us.php | 4 ++- mobile/index.php | 63 ++++++++++++++++++++++++++++++++++++++++++ pages.php | 1 + settings.template.php | 3 ++ 6 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 apps/sync_mobile.php create mode 100644 mobile/index.php 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 df11b7e8c8204905b507362e1f880fd30eee777e..e7161c36037b04313048e83f2ad4de6139217cf6 100644 GIT binary patch literal 17873 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 "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/');