diff --git a/lang/en_us.php b/lang/en_us.php
index 526fdad..9ddff0b 100644
--- a/lang/en_us.php
+++ b/lang/en_us.php
@@ -13,30 +13,14 @@ define("STRINGS", [
"password expired" => "You must change your password before continuing.",
"account terminated" => "Account terminated. Access denied.",
"account state error" => "Your account state is not stable. Log out, restart your browser, and try again.",
- "password on 500 list" => "The given password is ranked number {arg} out of the 500 most common passwords. Try a different one.",
"welcome user" => "Welcome, {user}!",
- "change password" => "Change password",
- "security options" => "Security options",
- "account security" => "Account security",
"sign out" => "Sign out",
"settings" => "Settings",
"options" => "Options",
"404 error" => "404 Error",
"page not found" => "Page not found.",
- "current password incorrect" => "The current password is incorrect. Try again.",
- "new password mismatch" => "The new passwords did not match. Try again.",
- "weak password" => "Password does not meet requirements.",
- "password updated" => "Password updated successfully.",
- "setup 2fa" => "Setup 2-factor authentication",
- "2fa removed" => "2-factor authentication disabled.",
- "2fa enabled" => "2-factor authentication activated.",
- "remove 2fa" => "Disable 2-factor authentication",
- "2fa explained" => "2-factor authentication adds more security to your account. You'll need an app such as Google Authenticator on your smartphone. When you have the app installed, you can enable 2-factor authentication by clicking the button below and scanning a QR code with the app. Whenever you sign in in the future, you'll need to input a six-digit code from your phone into the login page when prompted. You can disable 2-factor authentication from this page if you change your mind.",
- "2fa active" => "2-factor authentication is active on your account. To remove 2fa, reset your authentication secret, or change to a new security device, click the button below.",
- "enable 2fa" => "Enable 2-factor authentication",
- "scan 2fa qrcode" => "Scan the QR Code with the authenticator app, or enter the secret key manually.",
- "confirm 2fa" => "Finish setup",
"invalid parameters" => "Invalid request parameters.",
- "ldap server error" => "The LDAP server returned an error: {arg}",
+ "login server error" => "The login server returned an error: {arg}",
+ "login server user data error" => "The login server refused to provide account information. Try again or contact technical support.",
"home" => "Home",
]);
\ No newline at end of file
diff --git a/lib/login.php b/lib/login.php
index 67fdf90..a9e635b 100644
--- a/lib/login.php
+++ b/lib/login.php
@@ -1,147 +1,98 @@
debug()->insert('accounts', [
- 'username' => strtolower($username),
- 'password' => (is_null($password) ? null : encryptPassword($password)),
- 'realname' => $realname,
- 'email' => $email,
- 'phone1' => $phone1,
- 'phone2' => $phone2,
- 'acctstatus' => 1
- ]);
-
- return $database->id();
-}
-
-/**
- * Get where a user's account actually is.
- * @param string $username
- * @return string "LDAP", "LOCAL", "LDAP_ONLY", or "NONE".
- */
-function account_location($username, $password) {
- global $database;
- $user_exists = user_exists($username);
- if (!$user_exists && !LDAP_ENABLED) {
- return false;
- }
- if ($user_exists) {
- $userinfo = $database->select('accounts', ['password'], ['username' => $username])[0];
- // if password empty, it's an LDAP user
- if (is_empty($userinfo['password']) && LDAP_ENABLED) {
- return "LDAP";
- } else if (is_empty($userinfo['password']) && !LDAP_ENABLED) {
- return "NONE";
- } else {
- return "LOCAL";
- }
- } else {
- if (user_exists_ldap($username, $password)) {
- return "LDAP_ONLY";
- } else {
- return "NONE";
- }
- }
-}
-
-/**
- * Checks the given credentials against the database.
+ * Checks the given credentials against the API.
* @param string $username
* @param string $password
* @return boolean True if OK, else false
*/
function authenticate_user($username, $password) {
- global $database;
- global $ldap_config;
- if (is_empty($username) || is_empty($password)) {
- return false;
+ $client = new GuzzleHttp\Client();
+
+ $response = $client
+ ->request('POST', PORTAL_API, [
+ 'form_params' => [
+ 'key' => PORTAL_KEY,
+ 'action' => "auth",
+ 'username' => $username,
+ 'password' => $password
+ ]
+ ]);
+
+ if ($response->getStatusCode() > 299) {
+ sendError("Login server error: " . $response->getBody());
}
- $loc = account_location($username, $password);
- if ($loc == "NONE") {
- return false;
- } else if ($loc == "LOCAL") {
- $hash = $database->select('accounts', ['password'], ['username' => $username, "LIMIT" => 1])[0]['password'];
- return (comparePassword($password, $hash));
- } else if ($loc == "LDAP") {
- return authenticate_user_ldap($username, $password);
- } else if ($loc == "LDAP_ONLY") {
- if (authenticate_user_ldap($username, $password) === TRUE) {
- try {
- $user = (new LdapManager($ldap_config))->getRepository('user')->findOneByUsername($username);
- var_dump($user);
- adduser($user->getUsername(), null, $user->getName(), ($user->hasEmailAddress() ? $user->getEmailAddress() : null));
- return true;
- } catch (Exception $e) {
- sendError("LDAP error: " . $e->getMessage());
- }
- } else {
- return false;
- }
+
+ $resp = json_decode($response->getBody(), TRUE);
+ if ($resp['status'] == "OK") {
+ return true;
} else {
return false;
}
}
/**
- * Check if a username exists in the local database.
+ * Check if a username exists.
* @param String $username
*/
function user_exists($username) {
- global $database;
- return $database->has('accounts', ['username' => $username, "LIMIT" => QUERY_LIMIT]);
+ $client = new GuzzleHttp\Client();
+
+ $response = $client
+ ->request('POST', PORTAL_API, [
+ 'form_params' => [
+ 'key' => PORTAL_KEY,
+ 'action' => "userexists",
+ 'username' => $username
+ ]
+ ]);
+
+ if ($response->getStatusCode() > 299) {
+ sendError("Login server error: " . $response->getBody());
+ }
+
+ $resp = json_decode($response->getBody(), TRUE);
+ if ($resp['status'] == "OK" && $resp['exists'] === true) {
+ return true;
+ } else {
+ return false;
+ }
}
/**
* Get the account status: NORMAL, TERMINATED, LOCKED_OR_DISABLED,
* CHANGE_PASSWORD, or ALERT_ON_ACCESS
- * @global $database $database
* @param string $username
* @return string
*/
function get_account_status($username) {
- global $database;
- $loc = account_location($username);
- if ($loc == "LOCAL") {
- $statuscode = $database->select('accounts', [
- '[>]acctstatus' => [
- 'acctstatus' => 'statusid'
- ]
- ], [
- 'accounts.acctstatus',
- 'acctstatus.statuscode'
- ], [
- 'username' => $username,
- "LIMIT" => 1
- ]
- )[0]['statuscode'];
- return $statuscode;
- } else if ($loc == "LDAP") {
- // TODO: Read actual account status from AD servers
- return "NORMAL";
+ $client = new GuzzleHttp\Client();
+
+ $response = $client
+ ->request('POST', PORTAL_API, [
+ 'form_params' => [
+ 'key' => PORTAL_KEY,
+ 'action' => "acctstatus",
+ 'username' => $username
+ ]
+ ]);
+
+ if ($response->getStatusCode() > 299) {
+ sendError("Login server error: " . $response->getBody());
+ }
+
+ $resp = json_decode($response->getBody(), TRUE);
+ if ($resp['status'] == "OK") {
+ return $resp['account'];
} else {
- // account isn't setup properly
- return "LOCKED_OR_DISABLED";
+ return false;
}
}
@@ -150,93 +101,64 @@ function get_account_status($username) {
////////////////////////////////////////////////////////////////////////////////
/**
- * Setup $_SESSION values to log in a user
+ * Setup $_SESSION values with user data and set loggedin flag to true
* @param string $username
*/
-function doLoginUser($username, $password) {
- global $database;
- $userinfo = $database->select('accounts', ['email', 'uid', 'realname'], ['username' => $username])[0];
- $_SESSION['username'] = $username;
- $_SESSION['uid'] = $userinfo['uid'];
- $_SESSION['email'] = $userinfo['email'];
- $_SESSION['realname'] = $userinfo['realname'];
- $_SESSION['password'] = $password; // needed for things like EWS
- $_SESSION['loggedin'] = true;
-}
-
-/**
- * Send an alert email to the system admin
- *
- * Used when an account with the status ALERT_ON_ACCESS logs in
- * @param String $username the account username
- */
-function sendLoginAlertEmail($username) {
- // TODO: add email code
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// LDAP handling //
-////////////////////////////////////////////////////////////////////////////////
+function doLoginUser($username) {
+ $client = new GuzzleHttp\Client();
+
+ $response = $client
+ ->request('POST', PORTAL_API, [
+ 'form_params' => [
+ 'key' => PORTAL_KEY,
+ 'action' => "userinfo",
+ 'username' => $username
+ ]
+ ]);
-/**
- * Checks the given credentials against the LDAP server.
- * @param string $username
- * @param string $password
- * @return mixed True if OK, else false or the error code from the server
- */
-function authenticate_user_ldap($username, $password) {
- global $ldap_config;
- if (is_empty($username) || is_empty($password)) {
- return false;
+ if ($response->getStatusCode() > 299) {
+ sendError("Login server error: " . $response->getBody());
}
- $ldapManager = new LdapManager($ldap_config);
- $msg = "";
- $code = 0;
- if ($ldapManager->authenticate($username, $password, $msg, $code)) {
+
+ $resp = json_decode($response->getBody(), TRUE);
+ var_dump($resp);
+ if ($resp['status'] == "OK") {
+ $userinfo = $resp['data'];
+ $_SESSION['username'] = $username;
+ $_SESSION['uid'] = $userinfo['uid'];
+ $_SESSION['email'] = $userinfo['email'];
+ $_SESSION['realname'] = $userinfo['name'];
+ $_SESSION['password'] = $password;
+ $_SESSION['loggedin'] = true;
return true;
} else {
- return $code;
+ return false;
}
}
-/**
- * Check if a username exists on the LDAP server.
- * @global type $ldap_config
- * @param type $username
- * @return boolean true if yes, else false
- */
-function user_exists_ldap($username, $password) {
- global $ldap_config;
- $ldap = new LdapManager($ldap_config);
- if (!$ldap->authenticate($username, $password, $message, $code)) {
- switch ($code) {
- case ADResponseCodes::ACCOUNT_INVALID:
- return false;
- case ADResponseCodes::ACCOUNT_CREDENTIALS_INVALID:
- return true;
- case ADResponseCodes::ACCOUNT_RESTRICTIONS:
- return true;
- case ADResponseCodes::ACCOUNT_RESTRICTIONS_TIME:
- return true;
- case ADResponseCodes::ACCOUNT_RESTRICTIONS_DEVICE:
- return true;
- case ADResponseCodes::ACCOUNT_PASSWORD_EXPIRED:
- return true;
- case ADResponseCodes::ACCOUNT_DISABLED:
- return true;
- case ADResponseCodes::ACCOUNT_CONTEXT_IDS:
- return true;
- case ADResponseCodes::ACCOUNT_EXPIRED:
- return false;
- case ADResponseCodes::ACCOUNT_PASSWORD_MUST_CHANGE:
- return true;
- case ADResponseCodes::ACCOUNT_LOCKED:
- return true;
- default:
- return false;
- }
+function simLogin($username, $password) {
+ $client = new GuzzleHttp\Client();
+
+ $response = $client
+ ->request('POST', PORTAL_API, [
+ 'form_params' => [
+ 'key' => PORTAL_KEY,
+ 'action' => "login",
+ 'username' => $username,
+ 'password' => $password
+ ]
+ ]);
+
+ if ($response->getStatusCode() > 299) {
+ sendError("Login server error: " . $response->getBody());
+ }
+
+ $resp = json_decode($response->getBody(), TRUE);
+ if ($resp['status'] == "OK") {
+ return true;
+ } else {
+ return $resp['msg'];
}
- return true;
}
////////////////////////////////////////////////////////////////////////////////
@@ -245,43 +167,31 @@ function user_exists_ldap($username, $password) {
/**
* Check if a user has TOTP setup
- * @global $database $database
* @param string $username
* @return boolean true if TOTP secret exists, else false
*/
function userHasTOTP($username) {
- global $database;
- $secret = $database->select('accounts', 'authsecret', ['username' => $username])[0];
- if (is_empty($secret)) {
- return false;
- }
- return true;
-}
+ $client = new GuzzleHttp\Client();
+
+ $response = $client
+ ->request('POST', PORTAL_API, [
+ 'form_params' => [
+ 'key' => PORTAL_KEY,
+ 'action' => "hastotp",
+ 'username' => $username
+ ]
+ ]);
-/**
- * Generate a TOTP secret for the given user.
- * @param string $username
- * @return string OTP provisioning URI (for generating a QR code)
- */
-function newTOTP($username) {
- global $database;
- $secret = random_bytes(20);
- $encoded_secret = Base32::encode($secret);
- $userdata = $database->select('accounts', ['email', 'authsecret', 'realname'], ['username' => $username])[0];
- $totp = new TOTP((is_null($userdata['email']) ? $userdata['realname'] : $userdata['email']), $encoded_secret);
- $totp->setIssuer(SYSTEM_NAME);
- return $totp->getProvisioningUri();
-}
+ if ($response->getStatusCode() > 299) {
+ sendError("Login server error: " . $response->getBody());
+ }
-/**
- * Save a TOTP secret for the user.
- * @global $database $database
- * @param string $username
- * @param string $secret
- */
-function saveTOTP($username, $secret) {
- global $database;
- $database->update('accounts', ['authsecret' => $secret], ['username' => $username]);
+ $resp = json_decode($response->getBody(), TRUE);
+ if ($resp['status'] == "OK") {
+ return $resp['otp'];
+ } else {
+ return false;
+ }
}
/**
@@ -292,11 +202,26 @@ function saveTOTP($username, $secret) {
* @return boolean true if it's legit, else false
*/
function verifyTOTP($username, $code) {
- global $database;
- $userdata = $database->select('accounts', ['email', 'authsecret'], ['username' => $username])[0];
- if (is_empty($userdata['authsecret'])) {
+ $client = new GuzzleHttp\Client();
+
+ $response = $client
+ ->request('POST', PORTAL_API, [
+ 'form_params' => [
+ 'key' => PORTAL_KEY,
+ 'action' => "verifytotp",
+ 'username' => $username,
+ 'code' => $code
+ ]
+ ]);
+
+ if ($response->getStatusCode() > 299) {
+ sendError("Login server error: " . $response->getBody());
+ }
+
+ $resp = json_decode($response->getBody(), TRUE);
+ if ($resp['status'] == "OK") {
+ return $resp['valid'];
+ } else {
return false;
}
- $totp = new TOTP(null, $userdata['authsecret']);
- return $totp->verify($code);
}
diff --git a/nbproject/project.xml b/nbproject/project.xml
index f94ab98..3edeb05 100644
--- a/nbproject/project.xml
+++ b/nbproject/project.xml
@@ -3,7 +3,7 @@
org.netbeans.modules.php.project
- WebAppTemplate
+ BusinessAppTemplate
diff --git a/pages.php b/pages.php
index b22e658..6c876d4 100644
--- a/pages.php
+++ b/pages.php
@@ -3,7 +3,9 @@
// List of pages and metadata
define("PAGES", [
"home" => [
- "title" => "home"
+ "title" => "home",
+ "navbar" => true,
+ "icon" => "home"
],
"404" => [
"title" => "404 error"
diff --git a/settings.template.php b/settings.template.php
index d8e11e7..8bfd650 100644
--- a/settings.template.php
+++ b/settings.template.php
@@ -18,6 +18,20 @@ define("SITE_TITLE", "Web App Template");
// Used to identify the system in OTP and other places
define("SYSTEM_NAME", "Web App Template");
+// Which pages to show the app icon on:
+// index, app, both, none
+define("SHOW_ICON", "both");
+// Where to put the icon: top or menu
+// Overridden to 'menu' if MENU_BAR_STYLE is 'fixed'.
+define("ICON_POSITION", "menu");
+// App menu bar style: fixed or static
+define("MENU_BAR_STYLE", "fixed");
+
+// URL of the Business Portal API endpoint
+define("PORTAL_API", "http://localhost/api.php");
+// Business Portal API Key
+define("PORTAL_KEY", "123");
+
// For supported values, see http://php.net/manual/en/timezones.php
define("TIMEZONE", "America/Denver");
diff --git a/static/img/logo.png b/static/img/logo.png
new file mode 100644
index 0000000..d950420
Binary files /dev/null and b/static/img/logo.png differ
diff --git a/static/img/logo.svg b/static/img/logo.svg
new file mode 100644
index 0000000..410fb09
--- /dev/null
+++ b/static/img/logo.svg
@@ -0,0 +1,78 @@
+
+
+
+