diff --git a/ENVEXAMPLE b/ENVEXAMPLE index dbe5470c..db461f55 100644 --- a/ENVEXAMPLE +++ b/ENVEXAMPLE @@ -7,6 +7,8 @@ DB_PASSWORD=postgres # PostgreSQL password DB_HOST=postgres # Host for PostgreSQL in Docker DB_PORT=5432 # Port for PostgreSQL (default: 5432) ENCRYPTION_KEY=f4d5e6a7b8c9d0e1f23456789abcdef01234567890abcdef123456789abcdef0 # Key for encrypting sensitive data (passwords and proxies) +SESSION_SECRET=maxun_session # A strong, random string used to sign session cookies. Recommended to define your own session secret to avoid session hijacking. + MINIO_ENDPOINT=minio # MinIO endpoint in Docker MINIO_PORT=9000 # Port for MinIO (default: 9000) MINIO_CONSOLE_PORT=9001 # Web UI Port for MinIO (default: 9001) diff --git a/README.md b/README.md index a16df810..fced1ea5 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,7 @@ You can access the frontend at http://localhost:5173/ and backend at http://loca | `DB_HOST` | Yes | Host address where the Postgres database server is running. | Database connection will fail. | | `DB_PORT` | Yes | Port number used to connect to the Postgres database server. | Database connection will fail. | | `ENCRYPTION_KEY` | Yes | Key used for encrypting sensitive data (proxies, passwords). | Encryption functionality will not work. | +| `SESSION_SECRET` | No | A strong, random string used to sign session cookies | Uses default secret. Recommended to define your own session secret to avoid session hijacking. | | `MINIO_ENDPOINT` | Yes | Endpoint URL for MinIO, to store Robot Run Screenshots. | Connection to MinIO storage will fail. | | `MINIO_PORT` | Yes | Port number for MinIO service. | Connection to MinIO storage will fail. | | `MINIO_CONSOLE_PORT` | No | Port number for MinIO WebUI service. Needed for Docker setup. | Cannot access MinIO Web UI. | diff --git a/server/src/server.ts b/server/src/server.ts index 58338ff4..7f2d04d3 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -39,25 +39,34 @@ const pool = new Pool({ const PgSession = connectPgSimple(session); +interface PgStoreOptions { + pool: pg.Pool; + tableName: string; + createTableIfMissing?: boolean; + pruneSessionInterval?: number; + errorLog?: (err: Error) => void; +} + +const sessionStore = new PgSession({ + pool: pool, + tableName: 'session', + createTableIfMissing: true, + pruneSessionInterval: 15 * 60, + errorLog: (err: Error) => { + logger.log('error', `Session store error: ${err.message}`); + }, +} as PgStoreOptions); + app.use( session({ - store: new PgSession({ - pool: pool, - tableName: 'session', - createTableIfMissing: true, - pruneSessionInterval: 60 * 60, - errorLog: (err: any) => { - logger.log('error', `Session store error: ${err}`); - }, - } as any), - }), - secret: 'mx-session', - resave: false, // Do not resave the session if it hasn't changed - saveUninitialized: true, // Save new sessions + store: sessionStore, + secret: process.env.SESSION_SECRET || 'mx-session', + resave: false, + saveUninitialized: false, cookie: { - secure: false, // Set to true if using HTTPS - maxAge: 24 * 60 * 60 * 1000, // 1-day session expiration - }, + secure: process.env.NODE_ENV === 'production', + maxAge: 24 * 60 * 60 * 1000, + } }) );