mirror of
https://github.com/Znote/ZnoteAAC.git
synced 2025-04-30 03:09:22 +02:00
TFS 1.2+ Two-Factor Authentication system.
RFC6238 Implementation of the OTP algorythm, tested with the app "Authy" from the iOS iPhone app store.
This commit is contained in:
parent
236eca61c8
commit
c3c236e13e
39
config.php
39
config.php
File diff suppressed because one or more lines are too long
@ -45,6 +45,7 @@ CREATE TABLE IF NOT EXISTS `znote_accounts` (
|
|||||||
`active` tinyint(4) NOT NULL DEFAULT '0',
|
`active` tinyint(4) NOT NULL DEFAULT '0',
|
||||||
`activekey` int(11) NOT NULL DEFAULT '0',
|
`activekey` int(11) NOT NULL DEFAULT '0',
|
||||||
`flag` varchar(20) NOT NULL,
|
`flag` varchar(20) NOT NULL,
|
||||||
|
`secret` char(16) DEFAULT NULL,
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB;
|
) ENGINE=InnoDB;
|
||||||
|
|
||||||
|
@ -532,4 +532,14 @@ function logo_exists($guild) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function generateRandomString($length = 16) {
|
||||||
|
$characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
|
||||||
|
$charactersLength = strlen($characters);
|
||||||
|
$randomString = '';
|
||||||
|
for ($i = 0; $i < $length; $i++) {
|
||||||
|
$randomString .= $characters[rand(0, $charactersLength - 1)];
|
||||||
|
}
|
||||||
|
return $randomString;
|
||||||
|
}
|
||||||
|
|
||||||
?>
|
?>
|
285
engine/function/rfc6238.php
Normal file
285
engine/function/rfc6238.php
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
<?php
|
||||||
|
/** https://github.com/Voronenko/PHPOTP/blob/08cda9cb9c30b7242cf0b3a9100a6244a2874927/code/base32static.php
|
||||||
|
* Encode in Base32 based on RFC 4648.
|
||||||
|
* Requires 20% more space than base64
|
||||||
|
* Great for case-insensitive filesystems like Windows and URL's (except for = char which can be excluded using the pad option for urls)
|
||||||
|
*
|
||||||
|
* @package default
|
||||||
|
* @author Bryan Ruiz
|
||||||
|
**/
|
||||||
|
class Base32Static {
|
||||||
|
|
||||||
|
private static $map = array(
|
||||||
|
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 7
|
||||||
|
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 15
|
||||||
|
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 23
|
||||||
|
'Y', 'Z', '2', '3', '4', '5', '6', '7', // 31
|
||||||
|
'=' // padding character
|
||||||
|
);
|
||||||
|
|
||||||
|
private static $flippedMap = array(
|
||||||
|
'A'=>'0', 'B'=>'1', 'C'=>'2', 'D'=>'3', 'E'=>'4', 'F'=>'5', 'G'=>'6', 'H'=>'7',
|
||||||
|
'I'=>'8', 'J'=>'9', 'K'=>'10', 'L'=>'11', 'M'=>'12', 'N'=>'13', 'O'=>'14', 'P'=>'15',
|
||||||
|
'Q'=>'16', 'R'=>'17', 'S'=>'18', 'T'=>'19', 'U'=>'20', 'V'=>'21', 'W'=>'22', 'X'=>'23',
|
||||||
|
'Y'=>'24', 'Z'=>'25', '2'=>'26', '3'=>'27', '4'=>'28', '5'=>'29', '6'=>'30', '7'=>'31'
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use padding false when encoding for urls
|
||||||
|
*
|
||||||
|
* @return base32 encoded string
|
||||||
|
* @author Bryan Ruiz
|
||||||
|
**/
|
||||||
|
public static function encode($input, $padding = true) {
|
||||||
|
if(empty($input)) return "";
|
||||||
|
|
||||||
|
$input = str_split($input);
|
||||||
|
$binaryString = "";
|
||||||
|
|
||||||
|
for($i = 0; $i < count($input); $i++) {
|
||||||
|
$binaryString .= str_pad(base_convert(ord($input[$i]), 10, 2), 8, '0', STR_PAD_LEFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
$fiveBitBinaryArray = str_split($binaryString, 5);
|
||||||
|
$base32 = "";
|
||||||
|
$i=0;
|
||||||
|
|
||||||
|
while($i < count($fiveBitBinaryArray)) {
|
||||||
|
$base32 .= self::$map[base_convert(str_pad($fiveBitBinaryArray[$i], 5,'0'), 2, 10)];
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($padding && ($x = strlen($binaryString) % 40) != 0) {
|
||||||
|
if($x == 8) $base32 .= str_repeat(self::$map[32], 6);
|
||||||
|
else if($x == 16) $base32 .= str_repeat(self::$map[32], 4);
|
||||||
|
else if($x == 24) $base32 .= str_repeat(self::$map[32], 3);
|
||||||
|
else if($x == 32) $base32 .= self::$map[32];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $base32;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function decode($input) {
|
||||||
|
if(empty($input)) return;
|
||||||
|
|
||||||
|
$paddingCharCount = substr_count($input, self::$map[32]);
|
||||||
|
$allowedValues = array(6,4,3,1,0);
|
||||||
|
|
||||||
|
if(!in_array($paddingCharCount, $allowedValues)) return false;
|
||||||
|
|
||||||
|
for($i=0; $i<4; $i++){
|
||||||
|
if($paddingCharCount == $allowedValues[$i] &&
|
||||||
|
substr($input, -($allowedValues[$i])) != str_repeat(self::$map[32], $allowedValues[$i])) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$input = str_replace('=','', $input);
|
||||||
|
$input = str_split($input);
|
||||||
|
$binaryString = "";
|
||||||
|
|
||||||
|
for($i=0; $i < count($input); $i = $i+8) {
|
||||||
|
$x = "";
|
||||||
|
|
||||||
|
if(!in_array($input[$i], self::$map)) return false;
|
||||||
|
|
||||||
|
for($j=0; $j < 8; $j++) {
|
||||||
|
$x .= str_pad(base_convert(@self::$flippedMap[@$input[$i + $j]], 10, 2), 5, '0', STR_PAD_LEFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
$eightBits = str_split($x, 8);
|
||||||
|
|
||||||
|
for($z = 0; $z < count($eightBits); $z++) {
|
||||||
|
$binaryString .= ( ($y = chr(base_convert($eightBits[$z], 2, 10))) || ord($y) == 48 ) ? $y:"";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $binaryString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://www.faqs.org/rfcs/rfc6238.html
|
||||||
|
// https://github.com/Voronenko/PHPOTP/blob/08cda9cb9c30b7242cf0b3a9100a6244a2874927/code/rfc6238.php
|
||||||
|
// Local changes: http -> https, consistent indentation, 200x200 -> 300x300 QR image size, PHP end tag
|
||||||
|
class TokenAuth6238 {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* verify
|
||||||
|
*
|
||||||
|
* @param string $secretkey Secret clue (base 32).
|
||||||
|
* @return bool True if success, false if failure
|
||||||
|
*/
|
||||||
|
public static function verify($secretkey, $code, $rangein30s = 3) {
|
||||||
|
$key = base32static::decode($secretkey);
|
||||||
|
$unixtimestamp = time()/30;
|
||||||
|
|
||||||
|
for($i=-($rangein30s); $i<=$rangein30s; $i++) {
|
||||||
|
$checktime = (int)($unixtimestamp+$i);
|
||||||
|
$thiskey = self::oath_hotp($key, $checktime);
|
||||||
|
|
||||||
|
if ((int)$code == self::oath_truncate($thiskey,6)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static function getTokenCode($secretkey,$rangein30s = 3) {
|
||||||
|
$result = "";
|
||||||
|
$key = base32static::decode($secretkey);
|
||||||
|
$unixtimestamp = time()/30;
|
||||||
|
|
||||||
|
for($i=-($rangein30s); $i<=$rangein30s; $i++) {
|
||||||
|
$checktime = (int)($unixtimestamp+$i);
|
||||||
|
$thiskey = self::oath_hotp($key, $checktime);
|
||||||
|
$result = $result." # ".self::oath_truncate($thiskey,6);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getTokenCodeDebug($secretkey,$rangein30s = 3) {
|
||||||
|
$result = "";
|
||||||
|
print "<br/>SecretKey: $secretkey <br/>";
|
||||||
|
|
||||||
|
$key = base32static::decode($secretkey);
|
||||||
|
print "Key(base 32 decode): $key <br/>";
|
||||||
|
|
||||||
|
$unixtimestamp = time()/30;
|
||||||
|
print "UnixTimeStamp (time()/30): $unixtimestamp <br/>";
|
||||||
|
|
||||||
|
for($i=-($rangein30s); $i<=$rangein30s; $i++) {
|
||||||
|
$checktime = (int)($unixtimestamp+$i);
|
||||||
|
print "Calculating oath_hotp from (int)(unixtimestamp +- 30sec offset): $checktime basing on secret key<br/>";
|
||||||
|
|
||||||
|
$thiskey = self::oath_hotp($key, $checktime, true);
|
||||||
|
print "======================================================<br/>";
|
||||||
|
print "CheckTime: $checktime oath_hotp:".$thiskey."<br/>";
|
||||||
|
|
||||||
|
$result = $result." # ".self::oath_truncate($thiskey,6,true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getBarCodeUrl($username, $domain, $secretkey, $issuer) {
|
||||||
|
$url = "https://chart.apis.google.com/chart";
|
||||||
|
$url = $url."?chs=300x300&chld=M|0&cht=qr&chl=otpauth://totp/";
|
||||||
|
$url = $url.$username . "@" . $domain . "%3Fsecret%3D" . $secretkey . '%26issuer%3D' . rawurlencode($issuer);
|
||||||
|
return $url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function generateRandomClue($length = 16) {
|
||||||
|
$b32 = "234567QWERTYUIOPASDFGHJKLZXCVBNM";
|
||||||
|
$s = "";
|
||||||
|
|
||||||
|
for ($i = 0; $i < $length; $i++)
|
||||||
|
$s .= $b32[rand(0,31)];
|
||||||
|
|
||||||
|
return $s;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function hotp_tobytestream($key) {
|
||||||
|
$result = array();
|
||||||
|
$last = strlen($key);
|
||||||
|
for ($i = 0; $i < $last; $i = $i + 2) {
|
||||||
|
$x = $key[$i] + $key[$i + 1];
|
||||||
|
$x = strtoupper($x);
|
||||||
|
$x = hexdec($x);
|
||||||
|
$result = $result.chr($x);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function oath_hotp ($key, $counter, $debug=false) {
|
||||||
|
$result = "";
|
||||||
|
$orgcounter = $counter;
|
||||||
|
$cur_counter = array(0,0,0,0,0,0,0,0);
|
||||||
|
|
||||||
|
if ($debug) {
|
||||||
|
print "Packing counter $counter (".dechex($counter).")into binary string - pay attention to hex representation of key and binary representation<br/>";
|
||||||
|
}
|
||||||
|
|
||||||
|
for($i=7;$i>=0;$i--) { // C for unsigned char, * for repeating to the end of the input data
|
||||||
|
$cur_counter[$i] = pack ('C*', $counter);
|
||||||
|
|
||||||
|
if ($debug) {
|
||||||
|
print $cur_counter[$i]."(".dechex(ord($cur_counter[$i])).")"." from $counter <br/>";
|
||||||
|
}
|
||||||
|
|
||||||
|
$counter = $counter >> 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($debug) {
|
||||||
|
foreach ($cur_counter as $char) {
|
||||||
|
print ord($char) . " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
print "<br/>";
|
||||||
|
}
|
||||||
|
|
||||||
|
$binary = implode($cur_counter);
|
||||||
|
|
||||||
|
// Pad to 8 characters
|
||||||
|
str_pad($binary, 8, chr(0), STR_PAD_LEFT);
|
||||||
|
|
||||||
|
if ($debug) {
|
||||||
|
print "Prior to HMAC calculation pad with zero on the left until 8 characters.<br/>";
|
||||||
|
print "Calculate sha1 HMAC(Hash-based Message Authentication Code http://en.wikipedia.org/wiki/HMAC).<br/>";
|
||||||
|
print "hash_hmac ('sha1', $binary, $key)<br/>";
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = hash_hmac ('sha1', $binary, $key);
|
||||||
|
|
||||||
|
if ($debug) {
|
||||||
|
print "Result: $result <br/>";
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function oath_truncate($hash, $length = 6, $debug=false) {
|
||||||
|
$result="";
|
||||||
|
|
||||||
|
// Convert to dec
|
||||||
|
if($debug) {
|
||||||
|
print "converting hex hash into characters<br/>";
|
||||||
|
}
|
||||||
|
|
||||||
|
$hashcharacters = str_split($hash,2);
|
||||||
|
|
||||||
|
if($debug) {
|
||||||
|
print_r($hashcharacters);
|
||||||
|
print "<br/>and convert to decimals:<br/>";
|
||||||
|
}
|
||||||
|
|
||||||
|
for ($j=0; $j<count($hashcharacters); $j++) {
|
||||||
|
$hmac_result[]=hexdec($hashcharacters[$j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($debug) {
|
||||||
|
print_r($hmac_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://php.net/manual/ru/function.hash-hmac.php
|
||||||
|
// adopted from brent at thebrent dot net 21-May-2009 08:17 comment
|
||||||
|
|
||||||
|
$offset = $hmac_result[19] & 0xf;
|
||||||
|
|
||||||
|
if($debug) {
|
||||||
|
print "Calculating offset as 19th element of hmac:".$hmac_result[19]."<br/>";
|
||||||
|
print "offset:".$offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = (
|
||||||
|
(($hmac_result[$offset+0] & 0x7f) << 24 ) |
|
||||||
|
(($hmac_result[$offset+1] & 0xff) << 16 ) |
|
||||||
|
(($hmac_result[$offset+2] & 0xff) << 8 ) |
|
||||||
|
($hmac_result[$offset+3] & 0xff)
|
||||||
|
) % pow(10,$length);
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
@ -11,6 +11,10 @@
|
|||||||
Password: <br>
|
Password: <br>
|
||||||
<input type="password" name="password">
|
<input type="password" name="password">
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
Token: <br>
|
||||||
|
<input type="password" name="authcode">
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<input type="submit" value="Log in">
|
<input type="submit" value="Log in">
|
||||||
</li>
|
</li>
|
||||||
|
50
login.php
50
login.php
@ -4,12 +4,14 @@ logged_in_redirect();
|
|||||||
include 'layout/overall/header.php';
|
include 'layout/overall/header.php';
|
||||||
|
|
||||||
if (empty($_POST) === false) {
|
if (empty($_POST) === false) {
|
||||||
|
|
||||||
if ($config['log_ip']) {
|
if ($config['log_ip']) {
|
||||||
znote_visitor_insert_detailed_data(5);
|
znote_visitor_insert_detailed_data(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
$username = $_POST['username'];
|
$username = $_POST['username'];
|
||||||
$password = $_POST['password'];
|
$password = $_POST['password'];
|
||||||
//data_dump($_POST, false, "POST");
|
|
||||||
if (empty($username) || empty($password)) {
|
if (empty($username) || empty($password)) {
|
||||||
$errors[] = 'You need to enter a username and password.';
|
$errors[] = 'You need to enter a username and password.';
|
||||||
} else if (strlen($username) > 32 || strlen($password) > 64) {
|
} else if (strlen($username) > 32 || strlen($password) > 64) {
|
||||||
@ -41,6 +43,47 @@ if (empty($_POST) === false) {
|
|||||||
}
|
}
|
||||||
} else $status = true;
|
} else $status = true;
|
||||||
|
|
||||||
|
if ($status) {
|
||||||
|
// Regular login success, now lets check authentication token code
|
||||||
|
if ($config['TFSVersion'] == 'TFS_10' && $config['twoFactorAuthenticator']) {
|
||||||
|
require_once("engine/function/rfc6238.php");
|
||||||
|
|
||||||
|
// Two factor authentication code / token
|
||||||
|
$authcode = (isset($_POST['authcode'])) ? getValue($_POST['authcode']) : false;
|
||||||
|
|
||||||
|
// Load secret values from db
|
||||||
|
$query = mysql_select_single("SELECT `a`.`secret` AS `secret`, `za`.`secret` AS `znote_secret` FROM `accounts` AS `a` INNER JOIN `znote_accounts` AS `za` ON `a`.`id` = `za`.`account_id` WHERE `a`.`id`='".(int)$login."' LIMIT 1;");
|
||||||
|
|
||||||
|
// If account table HAS a secret, we need to validate it
|
||||||
|
if ($query['secret'] !== NULL) {
|
||||||
|
|
||||||
|
// Validate the secret first to make sure all is good.
|
||||||
|
if (TokenAuth6238::verify($query['znote_secret'], $authcode) !== true) {
|
||||||
|
$errors[] = "Submitted Two-Factor Authentication token is wrong.";
|
||||||
|
$errors[] = "Make sure to type the correct token from your mobile authenticator.";
|
||||||
|
$status = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// secret from accounts table is null/not set. Perhaps we can activate it:
|
||||||
|
if ($query['znote_secret'] !== NULL && $authcode !== false && !empty($authcode)) {
|
||||||
|
|
||||||
|
// Validate the secret first to make sure all is good.
|
||||||
|
if (TokenAuth6238::verify($query['znote_secret'], $authcode)) {
|
||||||
|
// Success, enable the 2FA system
|
||||||
|
mysql_update("UPDATE `accounts` SET `secret`= '$authcode' WHERE `id`='$login';");
|
||||||
|
} else {
|
||||||
|
$errors[] = "Activating Two-Factor authentication failed.";
|
||||||
|
$errors[] = "Try to login without token and configure your app properly.";
|
||||||
|
$errors[] = "Submitted Two-Factor Authentication token is wrong.";
|
||||||
|
$errors[] = "Make sure to type the correct token from your mobile authenticator.";
|
||||||
|
$status = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // End tfs 1.0+ with 2FA auth
|
||||||
|
|
||||||
if ($status) {
|
if ($status) {
|
||||||
setSession('user_id', $login);
|
setSession('user_id', $login);
|
||||||
|
|
||||||
@ -59,6 +102,7 @@ if (empty($_POST) === false) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
header('Location: index.php');
|
header('Location: index.php');
|
||||||
}
|
}
|
||||||
@ -69,5 +113,5 @@ if (empty($errors) === false) {
|
|||||||
<?php
|
<?php
|
||||||
echo output_errors($errors);
|
echo output_errors($errors);
|
||||||
}
|
}
|
||||||
include 'layout/overall/footer.php';
|
|
||||||
?>
|
include 'layout/overall/footer.php'; ?>
|
@ -241,6 +241,14 @@ if ($render_page) {
|
|||||||
<h1>My account</h1>
|
<h1>My account</h1>
|
||||||
<p>Welcome to your account page, <?php echo $user_data['name']; ?><br>
|
<p>Welcome to your account page, <?php echo $user_data['name']; ?><br>
|
||||||
You have <?php echo $user_data['premdays']; ?> days remaining premium account.</p>
|
You have <?php echo $user_data['premdays']; ?> days remaining premium account.</p>
|
||||||
|
<?php
|
||||||
|
if ($config['TFSVersion'] === 'TFS_10' && $config['twoFactorAuthenticator']) {
|
||||||
|
|
||||||
|
$query = mysql_select_single("SELECT `secret` FROM `accounts` WHERE `id`='".(int)$session_user_id."' LIMIT 1;");
|
||||||
|
$status = ($query['secret'] === NULL) ? false : true;
|
||||||
|
?><p>Account security with Two-factor Authentication: <a href="twofa.php"><?php echo ($status) ? 'Enabled' : 'Disabled'; ?></a></p><?php
|
||||||
|
}
|
||||||
|
?>
|
||||||
<h2>Character List: <?php echo $char_count; ?> characters.</h2>
|
<h2>Character List: <?php echo $char_count; ?> characters.</h2>
|
||||||
<?php
|
<?php
|
||||||
// Echo character list!
|
// Echo character list!
|
||||||
|
51
twofa.php
Normal file
51
twofa.php
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<?php require_once 'engine/init.php'; if ($config['twoFactorAuthenticator'] === false) die("twoFactorAuthenticator is disabled in config.php"); protect_page(); include 'layout/overall/header.php';
|
||||||
|
// Two-Factor Authentication setup page
|
||||||
|
if ($config['TFSVersion'] !== 'TFS_10') {
|
||||||
|
?>
|
||||||
|
<h1>Server compatibility error</h1>
|
||||||
|
<p>Sorry, this server is not compatible with Two-Factor Authentication.<br>
|
||||||
|
TFS 1.2 or higher is required to run two-factor authentication, grab it
|
||||||
|
<a href="https://github.com/otland/forgottenserver/releases" target="_BLANK">here</a>.</p>
|
||||||
|
<?php
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// General init
|
||||||
|
require_once("engine/function/rfc6238.php");
|
||||||
|
|
||||||
|
// Fetch the secret data from accounts and znote_accounts table
|
||||||
|
$query = mysql_select_single("SELECT `a`.`secret` AS `secret`, `za`.`secret` AS `znote_secret` FROM `accounts` AS `a` INNER JOIN `znote_accounts` AS `za` ON `a`.`id` = `za`.`account_id` WHERE `a`.`id`='".(int)$session_user_id."' LIMIT 1;");
|
||||||
|
|
||||||
|
// If secret column returns NULL on the regular accounts table, then it means the system is not active.
|
||||||
|
$status = ($query['secret'] === NULL) ? false : true;
|
||||||
|
|
||||||
|
// If secret column returns NULL on the znote_accounts table, then it means we havent generated a secret for it yet.
|
||||||
|
if ($query['znote_secret'] === NULL) {
|
||||||
|
$scrtString = ($query['secret'] === NULL) ? generateRandomString(16) : $query['secret'];
|
||||||
|
// Add secret to znote_accounts table
|
||||||
|
mysql_update("UPDATE `znote_accounts` SET `secret`= '$scrtString' WHERE `account_id`='$session_user_id';");
|
||||||
|
$query['znote_secret'] = $scrtString;
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTML rendering
|
||||||
|
?>
|
||||||
|
<h1>Two-Factor Authentication</h1>
|
||||||
|
<p>Account security with Two-factor Authentication: <b><?php echo ($status) ? 'Enabled' : 'Disabled'; ?></b>.</p>
|
||||||
|
|
||||||
|
<?php if ($status === false): ?>
|
||||||
|
<p><strong>Login with a token generated from this QR code to activate:</strong></p>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<img
|
||||||
|
src="<?php echo TokenAuth6238::getBarCodeUrl($user_data['name'], $_SERVER["HTTP_HOST"], $query['znote_secret'], preg_replace('/\s+/', '', $config['site_title'])); ?>"
|
||||||
|
alt="Two-Factor Authentication QR code image for this account."
|
||||||
|
/>
|
||||||
|
|
||||||
|
<h2>How to use:</h2>
|
||||||
|
<ol>
|
||||||
|
<li>Download an authenticator app for free on your mobile phone like <strong>Authy</strong> (<a target="_BLANK" href="https://play.google.com/store/apps/details?id=com.authy.authy">Android</a>), (<a target="_BLANK" href="https://itunes.apple.com/us/app/authy/id494168017">iPhone</a>) or <strong>Google Authenticator</strong> (<a target="_BLANK" href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2">Android</a>), (<a target="_BLANK" href="https://itunes.apple.com/us/app/google-authenticator/id388497605">iPhone</a>).</li>
|
||||||
|
<li>Scan the QR image with the app on your phone to create a Two-Factor account for this server.</li>
|
||||||
|
<li><a href="logout.php">Logout</a>, then login with username, password and token generated from your phone to enable Two-Factor Authentication.</li>
|
||||||
|
</ol>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
include 'layout/overall/footer.php'; ?>
|
Loading…
x
Reference in New Issue
Block a user