Laravel Cookie Excessive Timeout

Medium Risk Session Management
laravelphpcookiestimeoutsession-managementsecurity-policy

What it is

The Laravel application sets cookies with excessively long expiration times, increasing the window of opportunity for session hijacking and unauthorized access. Long-lived cookies remain valid even after users expect their sessions to have expired, creating security risks if devices are compromised.

// Vulnerable: Excessively long cookie timeouts public function login(Request $request) { $credentials = $request->only('email', 'password'); if (Auth::attempt($credentials)) { // Dangerous: 1 year session timeout return response('Login successful')->cookie( 'auth_token', $request->user()->createToken('auth')->plainTextToken, 60 * 24 * 365 // 1 year - too long! ); } } // Another example with remember functionality public function setRememberMe(Request $request) { $user = $request->user(); // Dangerous: 10 year expiration return response('Remembered')->cookie( 'remember_token', $user->remember_token, 60 * 24 * 365 * 10 // 10 years - extremely long! ); } // config/session.php (problematic configuration) return [ 'lifetime' => 525600, // 1 year in minutes - too long 'expire_on_close' => false, ];
// Secure: Appropriate cookie timeouts with security considerations public function login(Request $request) { $credentials = $request->only('email', 'password'); $rememberMe = $request->boolean('remember_me'); if (Auth::attempt($credentials)) { $user = $request->user(); if ($rememberMe) { // Secure: Reasonable remember duration (30 days max) $tokenExpiry = 60 * 24 * 30; // 30 days $token = $user->createToken('remember', ['remember'])->plainTextToken; return response('Login successful')->cookie( 'remember_token', $token, $tokenExpiry, '/', null, true, // secure true, // httpOnly false, 'Strict' ); } else { // Short session for regular login (2 hours) $sessionExpiry = 60 * 2; // 2 hours return response('Login successful')->cookie( 'session_token', $user->createToken('session')->plainTextToken, $sessionExpiry, '/', null, true, true, false, 'Strict' ); } } return response('Invalid credentials', 401); } // Implement sliding expiration class SessionTimeoutMiddleware { public function handle($request, Closure $next) { if (Auth::check()) { $user = Auth::user(); $lastActivity = $user->last_activity; $timeout = config('session.timeout', 120); // 2 hours default if ($lastActivity && now()->diffInMinutes($lastActivity) > $timeout) { Auth::logout(); return response('Session expired', 401); } // Update last activity (sliding expiration) $user->update(['last_activity' => now()]); } return $next($request); } } // config/session.php (secure configuration) return [ 'driver' => env('SESSION_DRIVER', 'database'), 'lifetime' => env('SESSION_LIFETIME', 120), // 2 hours 'expire_on_close' => env('SESSION_EXPIRE_ON_CLOSE', true), 'encrypt' => false, 'files' => storage_path('framework/sessions'), 'connection' => env('SESSION_CONNECTION', null), 'table' => 'sessions', 'store' => env('SESSION_STORE', null), 'lottery' => [2, 100], 'cookie' => env('SESSION_COOKIE', 'laravel_session'), 'path' => '/', 'domain' => env('SESSION_DOMAIN', null), 'secure' => env('SESSION_SECURE_COOKIE', true), 'http_only' => true, 'same_site' => 'strict', 'timeout' => env('SESSION_TIMEOUT', 120), // Custom timeout setting ]; // Service for managing session policies class SessionPolicyService { public function getTimeoutForRole($role) { $timeouts = [ 'admin' => 30, // 30 minutes for admin 'user' => 120, // 2 hours for regular users 'guest' => 15, // 15 minutes for guests ]; return $timeouts[$role] ?? 60; // Default 1 hour } public function shouldExtendSession($user) { // Extend session for active users $recentActivity = $user->actions() ->where('created_at', '>', now()->subMinutes(5)) ->exists(); return $recentActivity; } }

💡 Why This Fix Works

See fix suggestions for detailed explanation.

Why it happens

Laravel applications configure cookie timeouts measured in years or months without considering security implications of long-lived authentication credentials. Developers set cookie expiration using response()->cookie('token', $value, 60 * 24 * 365) creating 1-year cookies, or Cookie::queue('auth', $token, 60 * 24 * 365 * 5) establishing 5-year validity periods, treating cookies as permanent storage rather than temporary authentication mechanisms. These excessive timeouts arise from prioritizing user convenience (avoiding re-authentication) over security principles dictating that credentials should expire after reasonable periods. Common problematic durations include authentication tokens valid for years: response()->cookie('api_token', $token, 525600) setting 1-year expiration making stolen tokens valuable for extended periods, remember-me functionality with decade-long validity: Cookie::queue('remember', $hash, 60 * 24 * 365 * 10) creating 10-year cookies that persist across device compromises, and session cookies configured for months rather than hours. Financial applications, healthcare systems, and enterprise software inappropriately use long timeouts mimicking consumer applications' convenience without recognizing elevated security requirements. The risk manifests when devices are compromised, sold, or stolen: long-lived cookies enable persistent unauthorized access, attackers stealing cookies through XSS maintain access long after vulnerability is patched, and users sharing devices inadvertently grant access to subsequent users through unexpired cookies. Regulatory compliance violations occur when long cookie timeouts conflict with data protection regulations requiring session termination, HIPAA mandating automatic logoff after inactivity, PCI DSS requiring session timeout for payment applications, and GDPR principles of data minimization suggesting limiting authentication credential lifetime. Developer misconceptions drive the pattern: believing longer timeouts improve user experience without quantifying actual benefit, assuming cookies are secure because they use HTTPS ignoring device-level threats, and not understanding that cookie theft (through XSS, device theft, malware) provides immediate access regardless of password strength.

Root causes

Setting Cookie Expiration Times that Are Too Long for Security Requirements

Laravel applications configure cookie timeouts measured in years or months without considering security implications of long-lived authentication credentials. Developers set cookie expiration using response()->cookie('token', $value, 60 * 24 * 365) creating 1-year cookies, or Cookie::queue('auth', $token, 60 * 24 * 365 * 5) establishing 5-year validity periods, treating cookies as permanent storage rather than temporary authentication mechanisms. These excessive timeouts arise from prioritizing user convenience (avoiding re-authentication) over security principles dictating that credentials should expire after reasonable periods. Common problematic durations include authentication tokens valid for years: response()->cookie('api_token', $token, 525600) setting 1-year expiration making stolen tokens valuable for extended periods, remember-me functionality with decade-long validity: Cookie::queue('remember', $hash, 60 * 24 * 365 * 10) creating 10-year cookies that persist across device compromises, and session cookies configured for months rather than hours. Financial applications, healthcare systems, and enterprise software inappropriately use long timeouts mimicking consumer applications' convenience without recognizing elevated security requirements. The risk manifests when devices are compromised, sold, or stolen: long-lived cookies enable persistent unauthorized access, attackers stealing cookies through XSS maintain access long after vulnerability is patched, and users sharing devices inadvertently grant access to subsequent users through unexpired cookies. Regulatory compliance violations occur when long cookie timeouts conflict with data protection regulations requiring session termination, HIPAA mandating automatic logoff after inactivity, PCI DSS requiring session timeout for payment applications, and GDPR principles of data minimization suggesting limiting authentication credential lifetime. Developer misconceptions drive the pattern: believing longer timeouts improve user experience without quantifying actual benefit, assuming cookies are secure because they use HTTPS ignoring device-level threats, and not understanding that cookie theft (through XSS, device theft, malware) provides immediate access regardless of password strength.

Using Unlimited or Very Long Session Timeouts

Laravel session configuration in config/session.php sets 'lifetime' to extremely high values or effectively unlimited durations, making session cookies persist indefinitely without expiration enforcement. Configurations like 'lifetime' => 525600 (1 year in minutes) or 'lifetime' => 2147483647 (maximum integer, effectively unlimited) treat sessions as permanent, contradicting session concept of temporary authentication state. Combined with 'expire_on_close' => false, sessions persist across browser restarts extending vulnerability window beyond active user sessions. The problem compounds through framework defaults: older Laravel versions had generous default timeouts that developers never revisited, boilerplate configurations copied from tutorials contain insecure timeout values without explanation of security implications, and environment-specific overrides using env('SESSION_LIFETIME', 525600) with insecure fallback values. Session storage mechanisms influence risk severity: file-based sessions (session.driver = 'file') with long lifetimes accumulate on servers creating large attack surfaces and making session cleanup difficult, database sessions (session.driver = 'database') with no garbage collection allow indefinite session persistence, and Redis/Memcached sessions with no expiration policies bypass natural cache eviction. Application architecture amplifies issues: stateless JWT authentication claims to be sessionless but stores tokens in cookies with excessive expiration mimicking long sessions, single sign-on (SSO) implementations use long-lived session cookies for convenience across multiple applications multiplying risk, and API authentication storing bearer tokens in cookies with API-appropriate long lifetimes (intended for programmatic access) rather than user-appropriate short lifetimes. The fundamental misunderstanding treats sessions as identity storage rather than authentication proof: sessions should expire requiring re-authentication verifying user still possesses credentials, but long lifetimes assume initial authentication validates permanent access. Real-world exploitation: attackers compromising devices (lost laptops, stolen phones, malware-infected machines) leverage long-lived sessions for extended unauthorized access, automated session harvesting attacks collect cookies knowing they remain valid for extended periods, and insider threats exploit long sessions accessing systems long after employment termination if session cookies captured during employment.

Missing Consideration of Security vs. Convenience Trade-offs

Development teams prioritize user convenience over security without systematically evaluating trade-offs, resulting in excessive cookie timeouts that unnecessarily increase risk. Product requirements specify "keep users logged in" without defining acceptable timeout boundaries, leading developers to implement very long timeouts assuming "longer is better" for user experience. User complaints about frequent re-authentication prompt knee-jerk reactions extending timeouts to years rather than implementing proper solutions like sliding expiration or remember-me tokens. Competitive analysis observes other applications maintaining long sessions, leading product teams to demand matching timeout policies without understanding security implications: consumer applications with lower security requirements inform enterprise application timeout policies, social media platforms with different threat models become inappropriate benchmarks for financial applications, and gaming or entertainment applications prioritizing engagement over security set false standards. Business stakeholders lacking security awareness make timeout decisions based solely on convenience: customer support reports about login friction drive timeout extensions without security consultation, user experience designers optimize for login frequency reduction without security review, and product roadmaps prioritize authentication convenience over security hardening. Quantitative measurement gaps obscure actual user impact: no metrics distinguish between users actually benefiting from long sessions versus security costs, missing A/B testing comparing different timeout durations with actual user satisfaction, and lack of data showing whether 30-day sessions truly provide better experience than 7-day sessions with proper remember-me implementation. Development velocity pressures create suboptimal decisions: quick timeout configuration during MVP without revisiting during production hardening, copied configurations from other projects or frameworks without customization to security requirements, and technical debt accumulation where initial "temporary" long timeouts become permanent. The root issue is treating security and convenience as opposing forces rather than simultaneously achievable through proper design: sliding expiration provides convenience of rarely re-authenticating for active users while maintaining security of short timeouts for inactive sessions, remember-me tokens offer long-term convenience without maintaining active sessions, and contextual authentication (biometrics, device recognition) reduces re-authentication friction without extending cookie lifetimes. Proper approach requires: defining acceptable risk levels for applications, implementing layered authentication (short sessions for regular access, step-up authentication for sensitive operations), measuring actual user impact of different timeout policies through controlled experiments, and making security-informed decisions balancing measurable convenience against quantified risk.

Inadequate Session Timeout Policies

Organizations lack formal policies governing session timeout requirements, leading to ad-hoc per-application decisions without consistency or security consideration. Missing organizational standards: no enterprise-wide session timeout policy defining maximum allowable durations by application sensitivity, absence of role-based timeout requirements (administrators vs. regular users vs. guests), and no documentation explaining timeout policy rationale or enforcement mechanisms. Applications within same organization have wildly different timeout configurations: administrative portal uses 15-minute timeout while customer portal allows 1-year sessions despite similar data sensitivity, microservices use inconsistent timeout policies creating security gaps where least secure service determines overall security posture, and third-party SaaS integrations use varied session policies creating inconsistent user experience and security posture. Compliance-driven industries with regulatory requirements still lack implementation: HIPAA-regulated healthcare applications missing automatic logoff requirements (15-20 minutes inactivity), PCI DSS applications without session timeout enforcement (15 minutes per requirement 8.1.8), NIST 800-63 guidelines recommending 30-minute inactivity timeout not implemented, and financial services regulations requiring short session timeouts ignored. Policy creation challenges: security teams define policies but development teams don't implement due to perceived user experience impact, policies exist in documentation but no technical enforcement or monitoring, and policy exceptions granted liberally without documented risk acceptance. Technical gaps in policy enforcement: no centralized session management enforcing timeout policies across applications, missing middleware or framework-level controls implementing policies consistently, and lack of monitoring/alerting on policy violations. Policy review and updates: no regular review cycle updating policies as threats evolve, security incidents not triggering policy re-evaluation, and new application deployments not required to comply with session timeout policies. Developer awareness: developers unaware organizational policies exist, no training on session timeout security requirements and implementation, and security review processes don't check session timeout configurations. The solution requires: formal session timeout policy creation with executive support, technical controls enforcing policies at framework/infrastructure level, regular audits verifying compliance, integration into development lifecycle through security requirements in project charters, and continuous monitoring with automated policy compliance checking.

Copy-Pasting Cookie Code Without Reviewing Expiration Times

Developers copy cookie-related code from existing projects, tutorials, Stack Overflow, or documentation without reviewing or customizing timeout values for specific security requirements. Code reuse patterns introduce vulnerabilities: copying authentication code from tutorial with response()->cookie('token', $value, 525600) maintaining tutorial's 1-year example without adjusting for production requirements, duplicating cookie handling across multiple controllers copying initial insecure timeout to all authentication flows, and using boilerplate code from Laravel packages with generic long timeouts. Stack Overflow answers demonstrate functionality without security: developers searching "laravel set cookie" copy first working example without reading explanation or security considerations, accepted answers prioritize working code over secure code showing Cookie::queue('name', 'value', 999999) as example of "long lasting cookie", and code snippets lack security context explaining appropriate timeout ranges. Documentation examples balance clarity with comprehensiveness: official Laravel documentation shows cookie() with all parameters but uses arbitrary example values that developers copy literally, framework tutorials demonstrating features use simple examples (60 minutes) that developers extend dramatically without understanding security implications, and quickstart guides skip security configuration focusing on basic functionality. Legacy code migration introduces outdated patterns: modernizing older PHP applications by wrapping in Laravel framework but retaining original insecure cookie timeouts, converting from other frameworks keeping previous timeout policies without reevaluating for Laravel context, and technical debt where initial proof-of-concept timeouts persist into production. Team code patterns: junior developers copy senior developer code assuming it represents best practice without understanding original context was different application type, code review processes approve cookie code without scrutinizing timeout values if other aspects (HttpOnly, Secure flags) are correct, and linting/static analysis tools don't flag excessive timeout values. IDE auto-completion and snippets: editor snippets for cookie creation include placeholder timeout values that developers forget to customize, auto-complete showing previous cookie() calls with their timeouts leads to copying inappropriate values, and code generation tools create cookie handlers with default values requiring manual security review. The fix requires: code review checklists specifically checking cookie expiration appropriateness for application context, static analysis rules flagging cookies with timeouts exceeding thresholds, developer education on security implications of cookie timeouts, secure code templates with commented explanations of timeout value choices, and mandatory security review for authentication-related code changes.

Fixes

1

Implement Appropriate Session Timeout Policies

Define and enforce session timeout policies aligned with application security requirements, user risk profiles, and regulatory compliance obligations. Establish baseline timeouts: sensitive applications (banking, healthcare, administrative): 15-30 minute inactivity timeout, standard business applications: 1-2 hour timeout, low-risk consumer applications: 2-8 hour timeout with remember-me option. Document policy rationale: explain why specific timeouts chosen based on threat modeling and risk assessment, reference compliance requirements (HIPAA, PCI DSS, NIST 800-63) mandating specific timeouts, and describe trade-offs between security and convenience. Implement role-based timeouts: administrators: 15-30 minutes reflecting elevated privilege risk, privileged operations (payment processing, data export): 5-10 minutes requiring re-authentication, regular users: 1-2 hours balancing security and usability, and API access: token-based with 1-hour short-lived tokens and refresh token rotation. Configure Laravel session timeouts in config/session.php: set 'lifetime' => env('SESSION_LIFETIME', 120) using environment variable with secure default (120 minutes = 2 hours), adjust for sensitivity: 'lifetime' => 15 for admin applications, 'lifetime' => 30 for financial applications, and implement 'expire_on_close' => true for high-security contexts. Create environment-specific policies: production: strict timeouts enforcing security requirements, staging: match production for realistic testing, development: potentially longer timeouts for debugging convenience documented as exception. Implement custom timeout middleware: create SessionTimeoutMiddleware checking last activity timestamp, enforce inactivity timeout: if (now()->diffInMinutes($lastActivity) > $timeout) { Auth::logout(); }, store activity tracking: Session::put('last_activity', now()), and apply role-specific timeouts: $timeout = $this->getTimeoutForRole(Auth::user()->role). Document exceptions: maintain register of applications requiring non-standard timeouts with business justification, require executive approval for timeout extensions beyond policy, regularly review exceptions ensuring continued validity, and sunset exceptions when no longer necessary. Audit compliance: implement automated checks verifying session configuration matches policy, alert security team on policy violations detected in configuration, include session timeout review in penetration testing and security audits, and track session timeout metrics across application portfolio. Train developers: provide guidance on implementing session timeouts correctly, explain security rationale behind timeout requirements, demonstrate proper configuration patterns in code examples, and require security training covering session management. Monitor effectiveness: track user complaints about session expiration (too short), measure security incidents related to session hijacking (too long), analyze authentication logs identifying unusual session patterns, and adjust policies based on real-world effectiveness.

2

Use Shorter Cookie Expiration Times for Sensitive Applications

Configure significantly shorter cookie timeouts for applications handling sensitive data or requiring elevated security, prioritizing security over convenience. Categorize application sensitivity: high sensitivity (financial transactions, healthcare records, administrative access): 15-30 minute cookies, medium sensitivity (business applications with customer data): 1-2 hour cookies, low sensitivity (public content, non-authenticated features): up to 8 hours. Implement sensitivity-based configuration: create config/security.php defining sensitivity levels and corresponding timeouts: ['high' => 30, 'medium' => 120, 'low' => 480], use configuration in cookie creation: $timeout = config('security.timeouts')[config('app.sensitivity')], and enforce through middleware validating cookies don't exceed sensitivity-appropriate durations. Configure short authentication cookies: response()->cookie('auth_token', $token, 30, '/', null, true, true, false, 'Strict') for 30-minute expiration, differentiate authentication cookies (short) from preference cookies (can be longer), and implement separate token types: short-lived access tokens (30 minutes) and longer-lived refresh tokens (7 days) with different security properties. Handle sensitive operations: implement step-up authentication for critical actions requiring re-authentication regardless of active session, use short-lived operation tokens: $operationToken = $user->createToken('payment', [], now()->addMinutes(5)) for 5-minute validity, and prompt re-authentication for high-risk operations (password change, fund transfer, data export). Implement context-aware timeouts: detect sensitive page access adjusting timeout: if ($request->routeIs('admin.*')) { Session::put('timeout', 15); }, reduce timeout during suspicious activity (multiple failed attempts, unusual access patterns), and increase security level requiring re-authentication when risk increases. Test shorter timeouts: conduct user testing with proposed timeout values measuring actual friction, A/B test different timeout durations for sensitive features collecting user feedback, and measure support ticket volume about session expiration identifying pain points. Communicate timeouts to users: display session expiration warnings: "Your session will expire in 2 minutes due to inactivity", provide countdown timers for sensitive operations showing remaining time, explain why short timeouts necessary in security-conscious applications building user trust, and offer session extension option requiring user interaction confirming continued activity. Balance security and usability: implement activity detection extending sessions for active users while maintaining absolute maximum session duration, use sliding expiration: extend session on each request up to maximum lifetime, and provide clear re-authentication flow minimizing disruption when sessions expire. Monitor impact: track session expiration rates measuring how often users experience timeouts, analyze authentication patterns identifying workflows interrupted by short timeouts, collect user feedback through surveys about session timeout experience, and adjust timeouts based on actual user behavior balancing security requirements against measurable usability impact.

3

Implement Sliding Expiration for Active Sessions

Use sliding expiration extending session lifetime on user activity, maintaining security of short idle timeouts while providing convenience of rarely expiring for active users. Understand sliding expiration: each user request resets session expiration timer, idle timeout (no activity) triggers expiration, but active users maintain sessions indefinitely up to absolute maximum, providing security (inactive sessions expire quickly) with usability (active users not interrupted). Implement in middleware: create middleware tracking activity, update last activity timestamp on each request: Session::put('last_activity', now()), check idle timeout: $idleMinutes = now()->diffInMinutes(Session::get('last_activity')); if ($idleMinutes > $idleTimeout) { Auth::logout(); }, and maintain absolute maximum: Session::put('created_at', now()) on login, then if (now()->diffInHours(Session::get('created_at')) > $maxHours) { Auth::logout(); }. Configure timeouts: idle timeout (no activity): 15-30 minutes for sensitive applications, absolute maximum (regardless of activity): 8-24 hours preventing indefinite sessions, and role-based idle timeouts: administrators 15 minutes, regular users 30 minutes. Optimize activity tracking: not all requests should extend session (static assets, health checks, API polling), implement activity threshold: only extend if >1 minute since last extension preventing excessive session updates, use client-side activity detection: JavaScript tracking keyboard/mouse input, and send heartbeat requests on significant activity keeping session alive. Visual feedback: show session expiration countdown in UI: "Session expires in 5 minutes due to inactivity", provide "Stay signed in" button extending session with explicit user action, display warning before expiration: modal appearing 2 minutes before timeout offering extension, and clear communication: "You'll be logged out after 15 minutes of inactivity". Implement gracefully: save user work before logout: auto-save form data on timeout, redirect to login with return URL: after re-authentication, return to previous page, preserve draft state: store unsaved changes allowing recovery after re-login, and show clear message: "Your session expired due to inactivity. Please log in again.". Database session tracking: store last_activity in sessions table: Session::put('last_activity', now()), implement cleanup: delete sessions where last_activity < now - timeout, use database transactions ensuring consistency, and index last_activity for efficient cleanup queries. Test implementation: verify idle timeout works: inactive session expires after configured period, confirm activity extends session: active user maintains session, test absolute maximum: even active sessions eventually expire, and validate edge cases: what happens at exactly timeout threshold, midnight rollover, daylight saving changes. Monitor sliding expiration: track average session duration for active vs. inactive users, measure user complaints about premature expiration indicating threshold too aggressive, analyze session extension patterns identifying normal vs. suspicious activity, and alert on anomalies: sessions extended at unusual hours, from unusual locations, or with unusual patterns.

4

Provide Options for Users to Choose Session Duration

Offer users explicit control over session duration through "Remember me" functionality, allowing informed choice between security (short sessions) and convenience (longer persistence). Implement remember-me checkbox: add checkbox to login form: <input type="checkbox" name="remember" value="1"> Remember me on this device, validate input: $remember = $request->boolean('remember'), and create different token types: short session token vs. long remember token. Configure remember duration: reasonable maximum: 30 days for standard applications, shorter for sensitive: 7 days for financial applications, never unlimited: even remember-me should eventually expire, and configurable: define in config: 'remember_duration' => 60 * 24 * 30. Use Laravel's built-in remember: Auth::attempt($credentials, $remember) automatically handles remember functionality, creates remember_token in users table storing persistent token, sets encrypted cookie with long expiration when remember=true, and validates token on subsequent requests authenticating without credentials. Custom remember implementation: generate secure remember token: $token = Str::random(60), store hash in database: $user->update(['remember_token' => Hash::make($token)]), create long-lived cookie: response()->cookie('remember', $token, 60 * 24 * 30, '/', null, true, true, false, 'Strict'), and validate on return: verify token matches hashed value, check expiration hasn't passed, and create new regular session. Security considerations: remember tokens are sensitive: require HttpOnly, Secure, SameSite flags, implement token rotation: generate new token after use invalidating old, enable device management: users can see/revoke remember tokens per device, and force logout: security events (password change, suspicious activity) revoke all remember tokens. User communication: clearly explain remember-me implications: "Stay logged in for 30 days on this device", warn about public devices: "Don't use on shared computers", show active sessions: list devices with remember-me active offering revoke option, and privacy implications: explain that remember means longer cookies. Implement device binding: store device fingerprint with remember token: user agent, IP address range, prevent token use from different devices, provide recovery: if fingerprint changes, require re-authentication with additional verification, and balance security vs. usability: too strict fingerprinting breaks on legitimate device changes. Multi-factor authentication integration: require MFA on remember-me login from new device, cache MFA for remembered devices (with separate expiration), prompt MFA for sensitive operations even with remembered session, and offer "Remember this device for MFA" separate from session remember. Granular options: provide multiple duration choices: "Remember for 1 day", "7 days", "30 days", default to most secure: pre-select shortest or none, document recommendations: explain which option users should choose, and respect user choice: don't override user-selected duration. Monitor and metrics: track remember-me usage percentage showing user preference, measure remember-me token security events: stolen tokens, suspicious usage, analyze whether offering choice reduces support burden about session expiration, and optimize durations based on actual user behavior patterns.

5

Use Remember Tokens for Long-Term Authentication Instead of Long Cookies

Implement separate remember token mechanism for persistent authentication rather than extending session cookie lifetime, separating concerns and enabling better security controls. Understand token separation: session cookies: short-lived (hours), automatically expire on inactivity, for active session management, should be HTTPOnly with short timeout. Remember tokens: longer-lived (weeks), persist across browser sessions, only for re-authentication not active session, can have additional validation requirements. Implement token architecture: database table storing remember tokens: Schema::create('remember_tokens', function($table) { $table->id(); $table->foreignId('user_id'); $table->string('token', 64)->unique(); $table->string('device_identifier'); $table->timestamp('last_used_at'); $table->timestamp('expires_at'); }), generate secure random tokens: $token = bin2hex(random_bytes(32)), store hashed version: 'token_hash' => hash('sha256', $token), and set expiration: 'expires_at' => now()->addDays(30). Token validation flow: receive remember cookie, look up token in database, verify not expired: where('expires_at', '>', now()), check device identifier matches, validate token hash matches, create new session for user, update last_used_at: track token usage, and rotate token: generate new token after successful use. Security enhancements: one-time use tokens: delete after use forcing rotation, limited use tokens: max 100 uses then require re-authentication, geo-location validation: token bound to country/region, IP range validation: token only valid from similar IP addresses, and user agent validation: token bound to browser/device. User management interface: show active remember tokens: list all devices with active tokens, per-device information: last used date, location, device type, revoke functionality: delete specific tokens, logout all devices: delete all remember tokens forcing re-login, and notifications: email when new remember token created from unrecognized device. Implement token cleanup: scheduled job deleting expired tokens: RememberToken::where('expires_at', '<', now())->delete(), remove tokens unused for extended period: where('last_used_at', '<', now()->subMonths(3)), limit tokens per user: keep only most recent 5 tokens, and cascade deletion: on user deletion, remove associated remember tokens. Security events trigger cleanup: password change: delete all remember tokens, suspicious activity: require re-authentication invalidating remember token, account compromise: force logout deleting all tokens, and privilege escalation: administrator elevation revokes remember tokens. Token storage alternatives: encrypted cookies: store encrypted token directly in cookie, token service: centralized token management across microservices, Redis: fast token lookup for high-traffic applications, and hybrid: short token reference in cookie, full token data in database. Best practices: never store plaintext tokens: always hash before database storage, implement rate limiting: prevent token brute force, use secure random generation: cryptographically secure random_bytes(), and monitor for abuse: alert on unusual token validation patterns. Laravel integration: leverage Sanctum: Laravel Sanctum provides token-based authentication, use personal access tokens: for API authentication with remember functionality, implement token abilities: define what tokens can access, and combine with sessions: tokens for API, sessions for web interface.

6

Implement Automatic Session Extension for Active Users

Automatically extend sessions for actively engaged users while maintaining security through absolute maximums and intelligent activity detection. Activity detection patterns: client-side activity monitoring: JavaScript detecting keyboard input, mouse movement, click events, scroll events, distinguish active vs. passive: page load alone doesn't indicate activity, require meaningful interaction: form input, button clicks, navigation, and ignore automated activity: API polling, background requests, health checks. Implement client-side heartbeat: JavaScript timer checking activity: setInterval(() => { if (hasActivity()) { sendHeartbeat(); } }, 60000) sending heartbeat every minute if activity detected, include activity metadata: types of interactions, number of actions, time spent on sensitive pages, and use AJAX for heartbeat: fetch('/api/heartbeat', { method: 'POST' }) updating session without full page load. Server-side activity tracking: heartbeat endpoint extending session: public function heartbeat() { Session::put('last_activity', now()); return response()->json(['expires_at' => Session::get('expires_at')]); }, validate heartbeat authenticity: CSRF token, rate limiting, check activity legitimacy: suspicious patterns indicate bot/automated activity, and update session lifetime: extend expiration on verified activity. Implement progressive extension: first extension: full timeout extension on first activity, subsequent extensions: partial extensions reducing effectiveness over time, absolute maximum: even with constant activity, sessions expire after maximum duration (8-24 hours), and exponential backoff: extension amount decreases as session age increases. User feedback: countdown timer showing remaining time: "Session expires in 5:00", activity indication: "Your session has been extended due to activity", extension notifications: unobtrusive message confirming extension, and renewal prompt: before absolute maximum, offer explicit renewal with re-authentication. Optimize performance: batch updates: update last_activity every 5 minutes not every request, use cache: Redis/Memcached for fast activity timestamp updates reducing database load, async processing: queue session updates for non-critical paths, and lazy evaluation: defer activity check until session accessed. Intelligent activity scoring: assign weights: typing in form (high score), mouse movement (medium score), passive viewing (low score), threshold-based extension: only extend if activity score exceeds threshold, context-aware scoring: activity in sensitive areas weighted higher, and machine learning: learn user behavior patterns detecting anomalies. Security considerations: prevent manipulation: validate heartbeats aren't forged or replayed, detect suspicious patterns: heartbeats from multiple locations, unusual timing patterns, rate limiting: limit heartbeat frequency preventing DoS, and absolute session limit: regardless of activity, sessions must eventually expire. Testing: verify extension works: active user session properly extended, confirm expiration: inactive session expires correctly, test edge cases: activity exactly at expiration, concurrent requests, and performance testing: high-traffic scenarios with many heartbeat requests. Monitor extension patterns: track average session duration with/without extension, identify users with suspiciously long sessions requiring investigation, measure heartbeat effectiveness: does it reduce premature expirations, and optimize thresholds: adjust based on actual user behavior patterns.

Detect This Vulnerability in Your Code

Sourcery automatically identifies laravel cookie excessive timeout and many other security issues in your codebase.