385 lines
11 KiB
Markdown
385 lines
11 KiB
Markdown
# Session Expiration Analysis
|
||
**Date:** 2026-01-12
|
||
**Issue:** Session did not expire after over 1 day (user 161, organization 1)
|
||
**Status:** ⚠️ **WORKING AS DESIGNED** (but needs review)
|
||
|
||
---
|
||
|
||
## Issue Summary
|
||
|
||
User reported remaining logged in for over 1 day without session expiration. After investigation, this is **working as intended** due to the "Remember Me" functionality.
|
||
|
||
---
|
||
|
||
## Root Cause Analysis
|
||
|
||
### 1. Session Configuration
|
||
|
||
**File:** `config/session.php`
|
||
|
||
```php
|
||
'lifetime' => env('SESSION_LIFETIME', 480), // Default: 480 minutes (8 hours)
|
||
'expire_on_close' => false,
|
||
```
|
||
|
||
**Environment:** `.env`
|
||
```
|
||
SESSION_LIFETIME=120 // 2 hours
|
||
```
|
||
|
||
**Expected Behavior:** Sessions should expire after 120 minutes (2 hours) of inactivity.
|
||
|
||
### 2. Remember Me Functionality
|
||
|
||
**File:** `resources/views/auth/login.blade.php` (line ~X)
|
||
|
||
```blade
|
||
<label for="remember_me" class="flex items-center">
|
||
<x-jetstream.checkbox id="remember_me" name="remember" />
|
||
{{ __('Remember me for :period', ['period' => daysToHumanReadable(timebank_config('auth.remember_me_days', 90))]) }}
|
||
```
|
||
|
||
**Configuration:** `config/timebank_cc.php` and `config/timebank-default.php`
|
||
|
||
```php
|
||
'remember_me_days' => 90, // Number of days the "Remember me" checkbox will keep users logged in
|
||
```
|
||
|
||
**Duration:** 90 days = **129,600 minutes** (60 × 24 × 90)
|
||
|
||
### 3. How Remember Me Works
|
||
|
||
When a user checks "Remember me" during login:
|
||
|
||
1. Laravel creates a `remember_token` in the user's database record
|
||
2. A cookie is set with this token lasting 90 days
|
||
3. Even if the session expires (after 2 hours), the remember token keeps the user logged in
|
||
4. The user remains authenticated for the full 90-day period
|
||
|
||
**This is standard Laravel behavior** and is working as designed.
|
||
|
||
---
|
||
|
||
## Current Configuration Summary
|
||
|
||
| Setting | Value | Duration | Purpose |
|
||
|---------|-------|----------|---------|
|
||
| `SESSION_LIFETIME` | 120 | 2 hours | Session expires after 2 hours of inactivity |
|
||
| `remember_me_days` | 90 | 90 days | Remember Me cookie duration |
|
||
| `password_timeout` | 10800 | 3 hours | Password confirmation timeout |
|
||
| `expire_on_close` | false | - | Session persists after browser close |
|
||
|
||
---
|
||
|
||
## Security Implications
|
||
|
||
### ✅ Current Security Measures
|
||
|
||
1. **Session Encryption:** `SESSION_ENCRYPT=true`
|
||
2. **HTTP Only Cookies:** `http_only => true` (prevents JavaScript access)
|
||
3. **Secure Cookies:** `secure => env('SESSION_SECURE_COOKIE')` (HTTPS only)
|
||
4. **Same-Site Policy:** `same_site => 'lax'` (CSRF protection)
|
||
5. **Database Sessions:** Stored in database, not filesystem
|
||
6. **IP Tracking:** Last login IP stored for security monitoring
|
||
|
||
### ⚠️ Potential Security Concerns
|
||
|
||
1. **Long Remember Duration (90 days)**
|
||
- If a device is lost/stolen, attacker has 90-day access
|
||
- User may forget they're logged in on shared computers
|
||
- No mechanism to revoke all remember tokens globally
|
||
|
||
2. **No Idle Timeout for Remember Me**
|
||
- Regular sessions expire after 2 hours of inactivity
|
||
- Remember Me bypasses this completely
|
||
- User could be inactive for 89 days and still be logged in on day 90
|
||
|
||
3. **Profile Switching Session Variables**
|
||
- When switching to organization profile, session variables stored:
|
||
- `activeProfileType`
|
||
- `activeProfileId`
|
||
- `active_guard`
|
||
- These persist for the remember token duration (90 days)
|
||
- No separate timeout for elevated guard sessions
|
||
|
||
4. **Shared Computer Risk**
|
||
- User logs in on public computer with "Remember Me" checked
|
||
- Forgets to log out
|
||
- Next person has 90-day access to that account
|
||
|
||
---
|
||
|
||
## Privacy Policy Implications
|
||
|
||
The current privacy policy states:
|
||
|
||
> **File:** `references/gdpr/timebank_cc/2026-01-01/privacy-policy-FULL-en.md`
|
||
>
|
||
> Section 9. Security
|
||
> - "2-hour session timeouts"
|
||
|
||
**Issue:** This is **misleading** because:
|
||
- Sessions timeout after 2 hours of inactivity (correct)
|
||
- **BUT** Remember Me keeps users logged in for 90 days (not mentioned)
|
||
- Users may think they're protected by 2-hour timeout when they're not
|
||
|
||
---
|
||
|
||
## Recommendations
|
||
|
||
### Option 1: Reduce Remember Me Duration ⭐ **RECOMMENDED**
|
||
|
||
**Change remember_me_days from 90 to 14 or 30 days**
|
||
|
||
**Pros:**
|
||
- Still convenient for users
|
||
- Significantly reduces risk window
|
||
- Industry standard (many sites use 14-30 days)
|
||
|
||
**Implementation:**
|
||
```php
|
||
// config/timebank_cc.php
|
||
'remember_me_days' => 14, // Reduced from 90 to 14 days
|
||
```
|
||
|
||
### Option 2: Add Idle Timeout for Remember Me
|
||
|
||
**Implement additional check for last activity**
|
||
|
||
**Pros:**
|
||
- Remember Me users still logout after extended inactivity
|
||
- Combines convenience with security
|
||
|
||
**Implementation:**
|
||
- Add middleware to check last activity timestamp
|
||
- If last activity > X days ago (e.g., 7 days), force re-authentication
|
||
- Update remember token on each login to track last activity
|
||
|
||
**Example Middleware Logic:**
|
||
```php
|
||
// Check if user hasn't been active in 7 days
|
||
if (Auth::user()->last_activity_at < now()->subDays(7)) {
|
||
Auth::logout();
|
||
return redirect()->route('login')->with('message', 'Session expired due to inactivity');
|
||
}
|
||
```
|
||
|
||
### Option 3: Separate Session Lifetime for Elevated Guards
|
||
|
||
**Different timeouts for regular vs elevated sessions**
|
||
|
||
**Configuration:**
|
||
```php
|
||
'auth' => [
|
||
'remember_me_days' => 14, // Regular user sessions
|
||
'elevated_session_lifetime' => 60, // 1 hour for bank/admin/org profiles
|
||
],
|
||
```
|
||
|
||
**Pros:**
|
||
- Organizations/Banks/Admins have shorter session lifetime
|
||
- Regular users maintain convenience
|
||
- Better security for privileged accounts
|
||
|
||
### Option 4: Update Privacy Policy ⭐ **REQUIRED**
|
||
|
||
**Add disclosure about Remember Me functionality**
|
||
|
||
**Add to Section 9 (Security):**
|
||
```markdown
|
||
## Session Security
|
||
- Regular sessions expire after 2 hours of inactivity
|
||
- "Remember Me" feature (optional) keeps you logged in for 90 days
|
||
- Use only on trusted personal devices
|
||
- Always log out on shared or public computers
|
||
- You can revoke access by logging out from your account settings
|
||
```
|
||
|
||
**Add to Section 3.4 (Technical Data):**
|
||
```markdown
|
||
- **Authentication tokens** (for "Remember Me" feature)
|
||
- Optional remember me token (stored for 90 days if enabled)
|
||
- Automatically deleted when you log out or token expires
|
||
```
|
||
|
||
### Option 5: Add "Trusted Device" Management
|
||
|
||
**Allow users to view and revoke remember tokens**
|
||
|
||
**Features:**
|
||
- Show list of devices where user is "remembered"
|
||
- Display: Device type, IP address, last activity, location
|
||
- "Revoke access" button to delete remember token
|
||
- "Log out all devices" option
|
||
|
||
**Implementation:**
|
||
```php
|
||
// User can revoke specific device
|
||
User::find($userId)->remember_tokens()->where('id', $tokenId)->delete();
|
||
|
||
// User can revoke all devices
|
||
User::find($userId)->remember_tokens()->delete();
|
||
```
|
||
|
||
---
|
||
|
||
## Comparison with Industry Standards
|
||
|
||
| Service | Remember Me Duration | Session Timeout |
|
||
|---------|---------------------|-----------------|
|
||
| **Timebank.cc (current)** | 90 days | 2 hours |
|
||
| GitHub | 30 days | 2 weeks (idle) |
|
||
| Google | "Forever" (until revoked) | Variable |
|
||
| Facebook | 90 days | 30 days (idle) |
|
||
| Banking sites | Not offered | 5-15 minutes |
|
||
| AWS Console | 12 hours | 12 hours |
|
||
|
||
**Analysis:** 90 days is on the longer side but not unprecedented. However, for a financial platform (time banking involves transactions), this may be too long.
|
||
|
||
---
|
||
|
||
## Immediate Actions Required
|
||
|
||
### 1. ✅ Document Current Behavior
|
||
- [x] Analyze session configuration
|
||
- [x] Identify remember me functionality
|
||
- [x] Document security implications
|
||
|
||
### 2. ⚠️ Update Privacy Policy **URGENT**
|
||
- [ ] Add Remember Me disclosure to Section 9 (Security)
|
||
- [ ] Add authentication tokens to Section 3.4 (Technical Data)
|
||
- [ ] Update all language versions (EN, NL, DE, FR, ES)
|
||
|
||
### 3. 🔍 Security Review **RECOMMENDED**
|
||
- [ ] Assess if 90 days is appropriate for timebank platform
|
||
- [ ] Consider reducing to 14-30 days
|
||
- [ ] Evaluate implementing idle timeout for remember me
|
||
- [ ] Consider separate timeouts for elevated guards (org/bank/admin)
|
||
|
||
### 4. 🛠️ Feature Enhancements **OPTIONAL**
|
||
- [ ] Add "Trusted Devices" management page
|
||
- [ ] Show active sessions with revoke capability
|
||
- [ ] Add "Log out all devices" option
|
||
- [ ] Display warning on login page about Remember Me duration
|
||
|
||
---
|
||
|
||
## Testing Checklist
|
||
|
||
To verify session behavior:
|
||
|
||
### Test 1: Regular Session (No Remember Me)
|
||
```bash
|
||
# 1. Log in without checking "Remember Me"
|
||
# 2. Wait 2 hours (or set SESSION_LIFETIME=1 for testing)
|
||
# 3. Refresh page
|
||
# Expected: User is logged out
|
||
```
|
||
|
||
### Test 2: Remember Me Session
|
||
```bash
|
||
# 1. Log in WITH "Remember Me" checked
|
||
# 2. Close browser completely
|
||
# 3. Reopen browser and visit site
|
||
# Expected: User still logged in
|
||
# 4. Check database for remember_token in users table
|
||
```
|
||
|
||
### Test 3: Profile Switch Persistence
|
||
```bash
|
||
# 1. Log in as user 161 with Remember Me
|
||
# 2. Switch to organization profile 1
|
||
# 3. Close browser
|
||
# 4. Reopen browser
|
||
# Expected: Still logged in as organization 1
|
||
```
|
||
|
||
### Test 4: Token Expiration
|
||
```bash
|
||
# 1. Log in with Remember Me
|
||
# 2. Wait 90 days (or modify remember_me_days for testing)
|
||
# 3. Try to access site
|
||
# Expected: User is logged out, prompted to login
|
||
```
|
||
|
||
---
|
||
|
||
## Proposed Configuration Changes
|
||
|
||
### Recommended New Values
|
||
|
||
**File:** `config/timebank_cc.php`
|
||
|
||
```php
|
||
'auth' => [
|
||
// Reduced from 90 to 14 days for better security
|
||
'remember_me_days' => 14,
|
||
|
||
// NEW: Maximum idle time for remember me (7 days)
|
||
'remember_me_max_idle_days' => 7,
|
||
|
||
// NEW: Separate timeout for elevated guards (1 hour)
|
||
'elevated_guard_timeout' => 60,
|
||
],
|
||
```
|
||
|
||
**File:** `.env`
|
||
|
||
```
|
||
# Regular session timeout (unchanged)
|
||
SESSION_LIFETIME=120
|
||
|
||
# NEW: Force re-authentication for sensitive operations
|
||
PASSWORD_CONFIRMATION_TIMEOUT=900
|
||
```
|
||
|
||
---
|
||
|
||
## Database Schema for Trusted Devices (Optional Enhancement)
|
||
|
||
```sql
|
||
CREATE TABLE trusted_devices (
|
||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||
user_id BIGINT UNSIGNED NOT NULL,
|
||
device_name VARCHAR(255),
|
||
ip_address VARCHAR(45),
|
||
user_agent TEXT,
|
||
remember_token VARCHAR(100) NOT NULL,
|
||
last_activity_at TIMESTAMP NULL,
|
||
expires_at TIMESTAMP NULL,
|
||
created_at TIMESTAMP NULL,
|
||
updated_at TIMESTAMP NULL,
|
||
|
||
INDEX idx_user_id (user_id),
|
||
INDEX idx_remember_token (remember_token),
|
||
INDEX idx_expires_at (expires_at),
|
||
|
||
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
||
);
|
||
```
|
||
|
||
---
|
||
|
||
## Conclusion
|
||
|
||
**The session not expiring is WORKING AS DESIGNED** due to the Remember Me functionality. However, this behavior:
|
||
|
||
1. ⚠️ **Not clearly communicated** to users in privacy policy
|
||
2. ⚠️ **May be too permissive** for a financial platform (90 days is long)
|
||
3. ⚠️ **Lacks advanced controls** (no device management, no idle timeout)
|
||
|
||
### Recommended Next Steps (Priority Order)
|
||
|
||
1. **HIGH PRIORITY:** Update privacy policy to disclose Remember Me behavior
|
||
2. **MEDIUM PRIORITY:** Reduce `remember_me_days` from 90 to 14-30 days
|
||
3. **MEDIUM PRIORITY:** Implement idle timeout for remember me sessions
|
||
4. **LOW PRIORITY:** Add trusted device management page
|
||
5. **LOW PRIORITY:** Separate session lifetimes for elevated guards
|
||
|
||
---
|
||
|
||
**Report Generated:** 2026-01-12
|
||
**Issue Status:** Working as designed (requires policy update)
|
||
**Security Risk:** Medium (long remember me duration)
|
||
**Action Required:** Update privacy policy + consider reducing remember me duration
|