Modern, secure backend for turn-based multiplayer games built with Node.js, Express, MongoDB and Socket.IO.
- About
- Features
- Tech stack
- Quick start
- API reference
- Realtime (Socket.IO)
- Project structure
- Testing & troubleshooting
- Security notes
- Contributing
- License
GameZone backend provides authentication (JWT access + refresh), OTP-based password reset via email, persistent user profiles and leaderboards, plus a Socket.IO-based realtime layer to handle multiplayer game sessions and turn logic.
- Email OTP for password reset
- JWT access + refresh tokens stored in cookies (rotated on refresh)
- Protected endpoints for profile and score updates
- Leaderboard (top 10) and user progress history
- Socket.IO matchmaking and game room management (join, move, draw, checkmate, timeouts)
- HTTPS-capable server with TLS certs
- Node.js, Express
- MongoDB (mongoose)
- Socket.IO for realtime comms
- JWT for authentication
- Mailtrap (MailtrapTransport) for dev email delivery
- Node.js 18+ and npm
- MongoDB (Atlas or local)
- (Optional) Mailtrap token for email testing
- TLS certificate files (optional for HTTPS)
Clone and install dependencies:
git clone <repo-url>
cd Game-backend
npm installCreate a .env file in the project root. Use .env.example as a template.
# MongoDB
MONGODB_URL=mongodb+srv://<user>:<pass>@cluster.mongodb.net/gamezone
# Server
PORT=3001
# JWT secrets (use secure random values)
ACCESS_TOKEN_SECRETE=your_access_secret
REFRESH_TOKEN_SECRETE=your_refresh_secret
# Mailtrap (for dev emails)
MAILTRAP_TOKEN=your_mailtrap_tokenTip: keep secrets out of source control. Add
.envto.gitignore.
Development with nodemon:
npx nodemon server.jsProduction (example with PM2):
npm run start
# or using pm2
pm install -g pm2
pm run startBase URL: http://localhost:3001/api
Authentication
-
POST
/api/auth/register— register user- Body:
{ name, email, password } - Returns: 200 on success
- Body:
-
POST
/api/auth/login— login user- Body:
{ email, password } - On success: sets cookies
accessToken(httpOnly) andjwt(refresh token)
- Body:
-
POST
/api/auth/refresh-token— rotates refresh tokens, issues a new access token -
POST
/api/auth/send-otp— send OTP to email- Body:
{ email }
- Body:
-
POST
/api/auth/verify-otp— verify OTP- Body:
{ email, otp }
- Body:
-
POST
/api/auth/reset-password— reset password- Body:
{ newPassword, email, otp }(min 8 characters)
- Body:
-
GET
/api/auth/logout— clear auth cookies
User
-
POST
/api/user/updateProfile— protected- Body:
{ _id, name, image }— updates profile
- Body:
-
GET
/api/user/getLeaderboard— returns top 10 users by score -
POST
/api/user/updateScore— protected- Body:
{ id, score }— increments user score and logs progress
- Body:
-
GET
/api/user/profile— protected- Returns: logged-in user's profile (excludes password)
Authentication middleware expects accessToken cookie. Ensure client sends cookies using credentials: 'include' (fetch) or withCredentials: true (axios).
The Socket server matches players by gameType from handshake query and manages game rooms and turn timers.
Key events:
- Client connect handshake query:
{ gameType: 'TIC', id: '<userId>' } join— payload{ board, User }→ server pairs players and emitsstartGamewhen readymove— payload{ gameId, board, symbol }→ broadcast to room, reset turn timerreset,checkMate,Draw— broadcast accordinglyopponentDisconnected,turnTimeout— notifications fired by server
Example (client):
import { io } from 'socket.io-client';
const socket = io('https://localhost:3001', {
query: { gameType: 'TIC', id: USER_ID }
});
socket.emit('join', { board: initialBoard, User });Turn timeout is 60s by default; server deletes games after a timeout event.
/ (root)
├─ server.js
├─ app.js
├─ routes/
├─ controllers/
├─ models/
├─ socket/socketManager.js
├─ config/
└─ utils/
- Use strong, unique values for JWT secrets and keep them out of source control.
- Use HTTPS in production.
- Rotate refresh tokens and validate cookie scopes.
MIT. See LICENSE for details.