Files
pinapelz_Mirage/docs/SESSION_GUIDE.md
T

5.4 KiB

Session Management Guide

This guide explains how to use the session-based authentication system implemented in the backend.

Overview

The backend now supports persistent login sessions using:

  • express-session for server-side session management
  • HTTP-only cookies for secure session storage
  • Database session tracking with automatic cleanup
  • CSRF protection through HTTP-only cookies

Environment Setup

  1. Copy .env.example to .env:
cp .env.example .env
  1. Update the SESSION_SECRET in your .env file with a secure random string:
SESSION_SECRET="your-very-secure-secret-key-change-this-in-production-make-it-long-and-random"

API Endpoints

Authentication Endpoints

Register User

  • POST /api/register
  • Body: { username, password, name, email }
  • Response: User data + session created
  • Sets: HTTP-only session cookie

Login

  • POST /api/authenticate
  • Body: { username, password }
  • Response: User data + session created
  • Sets: HTTP-only session cookie

Logout

  • POST /api/logout
  • Requires: Valid session
  • Response: Success message
  • Clears: Session cookie and database sessions

Session Management

Check Session Status

  • GET /api/session
  • Response: { authenticated: boolean, user?: UserData }
  • Use: Check if user is still logged in

Get Current User

  • GET /api/me
  • Requires: Valid session
  • Response: Current user data

Frontend Integration

Making Authenticated Requests

Always include credentials in your fetch requests:

// Example fetch with credentials
const response = await fetch('http://localhost:5000/api/me', {
  method: 'GET',
  credentials: 'include', // This is crucial!
  headers: {
    'Content-Type': 'application/json',
  }
});

Login Flow Example

// Login
const loginResponse = await fetch('http://localhost:5000/api/authenticate', {
  method: 'POST',
  credentials: 'include',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    username: 'user@example.com',
    password: 'password123'
  })
});

if (loginResponse.ok) {
  const userData = await loginResponse.json();
  console.log('Logged in:', userData);
  // Session cookie is automatically set
}

Check Authentication Status

// Check if user is still logged in
const sessionResponse = await fetch('http://localhost:5000/api/session', {
  method: 'GET',
  credentials: 'include'
});

const sessionData = await sessionResponse.json();
if (sessionData.authenticated) {
  console.log('User is logged in:', sessionData.user);
} else {
  console.log('User is not logged in');
}

Logout

// Logout
const logoutResponse = await fetch('http://localhost:5000/api/logout', {
  method: 'POST',
  credentials: 'include'
});

if (logoutResponse.ok) {
  console.log('Logged out successfully');
  // Session cookie is automatically cleared
}

Security Features

Session Security

  • HTTP-only cookies: Prevents XSS attacks
  • Secure cookies: Enabled in production (HTTPS)
  • SameSite protection: Prevents CSRF attacks
  • Session expiration: 24-hour automatic expiry

Database Sessions

  • Sessions are stored in the database for server-side validation
  • Expired sessions are automatically cleaned up every hour
  • User logout removes all sessions for that user

Password Security

  • Passwords are hashed with bcrypt (12 rounds)
  • Unique salt per user for additional security
  • Original password never stored

Middleware

requireAuth Middleware

Protects routes that need authentication:

app.get('/api/protected-route', requireAuth, (req, res) => {
  // req.user contains the authenticated user data
  const user = req.user;
  res.json({ message: 'This is protected', user });
});

Production Considerations

Environment Variables

SESSION_SECRET="your-production-secret-minimum-32-characters-long"
NODE_ENV="production"
FRONTEND_URL="https://yourdomain.com"

Security Settings

In production, ensure:

  1. SESSION_SECRET is a strong, unique string
  2. secure: true in cookie settings (HTTPS only)
  3. Proper CORS origin configuration
  4. HTTPS enabled for your domain

Database

  • Consider using PostgreSQL or MySQL instead of SQLite
  • Implement database connection pooling
  • Set up database backups

Troubleshooting

Common Issues

  1. Session not persisting: Make sure credentials: 'include' is set in frontend requests
  2. CORS errors: Verify CORS origin matches your frontend URL
  3. Session expires immediately: Check system time and session expiration settings
  4. Authentication fails after server restart: Sessions are stored in database, so they should persist

Debug Session Issues

Check session status:

fetch('http://localhost:5000/api/session', {
  credentials: 'include'
}).then(r => r.json()).then(console.log);

Clear All Sessions

If you need to force logout all users:

DELETE FROM Session;

Database Schema

The session system adds a Session table:

model Session {
  id        String   @id @default(cuid())
  userId    Int
  user      User     @relation(fields: [userId], references: [id], onDelete: Cascade)
  createdAt DateTime @default(now())
  expiresAt DateTime
}

Sessions are automatically linked to users and cleaned up when users are deleted.