How to hide your API keys and tokens in React to protect your application
L Javier Tovar
Posted on January 17, 2023
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
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
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
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
In this case that we use Typescript, we will need in addition
pnpm ts-node @types/express @types/cors @types/dotenv @types/node
- 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",
...
}
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}`))
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
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"
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.
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:
How to create reusable and customizable modals with React and TypeScript
Why Should You Use Cleanup Functions in React’s useEffect Hook?
Want to Connect?
Love connecting with friends all around the world on Twitter.
Posted on January 17, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.