forked from Business/AccountHub
Create login system, add i18n, add 2fa auth
parent
b16da81513
commit
2caec9b758
Binary file not shown.
@ -0,0 +1,6 @@
|
||||
<?php
|
||||
require_once __DIR__ . "/required.php";
|
||||
|
||||
dieifnotloggedin();
|
||||
?>
|
||||
Home
|
@ -1,17 +1,113 @@
|
||||
<?php
|
||||
require_once __DIR__ . "/required.php";
|
||||
|
||||
require_once __DIR__ . "/lib/login.php";
|
||||
|
||||
/* Authenticate user */
|
||||
$userpass_ok = false;
|
||||
$multiauth = false;
|
||||
if ($VARS['progress'] == "1") {
|
||||
if (authenticate_user($VARS['username'], $VARS['password'])) {
|
||||
switch (get_account_status($VARS['username'])) {
|
||||
case "LOCKED_OR_DISABLED":
|
||||
$alert = lang("account locked", false);
|
||||
break;
|
||||
case "TERMINATED":
|
||||
$alert = lang("account terminated", false);
|
||||
break;
|
||||
case "CHANGE_PASSWORD":
|
||||
$alert = lang("password expired", false);
|
||||
case "NORMAL":
|
||||
$userpass_ok = true;
|
||||
break;
|
||||
case "ALERT_ON_ACCESS":
|
||||
sendAlertEmail($VARS['username']);
|
||||
$userpass_ok = true;
|
||||
break;
|
||||
}
|
||||
if ($userpass_ok) {
|
||||
if (userHasTOTP($VARS['username'])) {
|
||||
$multiauth = true;
|
||||
} else {
|
||||
doLoginUser($VARS['username']);
|
||||
header('Location: home.php');
|
||||
die("Logged in, go to home.php");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$alert = lang("login incorrect", false);
|
||||
}
|
||||
} else if ($VARS['progress'] == "2") {
|
||||
if (verifyTOTP($VARS['username'], $VARS['authcode'])) {
|
||||
doLoginUser($VARS['username']);
|
||||
header('Location: home.php');
|
||||
die("Logged in, go to home.php");
|
||||
} else {
|
||||
$alert = lang("2fa incorrect", false);
|
||||
}
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
To change this license header, choose License Headers in Project Properties.
|
||||
To change this template file, choose Tools | Templates
|
||||
and open the template in the editor.
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title></title>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" contgreent="width=device-width, initial-scale=1">
|
||||
|
||||
<title><?php echo SITE_TITLE; ?></title>
|
||||
|
||||
<link href="static/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="static/css/app.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-6 col-md-4 col-lg-4 col-sm-offset-3 col-md-offset-4 col-lg-offset-4">
|
||||
<div>
|
||||
<img class="img-responsive banner-image" src="static/img/banner.png" />
|
||||
</div>
|
||||
<div class="panel panel-primary">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title"><?php lang("sign in"); ?></h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form action="" method="POST">
|
||||
<?php
|
||||
if (!is_empty($alert)) {
|
||||
?>
|
||||
<div class="alert alert-danger">
|
||||
<?php echo $alert; ?>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
if ($multiauth != true) {
|
||||
?>
|
||||
<input type="text" class="form-control" name="username" placeholder="<?php lang("username"); ?>" required="required" /><br />
|
||||
<input type="password" class="form-control" name="password" placeholder="<?php lang("password"); ?>" required="required" /><br />
|
||||
<input type="hidden" name="progress" value="1" />
|
||||
<?php
|
||||
} else if ($multiauth) {
|
||||
?>
|
||||
<div class="alert alert-info">
|
||||
<?php lang("2fa prompt"); ?>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="authcode" placeholder="<?php lang("authcode"); ?>" required="required" /><br />
|
||||
<input type="hidden" name="progress" value="2" />
|
||||
<input type="hidden" name="username" value="<?php echo $VARS['username']; ?>" />
|
||||
<?php
|
||||
// put your code here
|
||||
}
|
||||
?>
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<?php lang("continue"); ?>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="static/js/jquery-3.2.1.min.js"></script>
|
||||
<script src="static/js/bootstrap.min.js"></script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
define("STRINGS", [
|
||||
"sign in" => "Sign In",
|
||||
"username" => "Username",
|
||||
"password" => "Password",
|
||||
"continue" => "Continue",
|
||||
"authcode" => "Authentication code",
|
||||
"2fa prompt" => "Enter the six-digit code from your mobile authenticator app.",
|
||||
"2fa incorrect" => "Authentication code incorrect.",
|
||||
"login incorrect" => "Login incorrect.",
|
||||
"account locked" => "This account has been disabled. Contact technical support.",
|
||||
"password expired" => "You must change your password before continuing.",
|
||||
"account terminated" => "Account terminated. Access denied."
|
||||
]);
|
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
use Base32\Base32;
|
||||
use OTPHP\TOTP;
|
||||
|
||||
/**
|
||||
* 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 sendAlertEmail($username) {
|
||||
// TODO: add email code
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup $_SESSION values to log in a user
|
||||
* @param string $username
|
||||
*/
|
||||
function doLoginUser($username) {
|
||||
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['loggedin'] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate and store 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'], ['username' => $username])[0];
|
||||
$totp = new TOTP($userdata['email'], $encoded_secret);
|
||||
$totp->setIssuer(SYSTEM_NAME);
|
||||
$database->update('accounts', ['authsecret' => $encoded_secret], ['username' => $username]);
|
||||
return $totp->getProvisioningUri();
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify a TOTP multiauth code
|
||||
* @global $database
|
||||
* @param string $username
|
||||
* @param int $code
|
||||
* @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'])) {
|
||||
return false;
|
||||
}
|
||||
$totp = new TOTP(null, $userdata['authsecret']);
|
||||
echo $userdata['authsecret'] . ", " . $totp->now() . ", " . $code;
|
||||
return $totp->verify($code);
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
.banner-image {
|
||||
margin: 2em 0em;
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 434 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 58 KiB |
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 10 KiB |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
require __DIR__ . "/required.php";
|
||||
require __DIR__ . "/lib/login.php";
|
||||
|
||||
use Endroid\QrCode\QrCode;
|
||||
use OTPHP\TOTP;
|
||||
|
||||
if ($_GET['show'] == '1') {
|
||||
|
||||
$totp = new TOTP(
|
||||
"admin@netsyms.com", // The label (string)
|
||||
"ZBUJDTW5D5E6KBMDICAJSKRCX6VGQZCZ" // The secret encoded in base 32 (string)
|
||||
);
|
||||
|
||||
echo "Current OTP: " . $totp->now();
|
||||
|
||||
die();
|
||||
} else {
|
||||
|
||||
$user = "skylarmt";
|
||||
|
||||
$totp = newTOTP($user);
|
||||
|
||||
// Create a QR code
|
||||
$qrCode = new QrCode($totp);
|
||||
$qrCode->setSize(300);
|
||||
|
||||
// now we can output the QR code
|
||||
header('Content-Type: ' . $qrCode->getContentType(QrCode::IMAGE_TYPE_PNG));
|
||||
$qrCode->render(null, 'png');
|
||||
}
|
Loading…
Reference in New Issue