mirror of
https://github.com/danpros/htmly.git
synced 2026-04-17 11:16:00 +05:30
Improve MFA integration
Cleanup the code. Add password validation and error messages.
This commit is contained in:
parent
6d92d7044b
commit
505975e565
4 changed files with 176 additions and 148 deletions
|
|
@ -40,7 +40,7 @@ function create_user($userName, $password, $role)
|
|||
file_put_contents($file, "password = " . password_hash($password, PASSWORD_DEFAULT) . "\n" .
|
||||
"encryption = password_hash\n" .
|
||||
"role = " . $role . "\n" .
|
||||
"mfa_secret = none\n", LOCK_EX);
|
||||
"mfa_secret = disabled\n", LOCK_EX);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -56,6 +56,7 @@ function session($user, $pass)
|
|||
$user_enc = user('encryption', $user);
|
||||
$user_pass = user('password', $user);
|
||||
$user_role = user('role', $user);
|
||||
$mfa = user('mfa_secret', $user);
|
||||
|
||||
if(is_null($user_enc) || is_null($user_pass) || is_null($user_role)) {
|
||||
return $str = '<div class="error-message"><ul><li class="alert alert-danger">' . i18n('Invalid_Error') . '</li></ul></div>';
|
||||
|
|
@ -65,7 +66,6 @@ function session($user, $pass)
|
|||
if (password_verify($pass, $user_pass)) {
|
||||
if (session_status() == PHP_SESSION_NONE) session_start();
|
||||
if (password_needs_rehash($user_pass, PASSWORD_DEFAULT)) {
|
||||
$mfa = user('mfa_secret', $user);
|
||||
update_user($user, $pass, $user_role, $mfa);
|
||||
}
|
||||
$_SESSION[site_url()]['user'] = $user;
|
||||
|
|
@ -75,7 +75,6 @@ function session($user, $pass)
|
|||
}
|
||||
} else if (old_password_verify($pass, $user_enc, $user_pass)) {
|
||||
if (session_status() == PHP_SESSION_NONE) session_start();
|
||||
$mfa = user('mfa_secret', $user);
|
||||
update_user($user, $pass, $user_role, $mfa);
|
||||
$_SESSION[site_url()]['user'] = $user;
|
||||
header('location: admin');
|
||||
|
|
|
|||
|
|
@ -4,56 +4,61 @@ if (isset($_SESSION[site_url()]['user'])) {
|
|||
$user = $_SESSION[site_url()]['user'];
|
||||
}
|
||||
|
||||
use PragmaRX\Google2FA\Google2FA;
|
||||
use BaconQrCode\Renderer\GDLibRenderer;
|
||||
use BaconQrCode\Writer;
|
||||
use PragmaRX\Google2FA\Google2FA;
|
||||
use BaconQrCode\Renderer\GDLibRenderer;
|
||||
use BaconQrCode\Writer;
|
||||
|
||||
if (user('mfa_secret', $user) == 'disabled') {
|
||||
$google2fa = new Google2FA();
|
||||
$mfasecret = $google2fa->generateSecretKey();
|
||||
$mfa_state = user('mfa_secret', $user);
|
||||
|
||||
$g2faUrl = $google2fa->getQRCodeUrl(
|
||||
$user,
|
||||
site_url(),
|
||||
$mfasecret
|
||||
);
|
||||
if (is_null($mfa_state) || $mfa_state == 'disabled') {
|
||||
$google2fa = new Google2FA();
|
||||
$mfasecret = $google2fa->generateSecretKey();
|
||||
|
||||
$renderer = new GDLibRenderer(400);
|
||||
$writer = new Writer($renderer);
|
||||
$g2faUrl = $google2fa->getQRCodeUrl(
|
||||
$user,
|
||||
site_url(),
|
||||
$mfasecret
|
||||
);
|
||||
|
||||
$qrcode_image = base64_encode($writer->writeString($g2faUrl));
|
||||
$renderer = new GDLibRenderer(400);
|
||||
$writer = new Writer($renderer);
|
||||
|
||||
$qrcode_image = base64_encode($writer->writeString($g2faUrl));
|
||||
}
|
||||
?>
|
||||
<h2><?php echo i18n('config_mfa'); echo ': ' . $user; ?></h2>
|
||||
<br>
|
||||
<?php if (isset($error)) { ?>
|
||||
<div class="error-message"><?php echo $error ?></div>
|
||||
<?php } ?>
|
||||
<form method="POST">
|
||||
<input type="hidden" name="csrf_token" value="<?php echo get_csrf(); ?>">
|
||||
<input type="hidden" name="username" value="<?php echo $user; ?>">
|
||||
<?php if (user('mfa_secret', $user) == 'disabled') {
|
||||
echo '<div style="text-align:center;width:100%;"><img style="margin:-10px auto;" src="data:image/png;base64, '.$qrcode_image.' "/></div>
|
||||
<span style="text-align:center;width:100%;float:left;"><small>'.i18n('manualsetupkey').': '.$mfasecret.'</small></span>
|
||||
<div class="form-group row">
|
||||
<label for="site.url" class="col-sm-2 col-form-label">'.i18n('MFACode').'</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" name="mfacode" class="form-control" id="mfacode" value="" placeholder="'.i18n('verify_code').'">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="site.url" class="col-sm-2 col-form-label">'.i18n('Password').'</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" name="password" class="form-control" id="password" value="" placeholder="'.i18n('verify_password').'">
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" name="mfa_secret" value="'.$mfasecret.'">
|
||||
<input type="submit" class="btn btn-primary" style="width:100px;" value="'.i18n('Save').'">';
|
||||
} else {
|
||||
echo '<input type="hidden" name="mfa_secret" value="disabled">
|
||||
<div class="form-group row">
|
||||
<label for="site.url" class="col-sm-2 col-form-label">'.i18n('Password').'</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" name="password" class="form-control" id="password" value="" placeholder="'.i18n('verify_password').'">
|
||||
</div>
|
||||
</div>
|
||||
<input type="submit" class="btn btn-primary" style="width:100px;" value="'.i18n('disablemfa').'">';
|
||||
} ?>
|
||||
</form>
|
||||
<?php if (is_null($mfa_state) || $mfa_state == 'disabled') {?>
|
||||
<div style="text-align:center;width:100%;"><img style="margin:-10px auto;" src="data:image/png;base64, <?php echo $qrcode_image; ?>"/></div>
|
||||
<span style="text-align:center;width:100%;float:left;"><small><?php echo i18n('manualsetupkey') . ': ' . $mfasecret; ?></small></span>
|
||||
<div class="form-group row">
|
||||
<label for="site.url" class="col-sm-2 col-form-label"><?php echo i18n('MFACode');?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" name="mfacode" class="form-control" id="mfacode" value="" placeholder="<?php echo i18n('verify_code');?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="site.url" class="col-sm-2 col-form-label"><?php echo i18n('Password');?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" name="password" class="form-control" id="password" value="" placeholder="<?php echo i18n('verify_password');?>">
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" name="mfa_secret" value="<?php echo $mfasecret;?>">
|
||||
<input type="submit" class="btn btn-primary" style="width:100px;" value="<?php echo i18n('Save');?>">'
|
||||
<?php } else { ?>
|
||||
<input type="hidden" name="mfa_secret" value="disabled">
|
||||
<div class="form-group row">
|
||||
<label for="site.url" class="col-sm-2 col-form-label"><?php echo i18n('Password');?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" name="password" class="form-control" id="password" value="" placeholder="<?php echo i18n('verify_password');?>">
|
||||
</div>
|
||||
</div>
|
||||
<input type="submit" class="btn btn-primary" value="<?php echo i18n('disablemfa');?>">
|
||||
<?php } ?>
|
||||
</form>
|
||||
|
|
|
|||
204
system/htmly.php
204
system/htmly.php
|
|
@ -121,82 +121,82 @@ get('/index', function () {
|
|||
post('/login', function () {
|
||||
|
||||
$proper = (is_csrf_proper(from($_REQUEST, 'csrf_token')));
|
||||
if (config('login.protect.system') === 'google') {
|
||||
$captcha = isCaptcha(from($_REQUEST, 'g-recaptcha-response'));
|
||||
} elseif (config('login.protect.system') === 'cloudflare') {
|
||||
$captcha = isTurnstile(from($_REQUEST, 'cf-turnstile-response'));
|
||||
} else {
|
||||
$captcha = config('login.protect.system');
|
||||
if (is_null($captcha) || $captcha === 'disabled') {
|
||||
$captcha = true;
|
||||
} elseif ($captcha === 'cloudflare') {
|
||||
$captcha = isTurnstile(from($_REQUEST, 'cf-turnstile-response'));
|
||||
} elseif ($captcha === 'google') {
|
||||
$captcha = isCaptcha(from($_REQUEST, 'g-recaptcha-response'));
|
||||
}
|
||||
|
||||
$user = from($_REQUEST, 'user');
|
||||
$pass = from($_REQUEST, 'password');
|
||||
if ($proper && $captcha && !empty($user) && !empty($pass)) {
|
||||
|
||||
if (user('mfa_secret', $user) !== "disabled") {
|
||||
$mfa_secret = user('mfa_secret', $user);
|
||||
$mfacode = from($_REQUEST, 'mfacode');
|
||||
$google2fa = new Google2FA();
|
||||
if ($google2fa->verifyKey($mfa_secret, $mfacode, '1')) {
|
||||
session($user, $pass);
|
||||
$log = session($user, $pass);
|
||||
$mfa_secret = user('mfa_secret', $user);
|
||||
if ($proper && $captcha && !empty($user) && !empty($pass)) {
|
||||
if (!is_null($mfa_secret) && $mfa_secret !== "disabled") {
|
||||
$mfacode = from($_REQUEST, 'mfacode');
|
||||
$google2fa = new Google2FA();
|
||||
if ($google2fa->verifyKey($mfa_secret, $mfacode, '1')) {
|
||||
session($user, $pass);
|
||||
$log = session($user, $pass);
|
||||
|
||||
if (!empty($log)) {
|
||||
if (!empty($log)) {
|
||||
|
||||
config('views.root', 'system/admin/views');
|
||||
config('views.root', 'system/admin/views');
|
||||
|
||||
render('login', array(
|
||||
'title' => generate_title('is_default', i18n('Login')),
|
||||
'description' => i18n('Login') . ' ' . blog_title(),
|
||||
'canonical' => site_url(),
|
||||
'metatags' => generate_meta(null, null),
|
||||
'error' => '<ul>' . $log . '</ul>',
|
||||
'type' => 'is_login',
|
||||
'is_login' => true,
|
||||
'bodyclass' => 'in-login',
|
||||
'breadcrumb' => '<a href="' . site_url() . '">' . config('breadcrumb.home') . '</a> » ' . i18n('Login')
|
||||
));
|
||||
}
|
||||
} else {
|
||||
$message['error'] .= '<li class="alert alert-danger">' . i18n('MFA_Error') . '</li>';
|
||||
render('login', array(
|
||||
'title' => generate_title('is_default', i18n('Login')),
|
||||
'description' => i18n('Login') . ' ' . blog_title(),
|
||||
'canonical' => site_url(),
|
||||
'metatags' => generate_meta(null, null),
|
||||
'error' => '<ul>' . $log . '</ul>',
|
||||
'type' => 'is_login',
|
||||
'is_login' => true,
|
||||
'bodyclass' => 'in-login',
|
||||
'breadcrumb' => '<a href="' . site_url() . '">' . config('breadcrumb.home') . '</a> » ' . i18n('Login')
|
||||
));
|
||||
}
|
||||
} else {
|
||||
$message['error'] = '';
|
||||
$message['error'] .= '<li class="alert alert-danger">' . i18n('MFA_Error') . '</li>';
|
||||
config('views.root', 'system/admin/views');
|
||||
|
||||
config('views.root', 'system/admin/views');
|
||||
render('login', array(
|
||||
'title' => generate_title('is_default', i18n('Login')),
|
||||
'description' => i18n('Login') . ' ' . blog_title(),
|
||||
'canonical' => site_url(),
|
||||
'metatags' => generate_meta(null, null),
|
||||
'error' => '<ul>' . $message['error'] . '</ul>',
|
||||
'username' => $user,
|
||||
'password' => $pass,
|
||||
'type' => 'is_login',
|
||||
'is_login' => true,
|
||||
'bodyclass' => 'in-login',
|
||||
'breadcrumb' => '<a href="' . site_url() . '">' . config('breadcrumb.home') . '</a> » ' . i18n('Login')
|
||||
));
|
||||
}
|
||||
} else {
|
||||
session($user, $pass);
|
||||
$log = session($user, $pass);
|
||||
|
||||
render('login', array(
|
||||
'title' => generate_title('is_default', i18n('Login')),
|
||||
'description' => i18n('Login') . ' ' . blog_title(),
|
||||
'canonical' => site_url(),
|
||||
'metatags' => generate_meta(null, null),
|
||||
'error' => '<ul>' . $message['error'] . '</ul>',
|
||||
'username' => $user,
|
||||
'password' => $pass,
|
||||
'type' => 'is_login',
|
||||
'is_login' => true,
|
||||
'bodyclass' => 'in-login',
|
||||
'breadcrumb' => '<a href="' . site_url() . '">' . config('breadcrumb.home') . '</a> » ' . i18n('Login')
|
||||
));
|
||||
}
|
||||
} else {
|
||||
session($user, $pass);
|
||||
$log = session($user, $pass);
|
||||
if (!empty($log)) {
|
||||
|
||||
if (!empty($log)) {
|
||||
config('views.root', 'system/admin/views');
|
||||
|
||||
config('views.root', 'system/admin/views');
|
||||
|
||||
render('login', array(
|
||||
'title' => generate_title('is_default', i18n('Login')),
|
||||
'description' => i18n('Login') . ' ' . blog_title(),
|
||||
'canonical' => site_url(),
|
||||
'metatags' => generate_meta(null, null),
|
||||
'error' => '<ul>' . $log . '</ul>',
|
||||
'type' => 'is_login',
|
||||
'is_login' => true,
|
||||
'bodyclass' => 'in-login',
|
||||
'breadcrumb' => '<a href="' . site_url() . '">' . config('breadcrumb.home') . '</a> » ' . i18n('Login')
|
||||
));
|
||||
}
|
||||
}
|
||||
render('login', array(
|
||||
'title' => generate_title('is_default', i18n('Login')),
|
||||
'description' => i18n('Login') . ' ' . blog_title(),
|
||||
'canonical' => site_url(),
|
||||
'metatags' => generate_meta(null, null),
|
||||
'error' => '<ul>' . $log . '</ul>',
|
||||
'type' => 'is_login',
|
||||
'is_login' => true,
|
||||
'bodyclass' => 'in-login',
|
||||
'breadcrumb' => '<a href="' . site_url() . '">' . config('breadcrumb.home') . '</a> » ' . i18n('Login')
|
||||
));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$message['error'] = '';
|
||||
if (empty($user)) {
|
||||
|
|
@ -447,7 +447,7 @@ post('/edit/password', function() {
|
|||
} else {
|
||||
$login = site_url() . 'login';
|
||||
header("location: $login");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
get('/edit/mfa', function () {
|
||||
|
|
@ -474,34 +474,57 @@ post('/edit/mfa', function() {
|
|||
if (login() && $proper) {
|
||||
$username = from($_REQUEST, 'username');
|
||||
$mfa_secret = from($_REQUEST, 'mfa_secret');
|
||||
$mfacode = from($_REQUEST, 'mfacode');
|
||||
$user = $_SESSION[site_url()]['user'];
|
||||
$role = user('role', $user);
|
||||
$old_password = user('password', $user);
|
||||
$password = from($_REQUEST, 'password');
|
||||
$message['error'] = '';
|
||||
if ($user === $username) {
|
||||
if ($mfa_secret !== "disabled") {
|
||||
$mfacode = from($_REQUEST, 'mfacode');
|
||||
$google2fa = new Google2FA();
|
||||
if ($google2fa->verifyKey($mfa_secret, $mfacode, '1')) {
|
||||
$file = 'config/users/' . $user . '.ini';
|
||||
if (file_exists($file)) {
|
||||
if (!empty($mfa_secret)) {
|
||||
update_user($user, $password, $role, $mfa_secret);
|
||||
}
|
||||
}
|
||||
$redir = site_url() . 'admin';
|
||||
header("location: $redir");
|
||||
} else {
|
||||
$redir = site_url() . 'admin';
|
||||
header("location: $redir");
|
||||
}
|
||||
} else {
|
||||
$file = 'config/users/' . $user . '.ini';
|
||||
if (file_exists($file)) {
|
||||
update_user($user, $password, $role, 'disabled');
|
||||
}
|
||||
$redir = site_url() . 'admin';
|
||||
header("location: $redir");
|
||||
}
|
||||
if (!is_null($mfa_secret) && $mfa_secret !== "disabled") {
|
||||
$google2fa = new Google2FA();
|
||||
if ($google2fa->verifyKey($mfa_secret, $mfacode)) {
|
||||
if (password_verify($password, $old_password)) {
|
||||
if (!empty($mfa_secret)) {
|
||||
update_user($user, $password, $role, $mfa_secret);
|
||||
}
|
||||
} else {
|
||||
$message['error'] .= '<li class="alert alert-danger">' . i18n('Pass_Error') . '</li>';
|
||||
}
|
||||
} else {
|
||||
$message['error'] .= '<li class="alert alert-danger">' . i18n('MFA_Error') . '</li>';
|
||||
}
|
||||
config('views.root', 'system/admin/views');
|
||||
render('edit-mfa', array(
|
||||
'title' => generate_title('is_default', i18n('config_mfa')),
|
||||
'description' => safe_html(strip_tags(blog_description())),
|
||||
'canonical' => site_url(),
|
||||
'metatags' => generate_meta(null, null),
|
||||
'error' => '<ul>' . $message['error'] . '</ul>',
|
||||
'type' => 'is_profile',
|
||||
'is_admin' => true,
|
||||
'bodyclass' => 'edit-mfa',
|
||||
'breadcrumb' => '<a href="' . site_url() . '">' . config('breadcrumb.home') . '</a> » '. i18n('config_mfa'),
|
||||
));
|
||||
} else {
|
||||
if (password_verify($password, $old_password)) {
|
||||
update_user($user, $password, $role, 'disabled');
|
||||
} else {
|
||||
$message['error'] .= '<li class="alert alert-danger">' . i18n('Pass_Error') . '</li>';
|
||||
}
|
||||
config('views.root', 'system/admin/views');
|
||||
render('edit-mfa', array(
|
||||
'title' => generate_title('is_default', i18n('config_mfa')),
|
||||
'description' => safe_html(strip_tags(blog_description())),
|
||||
'canonical' => site_url(),
|
||||
'metatags' => generate_meta(null, null),
|
||||
'error' => '<ul>' . $message['error'] . '</ul>',
|
||||
'type' => 'is_profile',
|
||||
'is_admin' => true,
|
||||
'bodyclass' => 'edit-mfa',
|
||||
'breadcrumb' => '<a href="' . site_url() . '">' . config('breadcrumb.home') . '</a> » '. i18n('config_mfa'),
|
||||
));
|
||||
}
|
||||
} else {
|
||||
$redir = site_url();
|
||||
header("location: $redir");
|
||||
|
|
@ -509,8 +532,9 @@ post('/edit/mfa', function() {
|
|||
} else {
|
||||
$login = site_url() . 'login';
|
||||
header("location: $login");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Edit the frontpage
|
||||
get('/edit/frontpage', function () {
|
||||
|
||||
|
|
|
|||
|
|
@ -1226,7 +1226,7 @@ function get_author($name)
|
|||
$author->about = MarkdownExtra::defaultTransform(remove_html_comments($content));
|
||||
|
||||
$author->description = get_content_tag("d", $content, get_description($author->about));
|
||||
|
||||
|
||||
$author->avatar = get_content_tag("image", $content, site_url() . 'system/resources/images/logo-small.png');
|
||||
|
||||
$toc = explode('<!--toc-->', $author->about);
|
||||
|
|
@ -3440,9 +3440,9 @@ function head_contents()
|
|||
$output .= '<meta charset="utf-8" />' . "\n";
|
||||
$output .= '<meta http-equiv="X-UA-Compatible" content="IE=edge" />' . "\n";
|
||||
$output .= '<meta name="viewport" content="width=device-width, initial-scale=1" />' . "\n";
|
||||
if (config('show.version') == 'true') {
|
||||
$output .= '<meta name="generator" content="' . $version . '" />' . "\n";
|
||||
}
|
||||
if (config('show.version') == 'true') {
|
||||
$output .= '<meta name="generator" content="' . $version . '" />' . "\n";
|
||||
}
|
||||
$output .= $favicon;
|
||||
$output .= '<link rel="sitemap" href="' . site_url() . 'sitemap.xml" />' . "\n";
|
||||
$output .= '<link rel="alternate" type="application/rss+xml" title="' . blog_title() . ' Feed" href="' . site_url() . 'feed/rss" />' . "\n";
|
||||
|
|
@ -3583,8 +3583,8 @@ function isCaptcha($reCaptchaResponse)
|
|||
// Cloudflare Turnstile
|
||||
function isTurnstile($turnstileResponse)
|
||||
{
|
||||
$public = config("login.protect.public");
|
||||
$private = config("login.protect.private");
|
||||
$public = config("login.protect.public");
|
||||
$private = config("login.protect.private");
|
||||
$ip = $_SERVER['REMOTE_ADDR'];
|
||||
|
||||
$url = 'https://challenges.cloudflare.com/turnstile/v0/siteverify';
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue