.env Is Not Enough

Sample security image, with a phone and lock icon on the screen.
Photo by Franck / Unsplash

Everyone knows about .env file, right? To store API keys, and some secret credentials, we are using this file. Also, the most important thing is that we are not committing/pushing this file into any of the repositories. (with the help of .gitignore, for example)

But do you know when you compile ReactJS app, the .env variables are getting embedded into your app, so they can still be visible. So, what is our lesson from here? The .env file is not secret by itself.

What can we do?

We can easily create a middleware to handle requests in our backend. So, frontend would send a request to this middleware, and the middleware would proxy our request with related credentials to original APIs.

A working example:


const apiKey = process.env.API_KEY || "";
const apiUrl = process.env.API_URL || "";

app.use(cors({ origin: allowedOrigin }));
app.use(express.static(publicDir));
app.use(express.json({ limit: "2mb" }));
app.set("trust proxy", 1);

async function callApi(contents) {
  const response = await fetch(`${apiUrl}?key=${apiKey}`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      contents,
    }),
  });

  if (!response.ok) {
    const text = await response.text();
    throw new Error(`API error ${response.status}: ${text}`);
  }

  return await response.json();
}

app.post("/api/foo", async (req, res) => {
  try {
    const data = callApi([{}]);
   
    return res.json({ data: "Some data" || "An error occurred while getting the data." });
  } catch (err) {
    console.error(err);
    return res.status(500).json({ error: "Failed to process" });
  }
});