Skip to content

Commit a088f45

Browse files
committed
add redirect after log in to support deep links
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
1 parent 75c7d6c commit a088f45

File tree

1 file changed

+131
-70
lines changed

1 file changed

+131
-70
lines changed

front/index.php

Lines changed: 131 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -2,98 +2,159 @@
22
<link rel="stylesheet" href="css/app.css">
33

44
<?php
5+
declare(strict_types=1);
56

6-
//------------------------------------------------------------------------------
7-
// check if authenticated
8-
// Be CAREFUL WHEN INCLUDING NEW PHP FILES
9-
require_once $_SERVER['DOCUMENT_ROOT'] . '/php/server/db.php';
10-
require_once $_SERVER['DOCUMENT_ROOT'] . '/php/templates/language/lang.php';
11-
require_once $_SERVER['DOCUMENT_ROOT'] . '/php/templates/security.php';
12-
13-
// capture the redirect to after log in query string if available
14-
$redirectTo = 'devices.php'; // Default destination
15-
if (!empty($_GET['next'])) {
16-
$decoded = base64_decode($_GET['next']);
17-
// Validate that it's a local path to prevent Open Redirect vulnerabilities
18-
if (strpos($decoded, '/') === 0 && strpos($decoded, '//') !== 0) {
19-
$redirectTo = $decoded;
20-
}
7+
require_once $_SERVER['DOCUMENT_ROOT'].'/php/server/db.php';
8+
require_once $_SERVER['DOCUMENT_ROOT'].'/php/templates/language/lang.php';
9+
require_once $_SERVER['DOCUMENT_ROOT'].'/php/templates/security.php';
10+
11+
session_start();
12+
13+
const COOKIE_NAME = 'NetAlertX_SaveLogin';
14+
const DEFAULT_REDIRECT = '/devices.php';
15+
16+
/* =====================================================
17+
Helper Functions
18+
===================================================== */
19+
20+
function safe_redirect(string $path): void {
21+
header("Location: {$path}", true, 302);
22+
exit;
2123
}
2224

23-
$CookieSaveLoginName = 'NetAlertX_SaveLogin';
25+
function validate_local_path(?string $encoded): string {
26+
if (!$encoded) return DEFAULT_REDIRECT;
2427

25-
if ($nax_WebProtection != 'true')
26-
{
28+
$decoded = base64_decode($encoded, true);
29+
if ($decoded === false) return DEFAULT_REDIRECT;
30+
31+
// strict local path check
32+
if (!preg_match('#^/[a-zA-Z0-9_\-/\.]*$#', $decoded)) {
33+
return DEFAULT_REDIRECT;
34+
}
35+
36+
return $decoded;
37+
}
38+
39+
function append_hash(string $url): string {
2740
if (!empty($_POST['url_hash'])) {
28-
$redirectTo .= $_POST['url_hash'];
41+
return $url . preg_replace('/[^#a-zA-Z0-9_\-]/', '', $_POST['url_hash']);
2942
}
30-
header("Location: $redirectTo");
31-
$_SESSION["login"] = 1;
32-
exit;
43+
return $url;
3344
}
3445

35-
// Logout
36-
if (isset ($_GET["action"]) && $_GET["action"] == 'logout')
37-
{
38-
setcookie($CookieSaveLoginName, '', time()+1); // reset cookie
39-
$_SESSION["login"] = 0;
40-
header('Location: index.php');
41-
exit;
46+
function is_authenticated(): bool {
47+
return isset($_SESSION['login']) && $_SESSION['login'] === 1;
4248
}
4349

44-
// Password without Cookie check -> pass and set initial cookie
45-
if (isset ($_POST["loginpassword"]) && $nax_Password === hash('sha256',$_POST["loginpassword"]))
46-
{
47-
if (!empty($_POST['url_hash'])) {
48-
$redirectTo .= $_POST['url_hash'];
50+
function login_user(): void {
51+
$_SESSION['login'] = 1;
52+
session_regenerate_id(true);
53+
}
54+
55+
function logout_user(): void {
56+
$_SESSION = [];
57+
session_destroy();
58+
59+
setcookie(COOKIE_NAME,'',[
60+
'expires'=>time()-3600,
61+
'path'=>'/',
62+
'httponly'=>true,
63+
'samesite'=>'Strict'
64+
]);
65+
}
66+
67+
/* =====================================================
68+
Redirect Handling
69+
===================================================== */
70+
71+
$redirectTo = validate_local_path($_GET['next'] ?? null);
72+
73+
/* =====================================================
74+
Web Protection Disabled
75+
===================================================== */
76+
77+
if ($nax_WebProtection !== 'true') {
78+
login_user();
79+
safe_redirect(append_hash($redirectTo));
80+
}
81+
82+
/* =====================================================
83+
Logout
84+
===================================================== */
85+
86+
if (($_GET['action'] ?? '') === 'logout') {
87+
logout_user();
88+
safe_redirect('/index.php');
89+
}
90+
91+
/* =====================================================
92+
Login Attempt
93+
===================================================== */
94+
95+
if (!empty($_POST['loginpassword'])) {
96+
97+
$incomingHash = hash('sha256', $_POST['loginpassword']);
98+
99+
if (hash_equals($nax_Password, $incomingHash)) {
100+
101+
login_user();
102+
103+
if (!empty($_POST['PWRemember'])) {
104+
$token = bin2hex(random_bytes(32));
105+
106+
$_SESSION['remember_token'] = hash('sha256',$token);
107+
108+
setcookie(COOKIE_NAME,$token,[
109+
'expires'=>time()+604800,
110+
'path'=>'/',
111+
'secure'=>isset($_SERVER['HTTPS']),
112+
'httponly'=>true,
113+
'samesite'=>'Strict'
114+
]);
115+
}
116+
117+
safe_redirect(append_hash($redirectTo));
49118
}
50-
header("Location: $redirectTo");
51-
$_SESSION["login"] = 1;
52-
if (isset($_POST['PWRemember'])) {setcookie($CookieSaveLoginName, hash('sha256',$_POST["loginpassword"]), time()+604800);}
53-
exit;
54119
}
55120

56-
// active Session or valid cookie (cookie not extends)
57-
if (( isset ($_SESSION["login"]) && ($_SESSION["login"] == 1)) || (isset ($_COOKIE[$CookieSaveLoginName]) && $nax_Password === $_COOKIE[$CookieSaveLoginName]))
58-
{
59-
if (!empty($_POST['url_hash'])) {
60-
$redirectTo .= $_POST['url_hash'];
121+
/* =====================================================
122+
Remember Me Validation
123+
===================================================== */
124+
125+
if (!is_authenticated() && !empty($_COOKIE[COOKIE_NAME]) && !empty($_SESSION['remember_token'])) {
126+
127+
if (hash_equals($_SESSION['remember_token'], hash('sha256',$_COOKIE[COOKIE_NAME]))) {
128+
login_user();
129+
safe_redirect(append_hash($redirectTo));
61130
}
62-
header("Location: $redirectTo");
63-
$_SESSION["login"] = 1;
64-
if (isset($_POST['PWRemember'])) {setcookie($CookieSaveLoginName, hash('sha256',$_POST["loginpassword"]), time()+604800);}
65-
exit;
66131
}
67132

133+
/* =====================================================
134+
Already Logged In
135+
===================================================== */
136+
137+
if (is_authenticated()) {
138+
safe_redirect(append_hash($redirectTo));
139+
}
140+
141+
/* =====================================================
142+
Login UI Variables
143+
===================================================== */
144+
68145
$login_headline = lang('Login_Toggle_Info_headline');
69-
$login_info = lang('Login_Info');
70-
$login_mode = 'danger';
71-
$login_display_mode = 'display: block;';
72-
$login_icon = 'fa-info';
73-
74-
// no active session, cookie not checked
75-
if (isset ($_SESSION["login"]) == FALSE || $_SESSION["login"] != 1)
76-
{
77-
if ($nax_Password === '8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92')
78-
{
146+
$login_info = lang('Login_Info');
147+
$login_mode = 'info';
148+
$login_display_mode = 'display:none;';
149+
$login_icon = 'fa-info';
150+
151+
if ($nax_Password === '8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92') {
79152
$login_info = lang('Login_Default_PWD');
80153
$login_mode = 'danger';
81-
$login_display_mode = 'display: block;';
154+
$login_display_mode = 'display:block;';
82155
$login_headline = lang('Login_Toggle_Alert_headline');
83156
$login_icon = 'fa-ban';
84-
}
85-
else
86-
{
87-
$login_mode = 'info';
88-
$login_display_mode = 'display: none;';
89-
$login_headline = lang('Login_Toggle_Info_headline');
90-
$login_icon = 'fa-info';
91-
}
92157
}
93-
94-
// ##################################################
95-
// ## Login Processing end
96-
// ##################################################
97158
?>
98159

99160
<!DOCTYPE html>

0 commit comments

Comments
 (0)