If you have a JSON file hosted on a public endpoint, like https://quiz-host/questions.json
, securing it so only you can access it is crucial to prevent unauthorized access. Below, we discuss how to secure your JSON file using various methods, including JWT (JSON Web Tokens), Signed URLs, and other techniques.
Why Secure a JSON File?
A publicly accessible JSON file can expose sensitive information or allow misuse of your resources. Implementing security measures ensures:
- Authorized Access: Only you or trusted clients can access the file.
- Data Protection: Prevents exposure of sensitive information.
- Resource Control: Stops misuse of your bandwidth or server resources.
How Can You Secure the JSON File?
There are several methods to secure your JSON file, even without requiring a login process. Let’s explore them:
1. Using JWT Without Login
JSON Web Tokens (JWT) allow you to authenticate requests using a pre-generated token. Here’s how you can use JWT to secure your JSON file:
- Pre-generate a Token:
Generate a JWT token using a secret key and distribute it securely to your client.Example:const jwt = require("jsonwebtoken"); const SECRET_KEY = "your-secure-secret-key"; const token = jwt.sign({ access: "allowed" }, SECRET_KEY, { expiresIn: "1d" }); console.log("Use this token:", token);
- Validate the Token:
On your server, validate the JWT token before serving the JSON file.Example:const express = require("express"); const jwt = require("jsonwebtoken"); const fs = require("fs"); const SECRET_KEY = "your-secure-secret-key"; const app = express(); // Middleware to validate the token function authenticateToken(req, res, next) { const authHeader = req.headers["authorization"]; const token = authHeader && authHeader.split(" ")[1]; if (!token) return res.sendStatus(401); // No token provided jwt.verify(token, SECRET_KEY, (err) => { if (err) return res.sendStatus(403); // Invalid token next(); }); } // Secure route to serve JSON app.get("/secure-questions", authenticateToken, (req, res) => { const questions = fs.readFileSync("./questions.json"); res.json(JSON.parse(questions)); }); app.listen(3000, () => console.log("Server running on port 3000"));
- Access the JSON File:
Use the pre-shared token in theAuthorization
header when making requests.
2. Using Signed URLs
A signed URL grants time-limited access to your JSON file. Once the URL expires, it becomes invalid.
How It Works:
- Generate a Signed URL:
Use a secret key to create a hash signature that includes an expiration timestamp.Example:const crypto = require("crypto"); const SECRET_KEY = "your-secure-secret-key"; const url = "/secure/questions.json"; const expirationTime = Math.floor(Date.now() / 1000) + 60; // Expires in 60 seconds const signature = crypto .createHmac("sha256", SECRET_KEY) .update(`${url}${expirationTime}`) .digest("hex"); const signedUrl = `${url}?expires=${expirationTime}&signature=${signature}`; console.log("Signed URL:", signedUrl);
- Validate the URL on the Server:
Before serving the JSON file, validate the signature and expiration timestamp.Example:app.get("/secure/questions.json", (req, res) => { const { expires, signature } = req.query; // Check expiration if (Date.now() / 1000 > expires) { return res.status(403).send("URL expired"); } // Verify the signature const expectedSignature = crypto .createHmac("sha256", SECRET_KEY) .update(`/secure/questions.json${expires}`) .digest("hex"); if (signature !== expectedSignature) { return res.status(403).send("Invalid signature"); } res.sendFile(__dirname + "/questions.json"); });
3. Restricting by IP Address
If your JSON file should only be accessed from specific IPs, you can use IP whitelisting.
How It Works:
- Maintain a list of allowed IPs:
const WHITELISTED_IPS = ["123.456.78.90", "111.222.333.444"];
- Validate the IP Address:
app.use((req, res, next) => { const clientIp = req.ip || req.connection.remoteAddress; if (!WHITELISTED_IPS.includes(clientIp)) { return res.status(403).send("Access denied"); } next(); }); app.get("/secure-questions", (req, res) => { const questions = fs.readFileSync("./questions.json"); res.json(JSON.parse(questions)); });
4. Enforcing CORS Restrictions
If your JSON file is accessed via APIs, restrict cross-origin requests to only trusted domains using CORS.
How It Works:
- Allow requests from specific origins:
const cors = require("cors"); const allowedOrigins = ["https://your-allowed-site.com"]; app.use(cors({ origin: (origin, callback) => { if (!origin || allowedOrigins.includes(origin)) { callback(null, true); } else { callback(new Error("Not allowed by CORS")); } } }));
- Serve the JSON file:
app.get("/secure-questions", (req, res) => { const questions = fs.readFileSync("./questions.json"); res.json(JSON.parse(questions)); });
Best Method for Your Use Case
- JWT without Login: Best if you want pre-shared tokens for secure access.
- Signed URLs: Ideal for temporary, time-bound access.
- IP Whitelisting: Suitable for access from specific devices or locations.
- CORS Restrictions: Useful when integrating with specific websites or applications.
Securing your JSON file ensures only authorized users can access it. Depending on your needs, you can use JWT, Signed URLs, IP whitelisting, or CORS restrictions. Each method has its own advantages, so choose the one that best fits your use case.
Let us know if you need help implementing any of these solutions!