- Knowledge
- technology
- OOP
- Tips
- Programming
- Tips
- Tutorial
- SEO
- Ranking
- Knowledge
- Special Day
- Seo
- Bug
- Data science
- Seo
- artificial intelligence
- Machine Learning
- Robotics
- happyNewYear2021
- newYearEve
- 2021
- Automation
- Smart Home
- Career
- Best Practices
- Git
- Logging
- Web Fundamentals
- DNS
- HTTPS
- Performance
- AI Tools
- ChatGPT
- Claude
- Gemini
- Laravel
- Eloquent
- MySQL
- HTTPS
- TLS
- Web Security
- Certificates
- Developer Life
- Debugging
- Docker
- DevOps
- Transactions
- Queues
- LLMs
- AI
- AI Coding
- Developer Tools
- React Native
- Expo
- Kate PMS
- Mobile Apps
- Laravel
- Authentication
- Sanctum
- Cookies
- API Design
- Payments
- Idempotency
- DeepSeek
- Open Source AI
- LLMs
- AI News
- Git
- Version Control
- AI Coding
- Prompting
- PHP
- Checklist
- MCP
- AI Agents
- OpenAI
- Architecture
- Microservices
- Modular Monolith
- Estimation
- Developer Life
- Project Planning
- Humour
- OAuth
- OpenID Connect
- Authentication
- Embeddings
- Vector Search
- RAG
- pgvector
- OpenAI
- GPT-4.1
- Codex CLI
- Events
- Testing
- Clean Code
- Maintainability
- Code Review
- Webhooks
- API
- Security
- Claude Code
- Workflow
- AI
- LLM
- Prompt Injection
- Mobile
- React
- Networking
- TCP
- UDP
- HTTP/3
- CLAUDE.md
- AWS
- Cloud Security
- Backups
- PHPUnit
- Software Engineering
- Leadership
- Communication
- RAG
- Embeddings
- AI Engineering
- IT Infrastructure
- Networking
- Access Control
- CI/CD
- GitHub Actions
- Gemini CLI
- Claude Code
- JavaScript
- Async/Await
- Node.js
- Promises
- Security
- Cryptography
- Passwords
- MySQL
- Database
- Vibe Coding
- Software Quality
- DNS
- Code Reading
- Onboarding
- Productivity
- Background Jobs
- Developer Humour
- Estimates
- Dev Life
- JWT
- o3-mini
- DeepSeek R1
- Rate Limiting
- Kate PMS
- E-Signing
- Audit Trail
- REST
- GraphQL
- API Design
- Laravel 12
- Upgrade Guide
- Open Source
- Self-Hosting
- Task Scheduling
- Cron
- Secrets
- CORS
- PHP
- PHP-FPM
- OPcache
- GitHub Copilot
- Software Architecture
- Engineering
- TypeScript
- JavaScript
- Type Safety
- AI Security
- React Native
- Product Design
- AI Agents
- Kiro
- Queues
- Redis
- RabbitMQ
- AWS SQS
- Nginx
- Apache
- GPT-5
- gpt-oss
- Clean Code
- Architecture
- Naming
- Documentation
- Career
- ADR
- Teamwork
- Supply Chain
- Kate HRM
- HR Software
- Permissions
- System Design
- Pagination
- SSH
- Linux
- Big O
- Databases
- Laravel Boost
- MCP
- Developer Skills
- Validation
- Databases
- Indexes
- Code Quality
- Deployment
- Developer Humour
- Feature Flags
- Code Review
- Pull Requests
- Docker
- Cursor
- Authorization
- RBAC
- Gemini
- Long Context
- PHP 8.4
- Caching
- Dependency Injection
- Web Performance
- Browser
- CSS
- Database
- Migrations
- ChatGPT
- AI for Developers
- Monitoring
- On-Call
- REST
- Backend
- SQL
- NoSQL
- Database Design
- Coding Agents
- Claude 4
- API Resources
- REST API
- Load Balancing
- Scaling
- AWS
- AI Tools
- Claude
- Sora 2
- CTE
- 2FA
- TOTP
- Programming Languages
- Prompts
- Developer Workflow
- API Gateway
- APIs
- Passport
- API Auth
- Learning
- Burnout
- Developer Growth
- Web Development
- SEO
- Kate Mall
- ChatGPT Atlas
- Agent Skills
- Middleware
- Laravel 12
- Collections
- Context Window
- Monitoring
- Commit Messages
- Self Review
- Growth
- Regex
- Programming Basics
- Text Processing
- Database Design
- Normalization
- Linux
- Server Security
- Linux Foundation
- Open Standards
- Legacy Code
- Documentation
- AI Workflow
- File Uploads
- Test Data
- Hashing
- Performance
- Caching
- Enums
- Scope Creep
- Estimation
- Codex
- Gemini CLI
- Timezones
- Carbon
- Bugs
- PHP 8.5
- Gemini 3
- GPT-5.1
- Data Integrity
- Event Loop
- Async
- Opus 4.5
- AI Models
- React
- Forms
- Frontend
- Backups
- AI Images
- DALL-E
- Midjourney
- Race Conditions
- Concurrency
- Legacy Code
- Refactoring
- Senior Engineer
- Scope
- LLM
- CDN
- Web
- Sub-Agents
- Soft Deletes
- Audit Log
- Concurrency
- AI Learning
- NestJS
- AI Evals
- Policies
- SPF DKIM DMARC
- Unicode
- UTF-8
- Knowledge Graph
- Value Objects
- Technical Debt
- Feature Flags
- Laravel Pennant
- Deployment
- Copilot
- Composer
- Dependencies
- Artisan
- Automation
- AWS S3
- Object Storage
- Cloud
- Small Language Models
- Ollama
- Production
- Sessions
- HTTP
- Mentoring
- SQL
- Virtual Machines
- Web Development
- HTTP/2
- QUIC
- Web Performance
- AI Integration
- LLM API
- SOLID
- OOP
- Hosting
- Serverless
- Merge Conflicts
- Temperature
- AI Development
- Reverse Proxy
- Nginx
- Infrastructure
- Verification
- Passkeys
- WebAuthn
- Teams
- Communication
- Stakeholders
- Monorepo
- CI/CD
- Versioning
- JSON Schema
- Livewire
- Inertia
- Meetings
- Distributed Systems
- Privacy
- Full-Stack
- T-Shaped Skills
- Money
- Notifications
- Web Security
- HTTP Headers
- CSP
- Function Calling
- Load Testing
- k6
- Data Extraction
- Debugging
- WebSockets
- SSE
- Real-Time
- Laravel Reverb
- Infrastructure as Code
- Terraform
- Side Projects
- Laravel Pint
- OpenAPI
- Swagger
- UX
- Multimodal
- Jest
- Pair Programming
- APIs
- Rate Limiting
- Resilience
- Dev Humour
- Design Tokens
- JWT
- API Keys
- Sessions
- PHPStan
- Rector
- Incidents
- Reporting
- Dashboards
- Zero Trust
- IAM
- Search
- Laravel Scout
- Junior Developers
- Mentoring
- Images
- WebP
- AVIF
- Bug Reports
- Let's Encrypt
- Design Docs
- Software Design
- Observers
- Replication
- Accountability
- Data Structures
- Reliability
- LLM Memory
- Error Handling
- Payments
- Payment Gateway
- Webhooks
- PCI DSS
- Observability
- OpenTelemetry
- Personal Brand
- Writing
- Conventions
- Dates
- Scheduling
- Disaster Recovery
- Compression
- Brotli
- Deadlines
- Developer Habits
- State Machines
- Tech Roles
- UUID
- ULID
- Horizon
- Planning
- Engineering Culture
- Ownership
- Soft Skills
- Socialite
- Cost Control
- Collations
- Unicode
- Octane
- PostgreSQL
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
- 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=.... - 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.
- Every request after that. The cookie comes along. The server looks up the session, finds your user ID, and treats the request as yours.
- 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:
| Driver | Where the data lives | Good for | Watch out for |
|---|---|---|---|
file | Files on the web server | One server, simple setups | Breaks with several servers behind a load balancer |
database | A sessions table | Most apps; the default in new Laravel projects | Adds a query per request; prune old rows |
redis | Redis, in memory | Several servers, high traffic | One more service to run and secure |
cookie | Inside the encrypted cookie itself | Stateless, tiny sessions | Browser 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, setSESSION_SECURE_COOKIE=truein 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?

Be first to comment it...