1. Enforce HTTPS
If you're deploying your app, make sure your backend only allows HTTPS requests.
โ In Next.js, you don't need to configure HTTPS manually if you're using Vercel or Docker with Nginx, but in custom servers:
- Redirect HTTP to HTTPS:
if (process.env.NODE_ENV === "production") {
server.use((req, res, next) => {
if (req.headers["x-forwarded-proto"] !== "https") {
return res.redirect(`https://${req.headers.host}${req.url}`);
}
next();
});
}
2. HTTP Security Headers
Install the helmet
package to set security headers automatically.
npm install helmet
Configure it in middleware.ts:
import { NextRequest, NextResponse } from "next/server";
import helmet from "helmet";
export async function middleware(req: NextRequest) {
const headers = new Headers(req.headers);
headers.set("X-Frame-Options", "DENY");
headers.set("X-Content-Type-Options", "nosniff");
headers.set("Referrer-Policy", "no-referrer");
headers.set("Strict-Transport-Security", "max-age=63072000; includeSubDomains; preload");
headers.set("Content-Security-Policy", "default-src 'self'; img-src 'self' data:;");
const response = NextResponse.next();
response.headers = headers;
return response;
}
3. JWT Authentication
Install jsonwebtoken
for token generation and validation:
npm install jsonwebtoken
Usage:
import jwt from "jsonwebtoken";
const secret = process.env.JWT_SECRET!;
export const createToken = (user) => {
return jwt.sign({ id: user.id }, secret, { expiresIn: "1h" });
};
export const verifyToken = (token) => {
try {
return jwt.verify(token, secret);
} catch (err) {
return null;
}
};
4. Rate Limiting
To prevent brute force or DoS attacks, install express-rate-limit
:
npm install express-rate-limit
Configure it:
import rateLimit from "express-rate-limit";
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per window
message: "Too many requests, please try again later.",
});
app.use(limiter);
5. CORS Configuration
Allow specific domains only:
npm install cors
Setup:
import cors from "cors";
const corsOptions = {
origin: ["https://your-frontend.com"],
methods: ["GET", "POST"],
credentials: true,
};
app.use(cors(corsOptions));
6. Environment Variables Protection
โ
Never expose sensitive environment variables publicly.
Use .env.local
for local development:
JWT_SECRET=your-secret-key
API_KEY=your-api-key
7. Validation & Sanitization
Use express-validator
to validate inputs:
npm install express-validator
Example:
import { body, validationResult } from "express-validator";
app.post("/api/register",
body("email").isEmail(),
body("password").isLength({ min: 6 }),
(req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
// Continue with registration...
});
8. Error Handling
Centralize error responses:
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json({ message: "Internal Server Error" });
});
9. Logging Suspicious Activity
Use winston
or pino
for secure logging:
npm install pino
Example:
import pino from "pino";
const logger = pino();
logger.info("User signed up");
logger.error("Unauthorized access attempt");
๐ Bonus Tips:
Feature | Package | Purpose |
Dependency Security | npm audit | Scan dependencies for vulnerabilities |
Helmet | helmet | Security headers |
bcrypt | bcrypt | Password hashing |
Express-rate-limit | express-rate-limit | Prevent DoS attacks |
Final Folder Structure:
โโ src
โ โโ middleware.ts
โ โโ api
โ โ โโ auth.ts
โ โโ utils
โ โ โโ jwt.ts
โ โ โโ logger.ts
โ โโ app.ts
โโ .env.local
๐ฏ Conclusion
With these practices, your proxy backend will be resistant to:
XSS
SQL Injection
CSRF
Brute Force Attacks
DoS