A secure Node.js proxy server that validates and forwards client requests to external services. It operates as a middleware layer, implementing security controls such as input validation, rate limiting, CORS enforcement, and TLS-based data transmission to ensure integrity and confidentiality across applications.
- Secure Image Upload Proxy: Handles multipart/form-data image uploads with signature verification
- Cryptographic Security: HMAC-SHA256 signature validation for all incoming requests
- Rate Limiting: Configurable rate limiting to prevent abuse (10 requests per minute per IP)
- CORS Protection: Whitelist-based CORS configuration for secure cross-origin requests
- Request Logging: Comprehensive logging of all incoming requests
- Error Handling: Centralized error handling with appropriate HTTP status codes
- Environment Configuration: Secure environment-based configuration management
- Node.js (v18 or higher)
- npm or yarn package manager
- Clone the repository:
git clone https://github.com/jakariyaa/nodejs-backend-proxy.git
cd nodejs-backend-proxy- Install dependencies:
npm install- Create a
.envfile in the root directory:
# Server Configuration
PORT=3000
# Security Configuration
CRYPTO_SHARED_SECRET=your-secure-shared-secret-key
# Add Other External Webhook ConfigurationsThe server is pre-configured to accept requests from:
*.jakariya.eu.org(all subdomains)
http://localhost:3000
GET /
Returns a welcome message to confirm the server is running.
x-signature: HMAC-SHA256 signature of the meta data (required)
meta: JSON string containing metadata (required)image: Image file (required)
curl -X POST http://localhost:3000/proxy/calscan/sendData \
-H "x-signature: your-hmac-signature" \
-F "meta={\"key\":\"value\"}" \
-F "image=@/path/to/image.jpg"- 200 OK: Successfully forwarded to webhook
- 400 Bad Request: Missing required fields
- 401 Unauthorized: Invalid signature
- 429 Too Many Requests: Rate limit exceeded
- 500 Internal Server Error: Server error
All requests must include a valid HMAC-SHA256 signature in the x-signature header. The signature is calculated using the shared secret and the meta data string.
- Window: 60 seconds
- Max Requests: 10 per IP address
- Message: "Too many requests from this IP, please try again after an hour"
Strict CORS policy prevents unauthorized cross-origin requests. Only whitelisted domains are allowed.
nodejs-backend-proxy/
βββ app/
β βββ configs/
β β βββ env.js # Environment configuration
β βββ controllers/
β β βββ calscan.controller.js # Main business logic
β βββ middlewares/
β β βββ error-handler.js # Global error handling
β β βββ logger.js # Request logging
β β βββ rate-limiter.js # Rate limiting configuration
β βββ routes/
β βββ calscan.routes.js # Route definitions
βββ server.js # Express server setup
βββ package.json # Dependencies and scripts
βββ .env # Environment variables (not in repo)
βββ .gitignore # Git ignore rules
npm run devThis starts the server with file watching enabled.
npm start- Start the server:
npm run dev - Send a test request using curl or Postman
- Verify the signature is correctly calculated
- Check the webhook receives the forwarded data
const crypto = require("crypto");
const metaString = JSON.stringify({ key: "value" });
const signature = crypto
.createHmac("sha256", process.env.CRYPTO_SHARED_SECRET)
.update(metaString)
.digest("hex");This project is configured for Vercel deployment. The .vercel directory is ignored in git.
Create a Dockerfile:
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["npm", "start"]The server includes built-in request logging. All requests are logged with:
- HTTP method
- Request URL
- Request body (if present)
-
"Invalid signature" error
- Verify the shared secret matches between client and server
- Ensure the meta string is exactly the same when generating the signature
-
CORS errors
- Check if your domain is whitelisted in the CORS configuration
- Verify the origin header is being sent correctly
-
Rate limiting
- Check if you're exceeding 10 requests per minute
- The limit resets every 60 seconds
- Fork the repository
- Create a feature branch:
git checkout -b feature-name - Make your changes
- Add tests if applicable
- Commit your changes:
git commit -m 'Add feature' - Push to the branch:
git push origin feature-name - Submit a pull request
This project is licensed under the MIT License - see the LICENSE file for details.
For support, please open an issue in the GitHub repository or contact the development team.