I am trying to build an authentication system into my php website. I have no experiences with it so I go by documentation. No Frameworks or anything. Just plain vanilla PHP with a XAMPP Tech Stack on Windows.
- I check on my index.php at the beginning if the Session is already running. If not, create one with a dedicated Session Name, since I have several web services on my Apache and they shouldnt interfere with eachother.
- Then start the session if none is there.
- Check if $_SESSION[“loggedin” => true]. If yes, give me the content of the website. If not, display a login window
- After authentication in the login window, the website should redirect to the index.php, so the initialized $_SESSION will be validated again where $_SESSION[‘loggedin’ => true] and the content will be visible.
1. Problem: index.php
At any time when the index.php is checking the session, the session is not existent. And if php initializes it, it is filled like that $_SESSION[“loggedin” => false];. After the authentication it is supposed to be true. And before authentication $_SESSION[“loggedin”] it shouldnt be set at all since this step is only performed a few lines below.
2. Problem: The Controller post_login.php
After I start the session, the session is already authenticated with $_SESSION[“logged => true, “user” => “KENNUNG”];
How is it possible that index.php and post_login.php are handling different sessions? Or at least different session states?
The code is as follows:
/index.php
<?php
include_once("Config/settings.php"); //Some config values like $appName
if(!isset($_SESSION)) {
session_name($appName);
session_start([
'cookie_lifetime' => 86400,
//'cookie_domain' => $actual_link,
'gc_maxlifetime' => 86400,
'use_cookies' => 1,
'use_only_cookies' => 1
]);
}
// $_SESSION is already $_SESSION['loggedin' => false] at this point (?)
error_reporting(E_ALL);
ini_set('error_reporting', E_ALL);
ini_set('display_errors', 1);
$ROOT = __DIR__;
$content = "";
if (isset($_SESSION["loggedin"]) && $_SESSION["loggedin"] == 1) {
$content = $ROOT . "/View/Authentication/content.php";
} else {
$_SESSION["loggedin"] = false;
$_REQUEST = array();
$content = $ROOT . "/View/Authentication/login.php";
}
?>
<!doctype html>
<html lang="de">
<head>
<title><?php $appName ?></title>
<base href="" />
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="Assets/lib/jquery-3.7.0.min.js"></script>
<script src="https://code.jquery.com/ui/1.13.2/jquery-ui.js"></script>
<link rel="icon" type="image/x-icon" href="favicon.png">
<link rel="stylesheet" href="index.css">
<link rel="stylesheet" href="//code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css">
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
<script src="index.js"></script>
</head>
<body>
<div class="nav-bar" id="nav-bar">
<?php include($ROOT . "/View/Nav/nav.php"); ?>
</div>
<?php require($content); ?>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>
</body>
</html>
/View/Authentication/login.php
<?php
include_once(__DIR__ . "/../../Config/settings.php");
if (!isset($_SESSION)) {
session_name($appName);
session_start();
}
?>
<script src="View/Authentication/login.js" type="module"></script>
<style>
@import url("./View/Authentication/login.css") screen;
</style>
<!-- Modal -->
<div class="modal fade" id="LoginModal" tabindex="-1" aria-labelledby="LoginModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="LoginModalLabel">Login</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form id="login-form">
<label class="form-label" for="user_id">User ID</label>
<input class="form-control" type="text" id="user_id" name="user_id">
<label class="form-label" for="password">Password</label>
<input class="form-control" type="password" id="password" name="password">
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">Login</button>
</form>
</div>
</div>
</div>
</div>
/View/Authentication/login.js
//@Stackoverflow: Ignore Modal Initialization
openLoginModal();
function openLoginModal() {
const modal = bootstrap.Modal.getOrCreateInstance('#LoginModal', {
keyboard: false,
backdrop: 'static'
});
modal.show();
$("#login-form").on('submit', (event)=> {
event.preventDefault();
postAuthentication(event);
});
}
function postAuthentication(event) {
event.preventDefault();
const formData = new FormData();
const entries = $(event.currentTarget).serializeArray();
for (const entry of entries) {
formData.append(entry.name, entry.value);
}
$.ajax({
url: '/mydomain/Controller/Auth/post_login.php',
type: 'POST',
data: formData,
cache: false,
processData: false,
contentType: false,
success: (response) => {
window.location = "index.php"
},
error: (response) => {
alert("Error: " + response.responseText);
}
});
}
/Controller/Authentication/post_login.php
<?php
include_once("Config/settings.php");
if(!isset($_SESSION))
{
session_name($appName);
session_start();
}
include_once(__DIR__ . "/../../Service/AuthenticationService.php");
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: access");
header("Access-Control-Allow-Methods: POST");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
$authenticationService = new AuthenticationService();
if ($_SERVER["REQUEST_METHOD"] !== "POST") {
throw new Exception('Wrong method');
}
elseif (!isset($_POST['user_id'])|| !isset($_POST['password']) || empty(trim($_POST['user_id']))|| empty(trim($_POST['password']))) {
throw new Exception('Please fill out all input fields!');
} elseif (strlen($_POST['password']) < 8) {
throw new Exception('Password needs 8 figures!');
}
$return = $authenticationService->authenticate($_POST['user_id'], $_POST['password']);
header('Location: ../../index.php', true);
echo json_encode($return);
**/Service/AuthenticationService.php **
<?php
include_once("Config/settings.php");
if (!isset($_SESSION)) {
session_name($appName);
session_start();
}
require_once(__DIR__ . "./../Data/UserRepository.php");
class AuthenticationService
{
private UserRepository $userRepository;
public function __construct()
{
$this->userRepository = new UserRepository();
}
public function authenticate(string $kennung, string $password): array
{
$user = strtoupper(trim($kennung));
$PW = hash('sha3-512', trim($password));
$returnData = [
'loginOk' => false,
'passwordOk' => false,
'user' => $user
];
$user = $this->userRepository->get($user);
$dbPW = $user['password'];
if ($dbPW == $PW) {
$returnData['loginOk'] = true;
$returnData['passwordOk'] = true;
$returnData['$user'] = $user;
//Password is correct, so start a new session
//Store data in session variables
$_SESSION["loggedin"] = true;
$_SESSION["user"] = $user;
}
return $returnData;
}
}