Implemented 2FA TOTP with Google Authenticator

This commit is contained in:
root 2019-06-16 22:33:55 -04:00
parent bc8091ae49
commit e247ad4ee4
13 changed files with 564 additions and 125 deletions

View File

@ -8,65 +8,89 @@
</button>
</div>
<form action="post.php" method="post" enctype="multipart/form-data" autocomplete="off">
<div class="modal-body bg-white">
<div class="form-group">
<label>Assign a User to a Client</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-user"></i></span>
<div class="modal-body bg-white">
<ul class="nav nav-pills nav-justified mb-3" id="pills-tab" role="tablist">
<li class="nav-item">
<a class="nav-link active" id="pills-user-tab" data-toggle="pill" href="#pills-user">User</a>
</li>
<li class="nav-item">
<a class="nav-link" id="pills-assign-tab" data-toggle="pill" href="#pills-assign">Assign</a>
</li>
</ul>
<hr>
<div class="tab-content" id="pills-tabContent">
<div class="tab-pane fade show active" id="pills-user">
<div class="form-group">
<label>Name</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-user"></i></span>
</div>
<input type="text" class="form-control" name="name" placeholder="Full Name" required autofocus>
</div>
</div>
<select class="form-control selectpicker show-tick" data-live-search="true" name="client">
<option value="0">No Client Assignment</option>
<?php
$sql = mysqli_query($mysqli,"SELECT * FROM clients");
while($row = mysqli_fetch_array($sql)){
$client_id = $row['client_id'];
$client_name = $row['client_name'];
?>
<option value="<?php echo $client_id; ?>"><?php echo $client_name; ?></option>
<?php
}
?>
</select>
<div class="form-group">
<label>Email</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-envelope"></i></span>
</div>
<input type="email" class="form-control" name="email" placeholder="Email Address" required>
</div>
</div>
<div class="form-group">
<label>Password</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-lock"></i></span>
</div>
<input type="password" class="form-control" name="password" placeholder="Enter a Password" required>
</div>
</div>
<div class="form-group">
<label>Avatar</label>
<input type="file" class="form-control-file" accept="image/*;capture=camera" name="file">
</div>
</div>
<div class="tab-pane fade" id="pills-assign">
<div class="form-group">
<label>Assign a User to a Client</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-user"></i></span>
</div>
<select class="form-control selectpicker show-tick" data-live-search="true" name="client">
<option value="0">No Client Assignment</option>
<?php
$sql = mysqli_query($mysqli,"SELECT * FROM clients");
while($row = mysqli_fetch_array($sql)){
$client_id = $row['client_id'];
$client_name = $row['client_name'];
?>
<option value="<?php echo $client_id; ?>"><?php echo $client_name; ?></option>
<?php
}
?>
</select>
</div>
</div>
</div>
</div>
<div class="form-group">
<label>Name</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-user"></i></span>
</div>
<input type="text" class="form-control" name="name" placeholder="Full Name" required autofocus>
</div>
</div>
<div class="form-group">
<label>Email</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-envelope"></i></span>
</div>
<input type="email" class="form-control" name="email" placeholder="Email Address" required>
</div>
</div>
<div class="form-group">
<label>Password</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-lock"></i></span>
</div>
<input type="password" class="form-control" name="password" placeholder="Enter a Password" required>
</div>
</div>
<div class="form-group">
<label>Avatar</label>
<input type="file" class="form-control-file" accept="image/*;capture=camera" name="file">
</div>
</div>
<div class="modal-footer bg-white">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>

96
base32static.php Normal file
View File

@ -0,0 +1,96 @@
<?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;
}
}

View File

@ -20,6 +20,7 @@
$session_name = $row['name'];
$session_avatar = $row['avatar'];
$session_client_id = $row['client_id'];
$session_token = $row['token'];
//Detects if using an apple device and uses apple maps instead of google
$iPod = stripos($_SERVER['HTTP_USER_AGENT'],"iPod");

View File

@ -6,11 +6,11 @@ $url_query_strings_sb = http_build_query(array_merge($_GET,array('sb' => $sb, 'o
if(isset($_GET['p'])){
$p = intval($_GET['p']);
$record_from = (($p)-1)*10;
$record_to = 10;
$record_from = (($p)-1)*6;
$record_to = 6;
}else{
$record_from = 0;
$record_to = 10;
$record_to = 6;
$p = 1;
}
@ -39,12 +39,9 @@ if(isset($_GET['o'])){
$disp = "DESC";
}
$sql = mysqli_query($mysqli,"SELECT SQL_CALC_FOUND_ROWS * FROM contacts WHERE client_id = $client_id AND (contact_name LIKE '%$q%') ORDER BY $sb $o LIMIT $record_from, $record_to");
$sql = mysqli_query($mysqli,"SELECT SQL_CALC_FOUND_ROWS * FROM contacts WHERE client_id = $client_id AND (contact_name LIKE '%$q%') ORDER BY $sb $o LIMIT $record_from, $record_to");
$num_rows = mysqli_fetch_row(mysqli_query($mysqli,"SELECT FOUND_ROWS()"));
$total_found_rows = $num_rows[0];
$total_pages = ceil($total_found_rows / 10);
?>

View File

@ -42,8 +42,6 @@ if(isset($_GET['o'])){
$sql = mysqli_query($mysqli,"SELECT SQL_CALC_FOUND_ROWS * FROM clients WHERE client_name LIKE '%$q%' OR client_email LIKE '%$q%' ORDER BY $sb $o LIMIT $record_from, $record_to");
$num_rows = mysqli_fetch_row(mysqli_query($mysqli,"SELECT FOUND_ROWS()"));
$total_found_rows = $num_rows[0];
$total_pages = ceil($total_found_rows / 10);
?>
@ -51,7 +49,7 @@ $total_pages = ceil($total_found_rows / 10);
<div class="card-header bg-dark text-white">
<h6 class="float-left mt-2"><i class="fa fa-users mr-2"></i>Clients</h6>
<button type="button" class="btn btn-primary float-right" data-toggle="modal" data-target="#addClientModal"><i class="fas fa-fw fa-user-plus"></i> New</button>
<button type="button" class="btn btn-primary btn-sm float-right" data-toggle="modal" data-target="#addClientModal"><i class="fas fa-fw fa-user-plus"></i> New</button>
</div>
<div class="card-body">
@ -68,12 +66,12 @@ $total_pages = ceil($total_found_rows / 10);
<table class="table table-striped table-borderless table-hover">
<thead class="text-dark">
<tr>
<th><a class="text-secondary" href="?<?php echo $url_query_strings_sb; ?>&sb=client_name&o=<?php echo $disp; ?>">Name <i class="fa fa-sort<?php if($disp=='ASC'){ echo "-up"; }else{ echo "-down"; }?>"></i></a></th>
<th><a href="?<?php echo $url_query_strings_sb; ?>&sb=client_type&o=<?php echo $disp; ?>">Type <i class="fa fa-sort-up"></i></a></th>
<th>Email</th>
<th>Phone</th>
<th class="text-right">Balance</th>
<th class="text-center">Action</th>
<th class="w-50"><a class="text-secondary" href="?<?php echo $url_query_strings_sb; ?>&sb=client_name&o=<?php echo $disp; ?>">Name <i class="fa fa-sort<?php if($disp=='ASC'){ echo "-up"; }else{ echo "-down"; }?>"></i></a></th>
<th class="w-10"><a href="?<?php echo $url_query_strings_sb; ?>&sb=client_type&o=<?php echo $disp; ?>">Type <i class="fa fa-sort-up"></i></a></th>
<th class="w-10">Email</th>
<th class="w-10">Phone</th>
<th class="w-10 text-right">Balance</th>
<th class="w-10 text-center">Action</th>
</tr>
</thead>
<tbody>

View File

@ -16,6 +16,21 @@ function keygen()
return $key;
}
function key32gen()
{
$chars .= "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$chars .= "234567";
while (1) {
$key = '';
srand((double) microtime() * 1000000);
for ($i = 0; $i < 32; $i++) {
$key .= substr($chars, (rand() % (strlen($chars))), 1);
}
break;
}
return $key;
}
function initials($str) {
$ret = '';
foreach (explode(' ', $str) as $word)

View File

@ -8,22 +8,48 @@ if(isset($_POST['login'])){
$email = mysqli_real_escape_string($mysqli,$_POST['email']);
$password = md5(mysqli_real_escape_string($mysqli,$_POST['password']));
$current_code = $_POST['current_code'];
$sql = mysqli_query($mysqli,"SELECT * FROM users WHERE email = '$email' AND password = '$password'");
if(mysqli_num_rows($sql) == 1){
$row = mysqli_fetch_array($sql);
$_SESSION['logged'] = TRUE;
$_SESSION['user_id'] = $row['user_id'];
$_SESSION['name'] = $row['name'];
$_SESSION['client_id'] = $row['client_id'];
$client_id = $row['client_id'];
$token = $row['token'];
if(empty($token)){
$_SESSION['logged'] = TRUE;
$_SESSION['user_id'] = $row['user_id'];
$_SESSION['name'] = $row['name'];
$_SESSION['client_id'] = $row['client_id'];
$client_id = $row['client_id'];
if($client_id > 0){
header("Location: client.php?client_id=$client_id");
if($client_id > 0){
header("Location: client.php?client_id=$client_id");
}else{
header("Location: $config_start_page");
}
}else{
header("Location: $config_start_page");
require_once("rfc6238.php");
if(TokenAuth6238::verify($token,$current_code)){
$_SESSION['logged'] = TRUE;
$_SESSION['user_id'] = $row['user_id'];
$_SESSION['name'] = $row['name'];
$_SESSION['client_id'] = $row['client_id'];
$client_id = $row['client_id'];
header("Location: $config_start_page");
}else{
$response = "
<div class='alert alert-danger'>
Invalid Code.
<button class='close' data-dismiss='alert'>&times;</button>
</div>
";
}
}
}else{
$response = "
<div class='alert alert-danger'>
@ -79,6 +105,12 @@ if(isset($_POST['login'])){
<label for="inputPassword">Password</label>
</div>
</div>
<div class="form-group">
<div class="form-label-group">
<input type="text" id="inputToken" name="current_code" class="form-control" placeholder="2FA Token if applicable">
<label for="inputToken">Token</label>
</div>
</div>
<button class="btn btn-primary btn-block" type="submit" name="login">Login</button>
</form>
</div>

View File

@ -1,59 +1,62 @@
<?php
<?php
$total_found_rows = $num_rows[0];
$total_pages = ceil($total_found_rows / 10);
if ($total_found_rows > 10) {
?>
<ul class="pagination justify-content-end">
<ul class="pagination justify-content-end">
<?php
if($total_pages <= 100){
$pages_split = 10;
}
if(($total_pages <= 1000) AND ($total_pages > 100)){
$pages_split = 100;
}
if(($total_pages <= 10000) AND ($total_pages > 1000)){
$pages_split = 1000;
}
if($p > 1){
$prev_class = "";
}else{
$prev_class = "disabled";
}
if($p <> $total_pages) {
$next_class = "";
}else{
$next_class = "disabled";
}
$url_query_strings = http_build_query(array_merge($_GET,array('p' => $i)));
$prev_page = $p - 1;
$next_page = $p + 1;
if($p > 1){
echo "<li class='page-item $prev_class'><a class='page-link' href='?$url_query_strings&p=$prev_page'>Prev</a></li>";
}
while($i < $total_pages){
$i++;
if(($i == 1) OR (($p <= 3) AND ($i <= 6)) OR (($i > $total_pages - 6) AND ($p > $total_pages - 3 )) OR (is_int($i / $pages_split)) OR (($p > 3) AND ($i >= $p - 2) AND ($i <= $p + 3)) OR ($i == $total_pages)){
if($p == $i ) {
$page_class = "active";
}else{
$page_class = "";
}
echo "<li class='page-item $page_class'><a class='page-link' href='?$url_query_strings&p=$i'>$i</a></li>";
<?php
if($total_pages <= 100){
$pages_split = 10;
}
if(($total_pages <= 1000) AND ($total_pages > 100)){
$pages_split = 100;
}
if(($total_pages <= 10000) AND ($total_pages > 1000)){
$pages_split = 1000;
}
if($p > 1){
$prev_class = "";
}else{
$prev_class = "disabled";
}
if($p <> $total_pages) {
$next_class = "";
}else{
$next_class = "disabled";
}
$url_query_strings = http_build_query(array_merge($_GET,array('p' => $i)));
$prev_page = $p - 1;
$next_page = $p + 1;
if($p > 1){
echo "<li class='page-item $prev_class'><a class='page-link' href='?$url_query_strings&p=$prev_page'>Prev</a></li>";
}
while($i < $total_pages){
$i++;
if(($i == 1) OR (($p <= 3) AND ($i <= 6)) OR (($i > $total_pages - 6) AND ($p > $total_pages - 3 )) OR (is_int($i / $pages_split)) OR (($p > 3) AND ($i >= $p - 2) AND ($i <= $p + 3)) OR ($i == $total_pages)){
if($p == $i ) {
$page_class = "active";
}else{
$page_class = "";
}
echo "<li class='page-item $page_class'><a class='page-link' href='?$url_query_strings&p=$i'>$i</a></li>";
}
}
}
if($p <> $total_pages){
echo "<li class='page_item $next_class'><a class='page-link' href='?$url_query_strings&p=$next_page'>Next</a></li>";
}
if($p <> $total_pages){
echo "<li class='page_item $next_class'><a class='page-link' href='?$url_query_strings&p=$next_page'>Next</a></li>";
}
?>
?>
</ul>
</ul>
<?php

View File

@ -15,6 +15,21 @@ use PHPMailer\PHPMailer\Exception;
$todays_date = date('Y-m-d');
if(isset($_POST['verify'])){
require_once("rfc6238.php");
$currentcode = $_POST['code']; //code to validate, for example received from device
if(TokenAuth6238::verify($session_token,$currentcode)){
$_SESSION['alert_message'] = "VALID!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!";
}else{
$_SESSION['alert_message'] = "INVALID";
}
header("Location: " . $_SERVER["HTTP_REFERER"]);
}
if(isset($_POST['edit_general_settings'])){
$config_start_page = strip_tags(mysqli_real_escape_string($mysqli,$_POST['config_start_page']));
@ -100,6 +115,18 @@ if(isset($_POST['edit_invoice_settings'])){
}
if(isset($_POST['settings_2fa'])){
$token = mysqli_real_escape_string($mysqli,$_POST['token']);
mysqli_query($mysqli,"UPDATE users SET token = '$token' WHERE user_id = $session_user_id");
$_SESSION['alert_message'] = "Updated User Token";
header("Location: " . $_SERVER["HTTP_REFERER"]);
}
if(isset($_GET['download_database'])){
// Get All Table Names From the Database

171
rfc6238.php Normal file
View File

@ -0,0 +1,171 @@
<?php
// http://www.faqs.org/rfcs/rfc6238.html
require_once(dirname(__FILE__).'/base32static.php');
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 = "http://chart.apis.google.com/chart";
$url = $url."?chs=200x200&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;
}
}

58
settings-user.php Normal file
View File

@ -0,0 +1,58 @@
<?php include("header.php");
?>
<div class="card mb-3">
<div class="card-header">
<h6 class="float-left mt-1"><i class="fa fa-fw fa-cog mr-2"></i>User Settings</h6>
</div>
<div class="card-body">
<form class="p-3" action="post.php" method="post" autocomplete="off">
<input type="hidden" name="secretkey" value="<?php echo $secret_key; ?>">
<div class="custom-control custom-switch mb-2">
<input type="checkbox" class="custom-control-input" name="en2fa" <?php if($en2fa == 1){ echo "checked"; } ?> value="1" id="customSwitch1">
<label class="custom-control-label" for="customSwitch1">Enable Two Factor Authentication</label>
</div>
<?php
require_once('rfc6238.php');
//Generate a base32 Key
$secretkey = key32gen();
//Generate QR Code based off the generated key
print sprintf('<img src="%s"/>',TokenAuth6238::getBarCodeUrl('','',$secretkey,'PittPC-CRM'));
?>
<input type="hidden" name="token" value="<?php echo $secretkey; ?>">
<hr>
<button type="submit" name="settings_2fa" class="btn btn-primary">Enable</button>
</form>
<hr>
<form class="p-3" action="post.php" method="post" autocomplete="off">
<div class="form-group">
<label>Enter Code</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-key"></i></span>
</div>
<input type="text" class="form-control" name="code" placeholder="Enter Code" required>
</div>
</div>
<hr>
<button type="submit" name="verify" class="btn btn-primary">Verify</button>
</form>
</div>
</div>
<?php include("footer.php"); ?>

View File

@ -22,6 +22,22 @@
<h1>User Agent: <?php echo $_SERVER['HTTP_USER_AGENT']; ?>
<p>This is a great starting point for new custom pages.</p>
<?php
require_once('rfc6238.php');
$secretkey = 'GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ';
$currentcode = '739453';
if (TokenAuth6238::verify($secretkey,$currentcode)) {
echo "Code is valid\n";
} else {
echo "Invalid code\n";
}
print sprintf('<img src="%s"/>',TokenAuth6238::getBarCodeUrl('','',$secretkey,'My%20App'));
print TokenAuth6238::getTokenCodeDebug($secretkey,0);
?>
<h3><?php echo $config_quote_email_subject; ?></h3>

View File

@ -41,6 +41,7 @@
<center>
<img height="128" width="128" src="<?php echo "$session_avatar"; ?>" class="img-fluid rounded-circle">
</center>
<a class="dropdown-item" href="settings-user.php"><i class="fa fa-fw fa-cog"></i> Settings</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="logout.php"><i class="fa fa-fw fa-sign-out-alt"></i> Logout</a>
</div>