Suppose I have a static website that uses a web API and I want to use session for various purposes (for authorization, identification, etc.) on this website. I know that a static website lacks server side code and web APIs are stateless so neither one of them can be used to create a session object. If it is possible to create a session object that is safe and secure (not cookies or localstorage), how would I create a one for this situation?
If you’ve got a web API you dont have a static website, unless that API serves the same content constantly. And if it does, its not an API, it’s a file.
Let me rephrase, if I’m not using frameworks and libraries such as Angular, React, Vue, Dotnet MVC, etc. to create a website and all the webpages only get their data from web APIs and a database, how can I secure my website and make use of session after the user logs in. To mimic the creation of a session object as soon as a user logs in, I thought about storing a Boolean value of true in a database table column called Active.
Then every time a user requests data, my code would check if this value is true or false and it will grant or deny access based on this. Also if the user logs off, if the screen stays idled for too long, or if time runs out, then the Boolean value will be set to false. The only issue is I am not sure if SQL Server has a Timer function so I can do this. I see something called Conversation Timer but not sure if it will work as a timer.
This is just an experiment to see if it’s possible to create a very light website by not using too many frameworks and libraries and secure it using only the bare minimum requirements like a web API and a database without relying on the bells and whistles of the mentioned frameworks and libraries. Please share your thoughts.
Here’s an example of my login PHP -
<?php
// Include the configuration file and autoload file from the composer.
require_once __DIR__ . '/../config/starlite_config.php';
require_once "vendor/autoload.php";
// Import the ErrorHandler and Database classes from the PhotoTech namespace.
use clearwebconcepts\{
ErrorHandler,
Database,
LoginRepository as Login
};
// Create an ErrorHandler instance
$errorHandler = new ErrorHandler();
// Set the exception handler to use the ErrorHandler instance
set_exception_handler([$errorHandler, 'handleException']);
// Create a Database instance and establish a connection
$database = new Database();
$pdo = $database->createPDO();
// Create a LoginRepository instance with the database connection
$login = new Login($pdo);
$checkStatus = new Login($pdo);
// Start session if not already started
if (session_status() == PHP_SESSION_NONE) {
session_start();
}
// Redirect to dashboard if the user is already logged in
if ($login->check_login_token()) {
header('Location: member.php');
exit();
}
// Generate a CSRF token if it doesn't exist and store it in the session
if (!isset($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
// Detect environment
$isLocal = in_array($_SERVER['REMOTE_ADDR'], ['127.0.0.1', '::1']);
$cookieDomain = $isLocal ? '' : DOMAIN;
$cookieSecure = !$isLocal; // Set to true on remote server
// Process the login form submission
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Check if the submitted CSRF token matches the one stored in the session
if (hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
// Sanitize the username and password input
$username = strip_tags($_POST['username']);
$password = $_POST['password'];
// Verify the user's credentials
if ($login->verify_credentials($username, $password)) {
// Generate a secure login token
$token = bin2hex(random_bytes(32));
// Store the login token in the database
$login->store_token_in_database($_SESSION['user_id'], $token);
// Set a secure cookie with the login token
setcookie('login_token', $token, [
'expires' => strtotime('+6 months'),
'path' => '/',
'domain' => $cookieDomain, // Adjusted for environment
'secure' => $cookieSecure, // Adjusted for environment
'httponly' => true,
'samesite' => 'Lax'
]);
// Store the login token in the session
$_SESSION['login_token'] = $token;
// Redirect based on security level
$securityLevel = $_SESSION['security_level'];
if (in_array($securityLevel, ['admin','client', 'member','moderator', 'sysop'], true)) {
header('Location: member.php');
} else {
// Fallback for unexpected security levels
header('Location: index.php');
}
exit;
} else {
// Log error message for invalid username or password
$error = 'Invalid username or password';
error_log("Login error: " . $error);
}
} else {
// Display an error message
$error = 'Invalid CSRF token';
error_log("Login error: " . $error);
$error = 'An error occurred. Please try again.';
}
}
// Generate a random nonce value
$nonce = base64_encode(random_bytes(16));
?>
There’s session in my config.php as well that checks to see if the user is already login. This is just an example on how it can be done.
Hi thanks for your reply,
Based on my research PHP is a scripting language and it’s part of a framework much like asp.net is a framework with its own scripting language. I’m trying to stay away from using too many frameworks to keep my web project very light. As it is I’m using Dotnet web API and that already makes my project too heavy and bloated. I don’t want to go and add even more to the project by adding a script that requires a framework for it to work.
This is just an experiment that I want to try after watching a youtube video on creating a SPA without a framework. Unfortunately the video did not address the issue of securing such a web application.
PHP is a server side language. It’s not a framework any more than HTML or Javascript is.
What Pepster is hitting upon, however, is the nugget at the end of the question - you’d need a server side programming language of some form in order to secure anything. The server must be aware of the user in order for any trust to be given - which would require a stateful interaction of some kind.
My guess is that you probably use a database and .NET, One way is to store all credentials in the database.
I do this (simplified):
- The user log in and is verified against the database of accepted users.
- If the user is granted access, a cookie is created by the server and forwarded to the browser.
- For each call from browser to the server end points, this cookie is verified.
- If the cookie is not expired, the content is delivered from the server.
The main benefit is that nothing secret is in the browser. Just a harmless cookie. The session id and credentials is stored separately in the database for fast lookup.
As the database is on the same computer as the web server, the speed for lookup is very fast. And as the only connection to the database is through the web server, the database will not be directly exposed to the internet.
To be honest, there are so many ways to fix a login procedure so I was very confused. But my main focus was not to store anything of value in the browser.
I use a web server that serves the static content from templates. But you can also store the static content as simple files. In my case the page is rendered at the server and sent to the browser. So yes and no IMO.
Hello my name is Julio Herrera. I want to share my thoughts according my research!
Since a static website lacks server-side capabilities, and web APIs are stateless, traditional session management using server-side storage is not possible. However, you can implement secure session handling using token-based authentication with JWT (JSON Web Token) and browser storage alternatives.
Solution: Token-Based Sessions with Secure Storage
- Authentication & Token Issuance: When the user logs in, the web API issues a JWT (signed but not stored in cookies or localStorage).
- Secure Storage: Store the token in Memory (JavaScript variable) or Web Worker (to keep it session-based and avoid persistent storage).
- Session Management: Keep the token in memory and refresh it using Silent Authentication (e.g., OAuth 2.0 PKCE with refresh tokens in HttpOnly cookies).
- Token Expiry: Use short-lived access tokens and refresh tokens securely to maintain sessions.
This method ensures security while avoiding cookies and localStorage vulnerabilities.
until you change pages, anyway.
also i like how everyones dancing around the subject of “when the user logs in”… how exactly are you processing a login without a server side language? (and once you have a server side language… why arent you just using that language’s session management?)
I guess, at the heart of it, I ask the OP the question. Why is a local cookie not “safe and secure”?
If you don’t trust the user’s computer to hold a cookie, you don’t trust the user’s computer to hold a javascript variable, either.
Security would be a problem.
I am not sure what a session object is and I am not sure if you mean an object that is specific to ASP.Net or a session object in general. I assume that since there is no ASP.Net server-side you would not be able to use an ASP.Net session object. Therefore you would probably need to be able to get a session id that is sent to the client that the client returns and that is always sent in both directions. I do not know if that could be done securely and can be guaranteed to be secure.
How will you determine which user it is?
The term framework is general and the definition varies; some are server-side and some are client-side. I think it is better to say server-side language or server-side framework when referring to something server-side.
Yes, PHP is a server-side. HTML and JavaScript are client-side. The difference is highly relevant to this discussion.
The page ASP.NET Core Blazor | Microsoft Learn describes Blazor WebAssembly as a single-page app (SPA) framework, at least it did; the Google search result says it does but I cannot find those words in the page currently. I know however that Blazor WebAssembly can generate a static website, such as one that can be deployed from GitHub to GitHub pages or Cloudflare pages. I have a few websites in Cloudflare pages that are like that. See the following also.
- Call a web API from an ASP.NET Core Blazor app | Microsoft Learn
- Host and deploy ASP.NET Core Blazor WebAssembly | Microsoft Learn
Update: There is something new that I was unaware of. The ASP.NET Core Blazor pager describes use of the .NET Multi-platform App UI (.NET MAUI) instead of WebAssembly. I am not sure if that would be a static website but I know that ASP.NET Core Blazor with WebAssembly can generate a static site.
For a static website using a .NET web API, a secure session can be managed using server-issued tokens like JWT (JSON Web Token) or reference tokens combined with an authentication mechanism such as OAuth2. When a user logs in, the API can generate a short-lived, encrypted token and store it in session storage (to prevent persistent access like cookies) or use a Secure HttpOnly SameSite cookie for better protection. The token can be refreshed using a separate API endpoint with a refresh token stored securely on the server. This ensures authorization without exposing sensitive data in client-side storage. The API can validate the token on each request and retrieve session-related details from a secure server-side data store like Redis or an in-memory cache. To further enhance security, implement CORS restrictions, rate limiting, and HTTPS enforcement to minimize attack risks.
And once again, explain to me how you combine:
with:
Just because Javascript is used on the client’s end… doesnt magically remove the need for the server end… and if you’ve got the server end… just use the server end’s inbuilt session management.