Repository navigation
Session Management
- Introduction
- Project Structure
- Core Components
- Architecture Overview
- Detailed Component Analysis
- Dependency Analysis
- Performance Considerations
- Troubleshooting Guide
- Conclusion
This document explains the session management system used by the backend server. It covers how sessions are configured, stored, and integrated with authentication flows, including the current in-memory store, WebSocket authentication, and the separation between server-side sessions and Firebase client-side authentication. It also outlines security considerations, lifecycle management, invalidation strategies, and scaling implications for distributed deployments.
The session management spans several server modules:
- Express session initialization and middleware configuration
- Storage abstraction that exposes a session store
- Route handlers that set session data upon login and destroy sessions on logout
- Middleware enforcing authentication and roles
- WebSocket server authenticating via session store
- Client-side Firebase authentication (independent from server sessions)
graph TB
Client["Client App"] --> Express["Express Server"]
Express --> Session["Express Session Middleware"]
Session --> Store["Session Store (MemoryStore)"]
Express --> Routes["Route Handlers"]
Express --> WS["WebSocket Server"]
WS --> WSAuth["WS Session Auth"]
Routes --> Storage["MongoStorage (exposes sessionStore)"]
Storage --> Store
Diagram sources
- index.ts
- storage.ts
- routes.ts
- chat-ws.ts
Section sources
- index.ts
- storage.ts
- Express session configuration: Secret, cookie security, max age, and store binding
- Session store: In-memory store via MemoryStore
- Route handlers: Login sets session data; Logout destroys session
- Middleware: Authentication and role checks
- WebSocket authentication: Extracts session from cookie and validates via store
- Client-side Firebase auth: Independent of server sessions
Section sources
- index.ts
- storage.ts
- routes.ts
- middleware.ts
- chat-ws.ts
- express-session.d.ts
The session lifecycle integrates with HTTP routes and WebSockets:
- On login, the server sets session fields (userId, role) and sends a signed session cookie
- Subsequent requests carry the cookie; the server validates via the session store
- WebSocket connections authenticate using the same session store by parsing the cookie
- On logout, the server destroys the session, invalidating the cookie
sequenceDiagram
participant C as "Client"
participant S as "Express Server"
participant R as "Routes"
participant St as "Session Store"
participant W as "WebSocket Server"
C->>R : "POST /api/auth/login"
R->>St : "Set session fields (userId, role)"
R-->>C : "200 OK with session cookie"
C->>S : "Subsequent requests with cookie"
S->>St : "Lookup session by ID"
St-->>S : "Session data"
S-->>C : "200 OK"
C->>W : "Connect WebSocket with cookie"
W->>St : "Lookup session by parsed cookie"
St-->>W : "Session data"
W-->>C : "Connected"
Diagram sources
- routes.ts
- index.ts
- chat-ws.ts
- Secret: Required in production; defaults in development
- Cookie security: Secure flag enabled in production
- Max age: 24 hours
- Store: Bound to MongoStorage.sessionStore (currently MemoryStore)
Operational notes:
- The store is initialized with periodic pruning to clean expired entries
- The store is exposed via the storage singleton and attached to the Express app
Section sources
- index.ts
- storage.ts
- .env.example
- Current implementation: MemoryStore with periodic pruning
- Interface contract: Implements express-session Store interface
- Exposed via MongoStorage for binding to Express and WebSocket servers
Important observations:
- MemoryStore is local to the process and not suitable for multi-instance deployments
- There is no explicit TTL configuration in the current setup
Section sources
- storage.ts
- Login: Route handler sets req.session fields and returns user data
- Access: isAuthenticated middleware checks req.session.userId
- Logout: Route handler destroys the session
flowchart TD
Start(["Request Received"]) --> CheckAuth["Check isAuthenticated middleware"]
CheckAuth --> AuthOK{"Has userId?"}
AuthOK --> |No| Deny["401 Unauthorized"]
AuthOK --> |Yes| Proceed["Proceed to route handler"]
Proceed --> RouteLogic["Route logic (e.g., get user/me)"]
RouteLogic --> End(["Response Sent"])
subgraph "Logout Path"
LStart(["Logout Request"]) --> Destroy["Destroy session"]
Destroy --> LEnd(["200 OK"])
end
Diagram sources
- middleware.ts
- routes.ts
- routes.ts
Section sources
- routes.ts
- middleware.ts
- Parses the "connect.sid" cookie from the HTTP upgrade request
- Decodes the session ID and retrieves session data from the store
- Rejects unauthorized connections and closes them
sequenceDiagram
participant C as "Client WS"
participant W as "WS Server"
participant St as "Session Store"
C->>W : "Upgrade request with Cookie"
W->>W : "Parse 'connect.sid'"
W->>St : "get(sid)"
St-->>W : "Session {userId, role}"
alt "Valid session"
W-->>C : "Accept connection"
else "Invalid session"
W-->>C : "Close with error"
end
Diagram sources
- chat-ws.ts
Section sources
- chat-ws.ts
- Session fields include userId, username, role, email
- These are set during login and used for authorization checks
Section sources
- express-session.d.ts
- routes.ts
- MongoDB connection is established early in startup
- The current session store is MemoryStore; there is no explicit connect-mongo integration
- MongoDB is used for application data (not session persistence)
Section sources
- db.ts
- storage.ts
- Client initializes Firebase and manages auth state independently
- Login/registration flows write user profile to Firestore
- This is separate from server-side sessions; routes explicitly note reliance on Firebase for AI chat
Section sources
- firebase.ts
- firebase.ts
- firebase-auth-context.tsx
- routes.ts
- Express app depends on session middleware and MongoStorage.sessionStore
- Routes depend on session data for authorization
- WebSocket server depends on the same session store for authentication
- Client-side Firebase auth is independent of server sessions
graph LR
Express["Express App"] --> SessionMW["Session Middleware"]
Express --> Routes["Routes"]
Express --> WS["WebSocket Server"]
Routes --> Storage["MongoStorage"]
WS --> Storage
Storage --> Store["MemoryStore"]
Diagram sources
- index.ts
- storage.ts
- routes.ts
- chat-ws.ts
Section sources
- index.ts
- storage.ts
- routes.ts
- chat-ws.ts
- MemoryStore is efficient for single-instance deployments but does not scale across multiple nodes
- Periodic pruning reduces memory pressure but does not eliminate the need for a distributed store in clustered environments
- WebSocket authentication performs a synchronous store lookup per connection; ensure store latency is acceptable
[No sources needed since this section provides general guidance]
Common issues and remedies:
- Missing SESSION_SECRET in production: The server throws an error at startup
- Session not found during WebSocket auth: Verify the cookie is present and valid; ensure the session store is reachable
- Logout does not invalidate session: Confirm the session is destroyed and the client clears any cached state
Section sources
- index.ts
- routes.ts
- chat-ws.ts
The current session management uses an in-memory store bound to Express and consumed by HTTP routes and WebSocket connections. While functional for single-instance deployments, it requires migration to a distributed session store (such as connect-mongo with MongoDB) for horizontal scaling. Client-side Firebase authentication operates independently and complements server-side sessions where needed. Security enhancements should include robust secret management, secure cookies, and consideration of session hijacking prevention strategies.