adding functionalitiy to send login messages via telegram and password reset links via telegram/email
This commit is contained in:
@@ -17,6 +17,7 @@ if (!isset($_SESSION["logged_in"]) || $_SESSION["logged_in"] !== true) {
|
|||||||
<?php
|
<?php
|
||||||
include "../assets/components.php";
|
include "../assets/components.php";
|
||||||
?>
|
?>
|
||||||
|
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> <!-- Google Material Icons -->
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<!-- Main Container -->
|
<!-- Main Container -->
|
||||||
@@ -39,19 +40,22 @@ if (!isset($_SESSION["logged_in"]) || $_SESSION["logged_in"] !== true) {
|
|||||||
<!-- Tabs for General and Password sections -->
|
<!-- Tabs for General and Password sections -->
|
||||||
<ul class="nav nav-tabs" id="accountTab" role="tablist">
|
<ul class="nav nav-tabs" id="accountTab" role="tablist">
|
||||||
<li class="nav-item" role="presentation">
|
<li class="nav-item" role="presentation">
|
||||||
<a class="nav-link active" id="general-tab" data-bs-toggle="tab" href="#general" role="tab" aria-controls="general" aria-selected="true">General</a>
|
<a class="nav-link active" id="general-tab" data-bs-toggle="tab" href="#general" role="tab" aria-controls="general" aria-selected="true"><span class="material-icons">person</span></a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item" role="presentation">
|
<li class="nav-item" role="presentation">
|
||||||
<a class="nav-link" id="password-tab" data-bs-toggle="tab" href="#password" role="tab" aria-controls="password" aria-selected="false">Password</a>
|
<a class="nav-link" id="password-tab" data-bs-toggle="tab" href="#password" role="tab" aria-controls="password" aria-selected="false"><span class="material-icons">lock</span></a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item" role="presentation">
|
<li class="nav-item" role="presentation">
|
||||||
<a class="nav-link" id="2fa-tab" data-bs-toggle="tab" href="#2fa" role="tab" aria-controls="2fa" aria-selected="false">2fa</a>
|
<a class="nav-link" id="2fa-tab" data-bs-toggle="tab" href="#2fa" role="tab" aria-controls="2fa" aria-selected="false"><span class="material-icons">security</span></a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item" role="presentation">
|
<li class="nav-item" role="presentation">
|
||||||
<a class="nav-link" id="passkey-tab" data-bs-toggle="tab" href="#passkey" role="tab" aria-controls="passkey" aria-selected="false">Passkey</a>
|
<a class="nav-link" id="passkey-tab" data-bs-toggle="tab" href="#passkey" role="tab" aria-controls="passkey" aria-selected="false"><span class="material-icons">fingerprint</span></a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item" role="presentation">
|
<li class="nav-item" role="presentation">
|
||||||
<a class="nav-link" href="/login/logout.php" role="tab" aria-selected="false">Logout</a>
|
<a class="nav-link" id="message-tab" data-bs-toggle="tab" href="#message" role="tab" aria-controls="message" aria-selected="false"><span class="material-icons">message</span></a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item" role="presentation">
|
||||||
|
<a class="nav-link" href="/login/logout.php" role="tab" aria-selected="false"><span class="material-icons">logout</span></a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -79,6 +83,17 @@ if (!isset($_SESSION["logged_in"]) || $_SESSION["logged_in"] !== true) {
|
|||||||
<input type="text" class="form-control" id="telegram" placeholder="Set telegram id">
|
<input type="text" class="form-control" id="telegram" placeholder="Set telegram id">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="user_token" class="form-label">User token</label>
|
||||||
|
<input type="text" class="form-control" id="user_token" disabled>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="last_login" class="form-label">Last login</label>
|
||||||
|
<input type="text" class="form-control" id="last_login" disabled>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Save Changes Button -->
|
<!-- Save Changes Button -->
|
||||||
<button type="button" id="save-button" class="btn btn-success">Save Changes</button>
|
<button type="button" id="save-button" class="btn btn-success">Save Changes</button>
|
||||||
</form>
|
</form>
|
||||||
@@ -119,15 +134,16 @@ if (!isset($_SESSION["logged_in"]) || $_SESSION["logged_in"] !== true) {
|
|||||||
</div>
|
</div>
|
||||||
<div class="tab-pane fade" id="passkey" role="tabpanel" aria-labelledby="passkey-tab">
|
<div class="tab-pane fade" id="passkey" role="tabpanel" aria-labelledby="passkey-tab">
|
||||||
<p>Using a passkey you can login with e.g. your fingerprint. If this is enabled you can still login using your password but using a passkey is faster.</p>
|
<p>Using a passkey you can login with e.g. your fingerprint. If this is enabled you can still login using your password but using a passkey is faster.</p>
|
||||||
<!--
|
|
||||||
<div class="form-check form-switch">
|
|
||||||
<input class="form-check-input" type="checkbox" id="passkey-switch">
|
|
||||||
<label class="form-check-label" for="passkey-switch">Enable passkey</label>
|
|
||||||
</div>
|
|
||||||
-->
|
|
||||||
<br>
|
<br>
|
||||||
<button id="create-passkey" class="btn btn-primary" onclick="createRegistration()">Register passkey</button>
|
<button id="create-passkey" class="btn btn-primary" onclick="createRegistration()">Register passkey</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="tab-pane fade" id="message" role="tabpanel" aria-labelledby="message-tab">
|
||||||
|
<p>You can get a message via telegram whenever somebody logs in to your account</p>
|
||||||
|
<div class="form-check form-switch">
|
||||||
|
<input class="form-check-input" type="checkbox" id="message-switch">
|
||||||
|
<label class="form-check-label" for="message-switch">Enable login messages</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -188,9 +204,12 @@ if (!isset($_SESSION["logged_in"]) || $_SESSION["logged_in"] !== true) {
|
|||||||
|
|
||||||
// Fill input fields
|
// Fill input fields
|
||||||
document.getElementById('name').value = user.name;
|
document.getElementById('name').value = user.name;
|
||||||
|
document.getElementById('user_token').value = user.user_token;
|
||||||
document.getElementById('email').value = user.email;
|
document.getElementById('email').value = user.email;
|
||||||
document.getElementById('telegram').value = user.telegram_id;
|
document.getElementById('telegram').value = user.telegram_id;
|
||||||
document.getElementById('twofa-switch').checked = user.twofa_enabled;
|
document.getElementById('twofa-switch').checked = user.twofa_enabled;
|
||||||
|
document.getElementById('message-switch').checked = user.login_message;
|
||||||
|
document.getElementById('last_login').value = user.last_login;
|
||||||
|
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
@@ -316,6 +335,43 @@ if (!isset($_SESSION["logged_in"]) || $_SESSION["logged_in"] !== true) {
|
|||||||
showErrorModal('Failed to send request. Please try again later.');
|
showErrorModal('Failed to send request. Please try again later.');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const switchElement2 = document.getElementById('message-switch');
|
||||||
|
|
||||||
|
// Add an event listener for when the switch is changed
|
||||||
|
switchElement2.addEventListener('change', async function () {
|
||||||
|
// Get the current state of the switch
|
||||||
|
const isEnabled = switchElement2.checked;
|
||||||
|
if(document.getElementById('telegram').value.length!=0){
|
||||||
|
try {
|
||||||
|
// Send the state to the backend using a POST request
|
||||||
|
const response = await fetch('/api/account/update_message.php', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
enable_message: isEnabled, // Send the new state of 2FA
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check if the response is successful
|
||||||
|
const result = await response.json();
|
||||||
|
if (response.ok) {
|
||||||
|
// Handle success
|
||||||
|
showSuccessModal(result.message || (isEnabled ? 'Login messages enabled successfully.' : 'Login messages disabled successfully.'));
|
||||||
|
} else {
|
||||||
|
// Handle error
|
||||||
|
showErrorModal('Error: ' + (result.message || 'An error occurred while updating login messages.'));
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error:', error);
|
||||||
|
showErrorModal('Failed to send request. Please try again later.');
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
showErrorModal("Please configure your Telegram ID first.");
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Function to show error modal
|
// Function to show error modal
|
||||||
|
|||||||
@@ -15,16 +15,18 @@ include "../../config/config.php";
|
|||||||
$conn = new mysqli($DB_SERVERNAME, $DB_USERNAME, $DB_PASSWORD, $DB_DATABASE);
|
$conn = new mysqli($DB_SERVERNAME, $DB_USERNAME, $DB_PASSWORD, $DB_DATABASE);
|
||||||
|
|
||||||
$username=$_SESSION["username"];
|
$username=$_SESSION["username"];
|
||||||
$sql="SELECT id, email, telegram_id, auth_method_enabled_2fa FROM users WHERE username = ?";
|
$sql="SELECT id, email, telegram_id, auth_method_enabled_2fa, user_token, login_message FROM users WHERE username = ?";
|
||||||
$id=0;
|
$id=0;
|
||||||
$email="";
|
$email="";
|
||||||
$telegram_id="";
|
$telegram_id="";
|
||||||
$twofa_enabled="";
|
$twofa_enabled="";
|
||||||
|
$user_token="";
|
||||||
|
$login_message=0;
|
||||||
$stmt = mysqli_prepare($conn, $sql);
|
$stmt = mysqli_prepare($conn, $sql);
|
||||||
mysqli_stmt_bind_param($stmt, 's', $username);
|
mysqli_stmt_bind_param($stmt, 's', $username);
|
||||||
mysqli_stmt_execute($stmt);
|
mysqli_stmt_execute($stmt);
|
||||||
mysqli_stmt_store_result($stmt);
|
mysqli_stmt_store_result($stmt);
|
||||||
mysqli_stmt_bind_result($stmt, $id,$email,$telegram_id,$twofa_enabled);
|
mysqli_stmt_bind_result($stmt, $id,$email,$telegram_id,$twofa_enabled,$user_token,$login_message);
|
||||||
mysqli_stmt_fetch($stmt);
|
mysqli_stmt_fetch($stmt);
|
||||||
|
|
||||||
$_SESSION["id"]=$id;
|
$_SESSION["id"]=$id;
|
||||||
@@ -33,7 +35,10 @@ $user_data = [
|
|||||||
"name" => $username,
|
"name" => $username,
|
||||||
"email" => $email,
|
"email" => $email,
|
||||||
"telegram_id" => $telegram_id,
|
"telegram_id" => $telegram_id,
|
||||||
"twofa_enabled" => $twofa_enabled
|
"twofa_enabled" => $twofa_enabled,
|
||||||
|
"user_token"=>$user_token,
|
||||||
|
"last_login"=>$_SESSION["last_login"],
|
||||||
|
"login_message"=>$login_message
|
||||||
];
|
];
|
||||||
|
|
||||||
// Send JSON response
|
// Send JSON response
|
||||||
|
|||||||
67
app-code/api/account/update_message.php
Normal file
67
app-code/api/account/update_message.php
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
|
||||||
|
// Check if the user is logged in
|
||||||
|
if (!isset($_SESSION["logged_in"]) || $_SESSION["logged_in"] !== true) {
|
||||||
|
echo json_encode([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'Not logged in'
|
||||||
|
]);
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Include database configuration
|
||||||
|
include "../../config/config.php";
|
||||||
|
|
||||||
|
// Create a new database connection
|
||||||
|
$conn = new mysqli($DB_SERVERNAME, $DB_USERNAME, $DB_PASSWORD, $DB_DATABASE);
|
||||||
|
|
||||||
|
// Check for database connection errors
|
||||||
|
if ($conn->connect_error) {
|
||||||
|
echo json_encode([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'Database connection failed: ' . $conn->connect_error
|
||||||
|
]);
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the logged-in user's ID and username from the session
|
||||||
|
$id = $_SESSION["id"];
|
||||||
|
$username = $_SESSION["username"];
|
||||||
|
|
||||||
|
// Get the raw POST data (JSON)
|
||||||
|
$data = json_decode(file_get_contents("php://input"));
|
||||||
|
if($data->enable_message==true){
|
||||||
|
$sql="UPDATE users SET login_message=1 WHERE id = ?";
|
||||||
|
if ($update_stmt = $conn->prepare($sql)) {
|
||||||
|
$update_stmt->bind_param("i", $id);
|
||||||
|
if ($update_stmt->execute()) {
|
||||||
|
echo json_encode(['success' => true, 'message' => 'Login messages enabled.']);
|
||||||
|
} else {
|
||||||
|
echo json_encode(['success' => false, 'message' => 'Failed to enable login messages.']);
|
||||||
|
}
|
||||||
|
$update_stmt->close();
|
||||||
|
} else {
|
||||||
|
echo json_encode(['success' => false, 'message' => 'Database error.']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($data->enable_message==false){
|
||||||
|
//create 2fa secret key
|
||||||
|
$sql="UPDATE users SET login_message=0 WHERE id = ?";
|
||||||
|
if ($update_stmt = $conn->prepare($sql)) {
|
||||||
|
$update_stmt->bind_param("i",$id);
|
||||||
|
if ($update_stmt->execute()) {
|
||||||
|
echo json_encode(['success' => true, 'message' => 'Login messages disabled.']);
|
||||||
|
} else {
|
||||||
|
echo json_encode(['success' => false, 'message' => 'Failed to disable login messages.']);
|
||||||
|
}
|
||||||
|
$update_stmt->close();
|
||||||
|
} else {
|
||||||
|
echo json_encode(['success' => false, 'message' => 'Database error.']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
@@ -1,6 +1,33 @@
|
|||||||
<?php
|
<?php
|
||||||
session_start();
|
session_start();
|
||||||
header('Content-Type: application/json');
|
header('Content-Type: application/json');
|
||||||
|
|
||||||
|
|
||||||
|
function get_location_from_ip($ip) {
|
||||||
|
// Use ip-api.com to fetch geolocation data
|
||||||
|
$url = "http://ip-api.com/json/$ip";
|
||||||
|
|
||||||
|
// Initialize curl
|
||||||
|
$ch = curl_init();
|
||||||
|
curl_setopt($ch, CURLOPT_URL, $url);
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
|
|
||||||
|
// Execute curl and decode the JSON response
|
||||||
|
$response = curl_exec($ch);
|
||||||
|
curl_close($ch);
|
||||||
|
|
||||||
|
// Convert JSON response to PHP array
|
||||||
|
$data = json_decode($response, true);
|
||||||
|
|
||||||
|
// Check for a successful response
|
||||||
|
if ($data && $data['status'] === 'success') {
|
||||||
|
return $data; // Return the geolocation data
|
||||||
|
}
|
||||||
|
|
||||||
|
return null; // Return null if API call fails
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$send_to=$_SESSION["end_url"];
|
$send_to=$_SESSION["end_url"];
|
||||||
|
|
||||||
include "../../config/config.php";
|
include "../../config/config.php";
|
||||||
@@ -32,7 +59,6 @@ else if($_SESSION["needs_auth"]===false && $_SESSION["mfa_required"]==1 && $_SES
|
|||||||
echo(json_encode($data));
|
echo(json_encode($data));
|
||||||
}*/else if ($_SESSION["needs_auth"]===false && $_SESSION["mfa_authenticated"]==1 && $_SESSION["pw_authenticated"]==1){
|
}*/else if ($_SESSION["needs_auth"]===false && $_SESSION["mfa_authenticated"]==1 && $_SESSION["pw_authenticated"]==1){
|
||||||
//fully authenticated
|
//fully authenticated
|
||||||
$_SESSION["logged_in"]=true;
|
|
||||||
//create auth token which other services can then use to check if user logged in
|
//create auth token which other services can then use to check if user logged in
|
||||||
$user_id=$_SESSION["id"];
|
$user_id=$_SESSION["id"];
|
||||||
$auth_token=bin2hex(random_bytes(128));
|
$auth_token=bin2hex(random_bytes(128));
|
||||||
@@ -49,9 +75,56 @@ else if($_SESSION["needs_auth"]===false && $_SESSION["mfa_required"]==1 && $_SES
|
|||||||
}else{
|
}else{
|
||||||
$data=[
|
$data=[
|
||||||
'message' => 'done',
|
'message' => 'done',
|
||||||
'redirect' => ''
|
'redirect' => '/account/'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
//update last login
|
||||||
|
$ip=$_SERVER["REMOTE_ADDR"];
|
||||||
|
$date=date('Y-m-d H:i:s');
|
||||||
|
$last_login_msg=$date." from ".$ip;
|
||||||
|
$sql="UPDATE users SET last_login = ? WHERE id = ?";
|
||||||
|
$stmt = mysqli_prepare($conn, $sql);
|
||||||
|
mysqli_stmt_bind_param($stmt, 'si', $last_login_msg,$user_id);
|
||||||
|
mysqli_stmt_execute($stmt);
|
||||||
|
mysqli_stmt_close($stmt);
|
||||||
|
//send login message
|
||||||
|
if($_SESSION["login_message"] && $_SESSION["logged_in"]!==true){
|
||||||
|
$device = $_SERVER['HTTP_USER_AGENT'];
|
||||||
|
$location=get_location_from_ip($ip);
|
||||||
|
$message = "⚠️ *Login Warning*\n\n"
|
||||||
|
. "We noticed a login attempt with your account.\n\n"
|
||||||
|
. "*Date&Time*: $date\n"
|
||||||
|
. "*Device&Browser*: $device\n"
|
||||||
|
. "*Location*: ".$location["country"].", ".$location["state"].", ".$location["city"]."\n"
|
||||||
|
. "*Account*: ".$_SESSION["username"]."\n"
|
||||||
|
. "*IP*: $ip\n\n"
|
||||||
|
. "If this was you, you can ignore this message. If not, please secure your account immediately.";
|
||||||
|
|
||||||
|
// Telegram API URL
|
||||||
|
$url = "https://api.telegram.org/$TELEGRAM_BOT_API/sendMessage";
|
||||||
|
|
||||||
|
// Data to be sent in the POST request
|
||||||
|
$telegram_id=$_SESSION["telegram_id"];
|
||||||
|
$message_data = [
|
||||||
|
'chat_id' => $telegram_id,
|
||||||
|
'text' => $message,
|
||||||
|
'parse_mode' => 'Markdown', // Use Markdown for formatting
|
||||||
|
];
|
||||||
|
|
||||||
|
// Use cURL to send the request
|
||||||
|
$ch = curl_init();
|
||||||
|
|
||||||
|
// Construct the GET request URL
|
||||||
|
$query_string = http_build_query($message_data); // Converts the array to URL-encoded query string
|
||||||
|
$get_url = $url . '?' . $query_string; // Append query string to the base URL
|
||||||
|
curl_setopt($ch, CURLOPT_URL, $get_url);
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Still retrieve the response if needed
|
||||||
|
curl_exec($ch);
|
||||||
|
curl_close($ch);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$_SESSION["logged_in"]=true;
|
||||||
echo(json_encode($data));
|
echo(json_encode($data));
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
@@ -60,7 +133,7 @@ else{
|
|||||||
$username=$_SESSION["username"];
|
$username=$_SESSION["username"];
|
||||||
$_SESSION["needs_auth"]=false;
|
$_SESSION["needs_auth"]=false;
|
||||||
$_SESSION["logged_in"]=false;
|
$_SESSION["logged_in"]=false;
|
||||||
$sql="SELECT auth_method_required_pw, auth_method_required_2fa, auth_method_required_passkey, id, user_token FROM users WHERE username = ?";
|
$sql="SELECT auth_method_required_pw, auth_method_required_2fa, auth_method_required_passkey, id, user_token,last_login, login_message,telegram_id FROM users WHERE username = ?";
|
||||||
$stmt = mysqli_prepare($conn, $sql);
|
$stmt = mysqli_prepare($conn, $sql);
|
||||||
mysqli_stmt_bind_param($stmt, 's', $username);
|
mysqli_stmt_bind_param($stmt, 's', $username);
|
||||||
mysqli_stmt_execute($stmt);
|
mysqli_stmt_execute($stmt);
|
||||||
@@ -69,8 +142,11 @@ else{
|
|||||||
$mfa=0;
|
$mfa=0;
|
||||||
$passkey=0;
|
$passkey=0;
|
||||||
$user_token="";
|
$user_token="";
|
||||||
|
$last_login="";
|
||||||
|
$login_message=0;
|
||||||
|
$telegram_id="";
|
||||||
if(mysqli_stmt_num_rows($stmt) == 1){
|
if(mysqli_stmt_num_rows($stmt) == 1){
|
||||||
mysqli_stmt_bind_result($stmt, $pw,$mfa,$passkey,$user_id,$user_token);
|
mysqli_stmt_bind_result($stmt, $pw,$mfa,$passkey,$user_id,$user_token,$last_login,$login_message,$telegram_id);
|
||||||
mysqli_stmt_fetch($stmt);
|
mysqli_stmt_fetch($stmt);
|
||||||
$_SESSION["pw_required"] = $pw;
|
$_SESSION["pw_required"] = $pw;
|
||||||
$_SESSION["pw_authenticated"] = ($pw == 0) ? 1 : 0; // If $pw is 0, set pw_authenticated to 1
|
$_SESSION["pw_authenticated"] = ($pw == 0) ? 1 : 0; // If $pw is 0, set pw_authenticated to 1
|
||||||
@@ -80,6 +156,9 @@ else{
|
|||||||
$_SESSION["passkey_authenticated"] = ($passkey == 0) ? 1 : 0;
|
$_SESSION["passkey_authenticated"] = ($passkey == 0) ? 1 : 0;
|
||||||
$_SESSION["id"]=$user_id;
|
$_SESSION["id"]=$user_id;
|
||||||
$_SESSION["user_token"]=$user_token;
|
$_SESSION["user_token"]=$user_token;
|
||||||
|
$_SESSION["last_login"]=$last_login;
|
||||||
|
$_SESSION["telegram_id"]=$telegram_id;
|
||||||
|
$_SESSION["login_message"]=$login_message;
|
||||||
$data=[
|
$data=[
|
||||||
'message' => 'prepared_start_auth',
|
'message' => 'prepared_start_auth',
|
||||||
'redirect' => '/login/'
|
'redirect' => '/login/'
|
||||||
|
|||||||
70
app-code/api/login/reset_pw.php
Normal file
70
app-code/api/login/reset_pw.php
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
<?php
|
||||||
|
// Check if the POST request contains 'token' and 'password'
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
if (!isset($_POST['token']) || !isset($_POST['password']) || !isset($_POST['confirm_password'])) {
|
||||||
|
echo json_encode(['status' => 'error', 'message' => 'Missing required fields.']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
include "../../config/config.php";
|
||||||
|
|
||||||
|
// Create a new database connection
|
||||||
|
$conn = new mysqli($DB_SERVERNAME, $DB_USERNAME, $DB_PASSWORD, $DB_DATABASE);
|
||||||
|
|
||||||
|
$token = $_POST['token'];
|
||||||
|
$user_id="";
|
||||||
|
$valid_until=0;
|
||||||
|
$password = $_POST['password'];
|
||||||
|
$confirmPassword = $_POST['confirm_password'];
|
||||||
|
$sql="SELECT user_id, valid_until FROM reset_tokens WHERE auth_token=?;";
|
||||||
|
$stmt = mysqli_prepare($conn, $sql);
|
||||||
|
mysqli_stmt_bind_param($stmt, 's', $token);
|
||||||
|
mysqli_stmt_execute($stmt);
|
||||||
|
mysqli_stmt_store_result($stmt);
|
||||||
|
mysqli_stmt_bind_result($stmt, $user_id,$valid_until);
|
||||||
|
mysqli_stmt_fetch($stmt);
|
||||||
|
if(mysqli_stmt_num_rows($stmt) > 0 && time()<$valid_until){
|
||||||
|
mysqli_stmt_close($stmt);
|
||||||
|
// Check if passwords match
|
||||||
|
if ($password !== $confirmPassword) {
|
||||||
|
echo json_encode(['status' => 'error', 'message' => 'Passwords do not match.']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
if (strlen($password)<12) {
|
||||||
|
echo json_encode(['status' => 'error', 'message' => 'Password must be at least 12 characters.']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$new_pepper=bin2hex(random_bytes(32));
|
||||||
|
// Hash the password / a salt is added automaticly
|
||||||
|
$hashed_password = password_hash($password.$new_pepper, PASSWORD_BCRYPT);
|
||||||
|
|
||||||
|
// Update the password in the database
|
||||||
|
$update_sql = "UPDATE users SET password = ?, pepper = ? WHERE id = ?";
|
||||||
|
if ($update_stmt = $conn->prepare($update_sql)) {
|
||||||
|
$update_stmt->bind_param("ssi", $hashed_password, $new_pepper, $user_id);
|
||||||
|
if ($update_stmt->execute()) {
|
||||||
|
echo json_encode(['status' => 'success','success' => true, 'message' => 'Password updated successfully.']);
|
||||||
|
} else {
|
||||||
|
echo json_encode(['success' => false, 'message' => 'Failed to update password.']);
|
||||||
|
}
|
||||||
|
$update_stmt->close();
|
||||||
|
} else {
|
||||||
|
echo json_encode(['success' => false, 'message' => 'Database error.']);
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
mysqli_stmt_close($stmt);
|
||||||
|
echo json_encode(['success' => false, 'message' => 'Ivalid auth token']);
|
||||||
|
}
|
||||||
|
//remove token
|
||||||
|
$sql="DELETE FROM reset_tokens WHERE auth_token = ?;";
|
||||||
|
$stmt = mysqli_prepare($conn, $sql);
|
||||||
|
mysqli_stmt_bind_param($stmt, 's', $token);
|
||||||
|
mysqli_stmt_execute($stmt);
|
||||||
|
mysqli_stmt_close($stmt);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// If it's not a POST request, show error
|
||||||
|
echo json_encode(['status' => 'error', 'message' => 'Invalid request method.']);
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
192
app-code/api/login/send_reset_link.php
Normal file
192
app-code/api/login/send_reset_link.php
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
include "../../config/config.php";
|
||||||
|
$username=$_SESSION["username"];
|
||||||
|
$sql="SELECT id, email, telegram_id FROM users WHERE username = ?;";
|
||||||
|
$conn = new mysqli($DB_SERVERNAME, $DB_USERNAME, $DB_PASSWORD, $DB_DATABASE);
|
||||||
|
$mail="";
|
||||||
|
$id="";
|
||||||
|
$telegram_id="";
|
||||||
|
$stmt = mysqli_prepare($conn, $sql);
|
||||||
|
mysqli_stmt_bind_param($stmt, 's', $username);
|
||||||
|
mysqli_stmt_execute($stmt);
|
||||||
|
mysqli_stmt_store_result($stmt);
|
||||||
|
mysqli_stmt_bind_result($stmt,$id, $mail,$telegram_id);
|
||||||
|
mysqli_stmt_fetch($stmt);
|
||||||
|
mysqli_stmt_close($stmt);
|
||||||
|
//send telegram message
|
||||||
|
$device = $_SERVER['HTTP_USER_AGENT'];
|
||||||
|
$ip=$_SERVER["REMOTE_ADDR"];
|
||||||
|
$date=date('Y-m-d H:i:s');
|
||||||
|
$token=bin2hex(random_bytes(128));
|
||||||
|
$link="https://jakach.duckdns.org:444/login/reset_pw.php?token=$token";
|
||||||
|
|
||||||
|
$message = "*Password reset token*\n\n"
|
||||||
|
. "You have requested the reset of your password here is your reset link.\n\n"
|
||||||
|
. "*Link*: [click here]($link)\n\n"
|
||||||
|
. "*Details of this request:*\n"
|
||||||
|
. "• *Date&Time*: $date\n"
|
||||||
|
. "• *Device&Browser*: $device\n"
|
||||||
|
. "• *Account*: ".$_SESSION["username"]."\n"
|
||||||
|
. "• *IP*: $ip\n\n"
|
||||||
|
."If this was you, you can reset your password. If this was not you somebody else tried to reset your password!\n"
|
||||||
|
. "*Thank you for using Jakach login!*";
|
||||||
|
|
||||||
|
// Telegram API URL
|
||||||
|
$url = "https://api.telegram.org/$TELEGRAM_BOT_API/sendMessage";
|
||||||
|
|
||||||
|
$message_data = [
|
||||||
|
'chat_id' => $telegram_id,
|
||||||
|
'text' => $message,
|
||||||
|
'parse_mode' => 'Markdown', // Use Markdown for formatting
|
||||||
|
];
|
||||||
|
|
||||||
|
// Use cURL to send the request
|
||||||
|
$ch = curl_init();
|
||||||
|
|
||||||
|
// Construct the GET request URL
|
||||||
|
$query_string = http_build_query($message_data); // Converts the array to URL-encoded query string
|
||||||
|
$get_url = $url . '?' . $query_string; // Append query string to the base URL
|
||||||
|
curl_setopt($ch, CURLOPT_URL, $get_url);
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Still retrieve the response if needed
|
||||||
|
curl_exec($ch);
|
||||||
|
curl_close($ch);
|
||||||
|
//send mail
|
||||||
|
if(!empty($mail)){
|
||||||
|
$content = "
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang='en'>
|
||||||
|
<head>
|
||||||
|
<meta charset='UTF-8'>
|
||||||
|
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
|
||||||
|
<title>Password Reset</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
background-color: #f4f4f4;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.email-container {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 0 auto;
|
||||||
|
background-color: #ffffff;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
color: #333;
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
color: #666;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color: #ffffff;
|
||||||
|
background-color: #007bff;
|
||||||
|
padding: 12px 20px;
|
||||||
|
text-decoration: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
font-weight: bold;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
a:hover {
|
||||||
|
background-color: #0056b3;
|
||||||
|
}
|
||||||
|
.footer {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #888;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
.footer a {
|
||||||
|
color: #888;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class='email-container'>
|
||||||
|
<h1>Password Reset Request</h1>
|
||||||
|
<p>Hi $mail,</p>
|
||||||
|
<p>You have requested a password reset link. Here it is:</p>
|
||||||
|
<p><a href='$link'>Click here to reset your password</a></p>
|
||||||
|
<p>If you did not request this, please ignore this email. If you did, you can reset your password using the link above.</p>
|
||||||
|
|
||||||
|
<p><strong>Request Details:</strong></p>
|
||||||
|
<ul>
|
||||||
|
<li><strong>Date & Time:</strong> $date</li>
|
||||||
|
<li><strong>Device & Browser:</strong> $device</li>
|
||||||
|
<li><strong>Account:</strong> $mail</li>
|
||||||
|
<li><strong>IP Address:</strong> $ip</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>If this was you, you can reset your password. If this was not you, someone else may have tried to reset your password.</p>
|
||||||
|
|
||||||
|
<div class='footer'>
|
||||||
|
<p>Thanks for using our service!</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
";
|
||||||
|
|
||||||
|
|
||||||
|
$message = [
|
||||||
|
"personalizations" => [
|
||||||
|
[
|
||||||
|
"to" => [
|
||||||
|
[
|
||||||
|
"email" => $mail
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"from" => [
|
||||||
|
"email" => $SENDGRID_MAIL
|
||||||
|
],
|
||||||
|
"subject" => "Jakach login password reset",
|
||||||
|
"content" => [
|
||||||
|
[
|
||||||
|
"type" => "text/html",
|
||||||
|
"value" => $content
|
||||||
|
]
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
$url = "https://api.sendgrid.com/v3/mail/send";
|
||||||
|
|
||||||
|
// Initialize cURL
|
||||||
|
$ch = curl_init($url);
|
||||||
|
|
||||||
|
// Set cURL options
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
|
curl_setopt($ch, CURLOPT_POST, true);
|
||||||
|
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||||
|
"Authorization: Bearer $SENDGRID_KEY",
|
||||||
|
"Content-Type: application/json"
|
||||||
|
]);
|
||||||
|
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($message));
|
||||||
|
|
||||||
|
// Execute the cURL request
|
||||||
|
curl_exec($ch);
|
||||||
|
curl_close($ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//insert the token into our db
|
||||||
|
$valid_until=time()+8600;
|
||||||
|
$sql="INSERT INTO reset_tokens (auth_token, user_id,valid_until) VALUES (?,?,?);";
|
||||||
|
$stmt = mysqli_prepare($conn, $sql);
|
||||||
|
mysqli_stmt_bind_param($stmt, 'sii', $token,$id,$valid_until);
|
||||||
|
mysqli_stmt_execute($stmt);
|
||||||
|
mysqli_stmt_close($stmt);
|
||||||
|
|
||||||
|
?>
|
||||||
BIN
app-code/assets/image.png
Normal file
BIN
app-code/assets/image.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 297 KiB |
BIN
app-code/favicon.ico
Normal file
BIN
app-code/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
@@ -62,6 +62,8 @@
|
|||||||
username VARCHAR(255) NOT NULL UNIQUE,
|
username VARCHAR(255) NOT NULL UNIQUE,
|
||||||
public_key TEXT DEFAULT '',
|
public_key TEXT DEFAULT '',
|
||||||
credential_id VARBINARY(255),
|
credential_id VARBINARY(255),
|
||||||
|
last_login VARCHAR(255),
|
||||||
|
login_message INT,
|
||||||
user_token VARCHAR(128),
|
user_token VARCHAR(128),
|
||||||
counter INT DEFAULT 0,
|
counter INT DEFAULT 0,
|
||||||
2fa VARCHAR(255),
|
2fa VARCHAR(255),
|
||||||
@@ -114,6 +116,25 @@
|
|||||||
</div>';
|
</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$sql="CREATE TABLE IF NOT EXISTS reset_tokens (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
auth_token VARCHAR(256),
|
||||||
|
user_id INT,
|
||||||
|
valid_until INT
|
||||||
|
);";
|
||||||
|
|
||||||
|
|
||||||
|
if ($conn->query($sql) === TRUE) {
|
||||||
|
echo '<br><div class="alert alert-success" role="alert">
|
||||||
|
Table reset_tokens created successfully!
|
||||||
|
</div>';
|
||||||
|
} else {
|
||||||
|
$success=0;
|
||||||
|
echo '<br><div class="alert alert-danger" role="alert">
|
||||||
|
Error creating reset_tokens users: ' . $conn->error .'
|
||||||
|
</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if($success!==1){
|
if($success!==1){
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
echo('<a class="btn btn-primary btn-lg" href="/login/passkey.php">Use passkey instead</a>');
|
echo('<a class="btn btn-primary btn-lg" href="/login/passkey.php">Use passkey instead</a>');
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
<center><a href="#" onclick="reset_pw();">Forgott password</a></center>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@@ -57,7 +58,31 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="modal fade" id="resetModal" tabindex="-1" aria-labelledby="resetModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="errorModalLabel">Password reset</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
If you have a Telegram Id or an email address linked to your account, we have sent you a reset link.
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
//pw reset:
|
||||||
|
function reset_pw(){
|
||||||
|
fetch("/api/login/send_reset_link.php");
|
||||||
|
var resetModal = new bootstrap.Modal(document.getElementById('resetModal'));
|
||||||
|
resetModal.show();
|
||||||
|
}
|
||||||
|
|
||||||
// Select the form
|
// Select the form
|
||||||
const passwordForm = document.getElementById('passwordForm');
|
const passwordForm = document.getElementById('passwordForm');
|
||||||
|
|
||||||
|
|||||||
82
app-code/login/reset_pw.php
Normal file
82
app-code/login/reset_pw.php
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" data-bs-theme="dark">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Password Reset</title>
|
||||||
|
<?php
|
||||||
|
include "../assets/components.php";
|
||||||
|
?>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="container mt-5">
|
||||||
|
<h2>Password Reset</h2>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
// Check if the 'token' GET parameter is present
|
||||||
|
if (!isset($_GET['token'])) {
|
||||||
|
echo '<div class="alert alert-danger" role="alert">Invalid or missing token!</div>';
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
$token = $_GET['token'];
|
||||||
|
?>
|
||||||
|
|
||||||
|
<form id="resetForm">
|
||||||
|
<input type="hidden" name="token" value="<?= htmlspecialchars($token) ?>">
|
||||||
|
|
||||||
|
<!-- New Password -->
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="password">New Password</label>
|
||||||
|
<input type="password" class="form-control" id="password" name="password" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Confirm Password -->
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="confirm_password">Confirm Password</label>
|
||||||
|
<input type="password" class="form-control" id="confirm_password" name="confirm_password" required>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<button type="submit" class="btn btn-primary">Reset Password</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div id="responseMessage" class="mt-3"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.getElementById("resetForm").addEventListener("submit", async function(event) {
|
||||||
|
event.preventDefault(); // Prevent the form from submitting the traditional way
|
||||||
|
|
||||||
|
// Get form data
|
||||||
|
const formData = new FormData(this);
|
||||||
|
|
||||||
|
// Send data to the backend using fetch API
|
||||||
|
try {
|
||||||
|
const response = await fetch('/api/login/reset_pw.php', {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle response
|
||||||
|
const result = await response.json();
|
||||||
|
|
||||||
|
const responseMessage = document.getElementById("responseMessage");
|
||||||
|
if (response.ok && result.status === "success") {
|
||||||
|
responseMessage.innerHTML = `<div class="alert alert-success" role="alert">${result.message}</div>`;
|
||||||
|
} else {
|
||||||
|
responseMessage.innerHTML = `<div class="alert alert-danger" role="alert">${result.message}</div>`;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// Handle any network errors
|
||||||
|
const responseMessage = document.getElementById("responseMessage");
|
||||||
|
responseMessage.innerHTML = `<div class="alert alert-danger" role="alert">There was an error processing your request. Please try again later.</div>`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
|
||||||
@@ -22,6 +22,7 @@ services:
|
|||||||
ipv4_address: 192.168.5.3
|
ipv4_address: 192.168.5.3
|
||||||
ports:
|
ports:
|
||||||
- "444:443"
|
- "444:443"
|
||||||
|
- "80:443"
|
||||||
depends_on:
|
depends_on:
|
||||||
- jakach-login-db
|
- jakach-login-db
|
||||||
volumes:
|
volumes:
|
||||||
|
|||||||
Reference in New Issue
Block a user