Refactor cookie handling for user authentication; implement secure payload structure and cleanup invalid cookies
This commit is contained in:
@@ -85,21 +85,46 @@ $user = \S::get_session( 'user', true );
|
|||||||
\admin\Site::update();
|
\admin\Site::update();
|
||||||
\admin\Site::special_actions();
|
\admin\Site::special_actions();
|
||||||
|
|
||||||
$domain = preg_replace( '#^(http(s)?://)?w{3}\.#', '$1', $_SERVER['SERVER_NAME'] );
|
$domain = preg_replace( '/^www\./', '', $_SERVER['SERVER_NAME'] );
|
||||||
$cookie_name = str_replace( '.', '-', $domain );
|
$cookie_name = 'admin_remember_' . str_replace( '.', '-', $domain );
|
||||||
|
|
||||||
if ( isset( $_COOKIE[$cookie_name] ) && !isset( $_SESSION['user'] ) )
|
if ( isset( $_COOKIE[$cookie_name] ) && !isset( $_SESSION['user'] ) )
|
||||||
{
|
{
|
||||||
$obj = json_decode( $_COOKIE[$cookie_name] );
|
$payload = base64_decode($_COOKIE[$cookie_name]);
|
||||||
$login = $obj -> {'login'};
|
if ($payload !== false && strpos($payload, '.') !== false)
|
||||||
$password = $obj -> {'hash'};
|
|
||||||
|
|
||||||
if ( $mdb -> get( 'pp_users', '*', [ 'AND' => [ 'login' => $login, 'status' => 1, 'password' => $password ] ] ) )
|
|
||||||
{
|
{
|
||||||
\S::set_session( 'user', \admin\factory\Users::details( $login ) );
|
list($json, $sig) = explode('.', $payload, 2);
|
||||||
header( 'Location: /admin/articles/view_list/' );
|
$expected_sig = hash_hmac('sha256', $json, \admin\Site::APP_SECRET_KEY);
|
||||||
exit;
|
|
||||||
|
if (hash_equals($expected_sig, $sig))
|
||||||
|
{
|
||||||
|
$data = json_decode($json, true);
|
||||||
|
if ($data && isset($data['login']) && isset($data['ts']))
|
||||||
|
{
|
||||||
|
// Sprawdź czy cookie nie wygasło (14 dni)
|
||||||
|
if ((time() - $data['ts']) < (86400 * 14))
|
||||||
|
{
|
||||||
|
$user_data = $mdb->get('pp_users', '*', ['AND' => ['login' => $data['login'], 'status' => 1]]);
|
||||||
|
if ($user_data)
|
||||||
|
{
|
||||||
|
\S::set_session('user', \admin\factory\Users::details($data['login']));
|
||||||
|
$redirect = $_SERVER['REQUEST_URI'] ?: '/admin/articles/view_list/';
|
||||||
|
header('Location: ' . $redirect);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// Jeśli coś poszło nie tak, usuń nieprawidłowe cookie
|
||||||
|
setcookie($cookie_name, '', [
|
||||||
|
'expires' => time() - 86400,
|
||||||
|
'path' => '/',
|
||||||
|
'domain' => $domain,
|
||||||
|
'secure' => true,
|
||||||
|
'httponly' => true,
|
||||||
|
'samesite' => 'Lax',
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
echo \admin\view\Page::show();
|
echo \admin\view\Page::show();
|
||||||
|
|||||||
@@ -7,8 +7,9 @@ class Site
|
|||||||
const APP_SECRET_KEY = 'c3cb2537d25c0efc9e573d059d79c3b8';
|
const APP_SECRET_KEY = 'c3cb2537d25c0efc9e573d059d79c3b8';
|
||||||
|
|
||||||
static public function finalize_admin_login( array $user, string $domain, string $cookie_name, bool $remember = false ) {
|
static public function finalize_admin_login( array $user, string $domain, string $cookie_name, bool $remember = false ) {
|
||||||
\S::set_session('user', $user);
|
|
||||||
\S::delete_session('twofa_pending');
|
\S::set_session( 'user', $user );
|
||||||
|
\S::delete_session( 'twofa_pending' );
|
||||||
|
|
||||||
if ( $remember ) {
|
if ( $remember ) {
|
||||||
$payloadArr = [
|
$payloadArr = [
|
||||||
@@ -34,8 +35,8 @@ class Site
|
|||||||
public static function special_actions()
|
public static function special_actions()
|
||||||
{
|
{
|
||||||
$sa = \S::get('s-action');
|
$sa = \S::get('s-action');
|
||||||
$domain = preg_replace('#^(http(s)?://)?w{3}\.#', '$1', $_SERVER['SERVER_NAME']);
|
$domain = preg_replace('/^www\./', '', $_SERVER['SERVER_NAME']);
|
||||||
$cookie_name = str_replace('.', '-', $domain);
|
$cookie_name = 'admin_remember_' . str_replace( '.', '-', $domain );
|
||||||
|
|
||||||
switch ($sa)
|
switch ($sa)
|
||||||
{
|
{
|
||||||
@@ -46,18 +47,18 @@ class Site
|
|||||||
|
|
||||||
$result = \admin\factory\Users::logon($login, $pass);
|
$result = \admin\factory\Users::logon($login, $pass);
|
||||||
|
|
||||||
if ($result == 1)
|
if ( $result == 1 )
|
||||||
{
|
{
|
||||||
$user = \admin\factory\Users::details($login);
|
$user = \admin\factory\Users::details($login);
|
||||||
|
|
||||||
if ($user['twofa_enabled'] == 1)
|
if ( $user['twofa_enabled'] == 1 )
|
||||||
{
|
{
|
||||||
\S::set_session('twofa_pending', [
|
\S::set_session( 'twofa_pending', [
|
||||||
'uid' => (int)$user['id'],
|
'uid' => (int)$user['id'],
|
||||||
'login' => $login,
|
'login' => $login,
|
||||||
'remember' => (bool)\S::get('remember'),
|
'remember' => (bool)\S::get('remember'),
|
||||||
'started' => time(),
|
'started' => time(),
|
||||||
]);
|
] );
|
||||||
|
|
||||||
if ( !\admin\factory\Users::send_twofa_code( (int)$user['id'] ) )
|
if ( !\admin\factory\Users::send_twofa_code( (int)$user['id'] ) )
|
||||||
{
|
{
|
||||||
@@ -104,8 +105,7 @@ class Site
|
|||||||
case 'user-2fa-verify':
|
case 'user-2fa-verify':
|
||||||
{
|
{
|
||||||
$pending = \S::get_session('twofa_pending');
|
$pending = \S::get_session('twofa_pending');
|
||||||
if (!$pending || empty($pending['uid']))
|
if ( !$pending || empty( $pending['uid'] ) ) {
|
||||||
{
|
|
||||||
\S::alert('Sesja 2FA wygasła. Zaloguj się ponownie.');
|
\S::alert('Sesja 2FA wygasła. Zaloguj się ponownie.');
|
||||||
header('Location: /admin/');
|
header('Location: /admin/');
|
||||||
exit;
|
exit;
|
||||||
@@ -129,26 +129,13 @@ class Site
|
|||||||
|
|
||||||
// 2FA OK — finalna sesja
|
// 2FA OK — finalna sesja
|
||||||
$user = \admin\factory\Users::details($pending['login']);
|
$user = \admin\factory\Users::details($pending['login']);
|
||||||
\S::set_session('user', $user);
|
|
||||||
\S::delete_session('twofa_pending');
|
|
||||||
|
|
||||||
// Remember me – BEZPIECZNY podpis HMAC:
|
self::finalize_admin_login(
|
||||||
if (!empty($pending['remember']))
|
$user,
|
||||||
{
|
$domain,
|
||||||
$payloadArr = ['login' => $user['login'], 'ts' => time()];
|
$cookie_name,
|
||||||
$json = json_encode($payloadArr, JSON_UNESCAPED_SLASHES );
|
$pending['remember'] ? true : false
|
||||||
$sig = hash_hmac('sha256', $json, self::APP_SECRET_KEY );
|
);
|
||||||
$payload = base64_encode($json . '.' . $sig);
|
|
||||||
|
|
||||||
setcookie($cookie_name, $payload, [
|
|
||||||
'expires' => time() + (86400 * 14),
|
|
||||||
'path' => '/',
|
|
||||||
'domain' => $domain,
|
|
||||||
'secure' => true,
|
|
||||||
'httponly' => true,
|
|
||||||
'samesite' => 'Lax',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
header('Location: /admin/articles/view_list/');
|
header('Location: /admin/articles/view_list/');
|
||||||
exit;
|
exit;
|
||||||
@@ -180,7 +167,14 @@ class Site
|
|||||||
|
|
||||||
case 'user-logout':
|
case 'user-logout':
|
||||||
{
|
{
|
||||||
setcookie($cookie_name, "", time() - 86400, "/", $domain);
|
setcookie($cookie_name, "", [
|
||||||
|
'expires' => time() - 86400,
|
||||||
|
'path' => '/',
|
||||||
|
'domain' => $domain,
|
||||||
|
'secure' => true,
|
||||||
|
'httponly' => true,
|
||||||
|
'samesite' => 'Lax',
|
||||||
|
]);
|
||||||
\S::delete_session('twofa_pending');
|
\S::delete_session('twofa_pending');
|
||||||
session_destroy();
|
session_destroy();
|
||||||
header('Location: /admin/');
|
header('Location: /admin/');
|
||||||
|
|||||||
Reference in New Issue
Block a user