How to hide your API keys and tokens in React to protect your application

ljaviertovar

L Javier Tovar

Posted on January 17, 2023

How to hide your API keys and tokens in React to protect your application

Using environment variables in Reactjs with Vite and nodejs

Have you ever noticed that some applications have API keys, tokens, or other sensitive credentials visible in their source code? or maybe your own applications?

Well, this can be dangerous and put the security of your services at risk.

API keys, tokens, and other sensitive credentials are used to authenticate and authorize access to services and APIs. If this data is exposed in your application’s source code, anyone who can see your code can access it and use it to perform unauthorized actions on your behalf.

Moreover, by exposing your credentials, you are allowing third parties to use them, which can affect the performance or quality of your services, or even perform attacks against them.

This tutorial will show us how to hide your API keys, tokens, and other sensitive credentials.

How to hide sensitive data?

Some of the ways to do this are:

  • Use environment variables
  • Use a proxy server or a backend platform as a service (BaaS)
  • Use a secure hosting platform

In this way, you can protect the security of your services and prevent them from being compromised.

Now, we will see how to hide sensitive credentials by building a small backend for our React application.

Using Environment Variables in React with Vite

In this tutorial, we will add an OpenWeather APY KEY as an environment variable.
Specifically, we will use the weather API, which is a service that provides weather data, and after a certain number of requests, it starts charging for the requests, so we don’t want this API KEY to be available to the public.

To configure the environment variables in React with Vite we can follow the following steps:

1 — Create your React application with Vite. I will use TypeScript but you can use JavaScript if you wish.

2 — Create a .env file at the root of your project. This file should contain the environment variables you want to use in your application.

API_KEY=784dc6d4eXXXXXXXXb14460d3a356565
PORT=3001
Enter fullscreen mode Exit fullscreen mode

Once we create our .env file we must not forget to attach it to the .gitignore file of git, otherwise, our API KEY will be exposed in the repository.

3— In Vite, to access the environment variables we need to access them via import.meta.env. This returns an object containing the available environment variables known to Vite.

The variables created must have the prefix VITE_ or could be another prefix overwriting the default configuration option envPrefix.

const API_KEY = import.meta.env.VITE_API_KEY
Enter fullscreen mode Exit fullscreen mode

4 — Now we will create a simple application that will fetch the Weather API to retrieve the temperature of a city.

import { useEffect, useState } from "react"
import { ResponseWeather } from "../types"

const API_KEY = import.meta.env.VITE_API_KEY

import "./App.css"

function App() {
 const [weather, setWeather] = useState<ResponseWeather | null>(null)

 useEffect(() => {
   const options = {
     method: "GET",
     url: `https://api.openweathermap.org/data/2.5/weather?lat=43.7001&lon=-79.4163&appid=${API_KEY}`)
     headers: {
      "Content-Type": "application/json",
     },
  }

  axios.request(options).then(response => {
   setWeather(response.data)
  })

 }, [])

 if (!weather) return null

 return (
  <div className='App'>
   <h1>{weather?.name}</h1>
   <h2>{Math.floor(weather?.main.temp - 273.15)} °C</h2>
   <i>
     <img
       src={`http://openweathermap.org/img/wn/${weather?.weather[0].icon}@2x.png`}
       alt={weather?.weather[0].description}
      />
   </i>
   <p>{weather?.weather[0].main}</p>
  </div>
 )
}

export default App   
Enter fullscreen mode Exit fullscreen mode

Fetch Weather API

Now that we have hidden our API KEY with an environment variable and made sure that the .env file is not uploaded to the repository we have done half the work.

And why do we say this? Because our API KEY is still exposed in the final build, if we inspect our app in the browser we will find the value of the API KEY, so the only way to have this value completely hidden is to have it on the server side creating a backend service.

This backend will be in charge of making requests to the Openweather service and our client, that is, our React application will query this backend.

pnpm express cors dotenv axios
Enter fullscreen mode Exit fullscreen mode

In this case that we use Typescript, we will need in addition

pnpm ts-node @types/express @types/cors @types/dotenv @types/node
Enter fullscreen mode Exit fullscreen mode
  • express to create a server
  • cors to enable resource sharing between different domains.
  • dotenv to load environment variables.
  • axios to fetch data.

2 — We create a file called api.ts at the root of the project. We also take the opportunity to add a new command to package.json to boost our server.

"scripts": {
  "server": "npx ts-node api.ts",
  ...
}
Enter fullscreen mode Exit fullscreen mode

3 — We create the server and make available the endpoint that we will use from React.

import express from "express"
import { Request, Response } from "express"
import * as dotenv from "dotenv"
import cors from "cors"
import axios from "axios"

dotenv.config()

const app = express()

app.use(cors())

app.get("/api/weather", (req: Request, res: Response) => {
 const options = {
  method: "GET",
  url: `https://api.openweathermap.org/data/2.5/weather?lat=43.7001&lon=-79.4163&appid=${process.env.VITE_API_KEY}`,
  headers: {
   "Content-Type": "application/json",
  },
 }

 axios
  .request(options)
  .then(response => {
   res.json(response.data)
  })
  .catch(err => {
   console.log(err)
  })
})

app.listen(process.env.VITE_PORT, () => console.log(`Server on port ${process.env.VITE_PORT || 3001}`))
Enter fullscreen mode Exit fullscreen mode

Now that we have the backend service, our API KEY is completely hidden from the client. We could add more layers of security as we want for example, in the cors add only the domain where our app is hosted and only that domain can make requests.

4 — We start our server with the following command

pnpm run server
Enter fullscreen mode Exit fullscreen mode

Finally, we just need to replace the URL of the request we make in React with the one we have in the backend. We no longer need to retrieve the API KEY in React.

// Before
url: `https://api.openweathermap.org/data/2.5/weather?lat=43.7001&lon=-79.4163&appid=${API_KEY}`)

// After
 url: "http://localhost:3001/api/weather"
Enter fullscreen mode Exit fullscreen mode

And that’s it! our application continues to work as usual only that we no longer have our API KEY exposed on the client side.

Repo here.

Conclusion

In conclusion, hiding sensitive data is something relatively easy, just follow the steps mentioned above and with that, we can avoid major risks and complications.

I hope this will help you to keep your projects safe.


Read more:

Want to Connect?
Love connecting with friends all around the world on Twitter.

💖 💪 🙅 🚩
ljaviertovar
L Javier Tovar

Posted on January 17, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related