Profile    Mohammed Shiroz Status   Loading  
Logo
Share This
Back to blog
Filter by:
Tags
//Article title

Sessions Explained: How Websites Remember Who You Are

About Post

HTTP has the memory of a goldfish. Every request arrives as a complete stranger: no idea who you are, what's in your basket, or that you logged in thirty seconds ago.

And yet you can log in to a site in the morning and still be logged in at lunch. Something is doing the remembering. That something is the session, and once you see how small the trick is, a lot of web security suddenly makes sense.

The cloakroom ticket

The whole idea fits in one picture. You hand your coat to a cloakroom attendant and get a numbered ticket. The coat stays behind the counter. You carry only the number.

  • The coat is your session data: user ID, basket, flash messages, CSRF token. It stays on the server.
  • The ticket is the session ID: a long random string stored in a cookie in your browser.
  • On every request, the browser shows the ticket, and the server fetches the matching coat.

That's it. A session is a random ID in a cookie, pointing to data the server keeps.

Following one login, step by step

  1. First visit. You open the login page. The server creates a new session with a random ID, stores an empty record, and replies with Set-Cookie: laravel_session=....
  2. Login. You submit your email and password. The browser sends the cookie automatically. The server checks the password, then writes your user ID into the session record.
  3. Every request after that. The cookie comes along. The server looks up the session, finds your user ID, and treats the request as yours.
  4. Logout or expiry. The server deletes the record or it times out. The ticket in your browser now points to nothing.

Notice what the browser never holds: your user ID, your role, your data. Only the ticket. That's the main difference from a token like a JWT, where the data travels with the client.

Where the "coat" is stored

The server side can live in different places, and in Laravel that's the session driver, set with SESSION_DRIVER:

DriverWhere the data livesGood forWatch out for
fileFiles on the web serverOne server, simple setupsBreaks with several servers behind a load balancer
databaseA sessions tableMost apps; the default in new Laravel projectsAdds a query per request; prune old rows
redisRedis, in memorySeveral servers, high trafficOne more service to run and secure
cookieInside the encrypted cookie itselfStateless, tiny sessionsBrowser cookie size limits; can't revoke server-side

The file trap is a classic: the app works fine on one server, then you add a second and users get logged out at random, because their session file lives on the other machine. Shared storage (database or Redis) fixes it.

Expiry: two different clocks

Sessions die in two ways, and it's worth knowing which one you've configured.

  • Idle timeout. Laravel's SESSION_LIFETIME (in minutes) counts from your last activity. Every request resets the clock, so an active user stays logged in.
  • Browser close. With expire_on_close, the cookie has no expiry date and disappears when the browser fully closes. Modern browsers that restore tabs can keep these cookies alive longer than you'd expect.

"Remember me" is a separate mechanism: a long-lived cookie holding a remember token that can log you back in after the session itself has expired.

How sessions get attacked

Since the session ID is the login, anyone holding it is you. Almost every session attack is a way of stealing or planting that ticket.

Session hijacking

The attacker steals a valid session ID, through XSS reading the cookie, a network sniffed over plain HTTP, or a leaked log. The defences are mostly cookie flags:

  • HttpOnly: JavaScript can't read the cookie, so a script injected through XSS can't simply grab it.
  • Secure: the cookie is only sent over HTTPS. In Laravel, set SESSION_SECURE_COOKIE=true in production.
  • SameSite=Lax: the cookie isn't sent on most cross-site requests, which blocks a large class of CSRF attacks. It's Laravel's default.

Session fixation

This one is sneakier. The attacker doesn't steal your ticket; they hand you one. They get a valid session ID from the site, trick you into using it (for example through a crafted link on a site that accepts IDs from URLs), and wait for you to log in. If the ID doesn't change at login, their copy is now logged in as you.

The fix is simple: issue a new session ID whenever privilege changes. Laravel's session guard regenerates the ID when a user logs in, and the starter kits call it explicitly too. On logout, throw the whole session away:

public function logout(Request $request)
{
    Auth::logout();

    $request->session()->invalidate();      // delete data, new ID
    $request->session()->regenerateToken(); // new CSRF token

    return redirect('/');
}

Rule of thumb: the session ID is as valuable as the password. Keep it out of URLs and logs, send it only over HTTPS with HttpOnly, and give users a new one every time they log in or out.

The gotcha nobody mentions: concurrent requests

Here's the production one. A page fires two AJAX requests at the same time. Both load the session, both change something, and both save the whole session back. The last one to finish wins, and the other's change quietly disappears. A flash message vanishes, or a multi-step form loses a step.

Native PHP sessions avoid this by locking the session file. Laravel uses its own session handling instead, and doesn't lock by default. For routes where it matters, you can opt in:

Route::post('/checkout/step', [CheckoutController::class, 'store'])
    ->block(lockSeconds: 10, waitSeconds: 10);

It needs a cache driver that supports atomic locks. The session docs cover this and the drivers in more depth.

What to remember

  • A session is a random ID in a cookie, pointing to data on the server.
  • Use shared storage (database or Redis) once you have more than one server.
  • Know whether your timeout is idle-based, and what "remember me" really does.
  • Protect the cookie: HttpOnly, Secure, SameSite.
  • Regenerate the ID at login, invalidate at logout.

The OWASP session management cheat sheet is the best next read if you want the full security picture.

Which session driver do you run in production, and what made you pick it?

Comments (0)
Leave your review

Thanks for your valuable comments. Your comments has been updated and appreciate your getting in touch...

01. About Shiroz

Mohammed Shiroz

Hi, I'm Mohammed Shiroz, a software engineer and AI enthusiast from Sri Lanka who turns ideas into intelligent, real-world solutions. With over 9 years of hands-on experience, I currently lead real estate ERP development at Kate Group, a...

03.My Projects

04. Categories

Ready To order Your Project ?

Get in Touch
Close