Will my .env variable value be exposed to clients? - reactjs

I am using .env to store all my private Api_key value, which is to call third party API key like google map.
I was told that, with react js, the javascipt is actually excuted in client side.
Does it mean that actually, my .env variables are accessible by clients too in which they can actually see my API key?
For example, in my component code, I have this
<Geocoder
mapRef={mapRef}
mapboxApiAccessToken={process.env.NEXT_PUBLIC_mapbox_key}
position="top-left"
placeholder="Set your position"
/>
In my .env
NEXT_PUBLIC_mapbox_key=<KEY>
If yes, how do I keep it safe while providing the key to the third party components

Yes, users will be available to see your API key in network inspection, even if you will keep it in the .env file which is excluded from git.
It's better to make a separate route on your backend side and keep your API key on the backend - if it is possible.
Some useful links:
API security best practices
5 best practices for secure API key storage

Related

Exposing API Endpoints in Frontend Application

I am building a frontend application using react and I am wondering whether it is risky to expose API endpoint URLs (ex: https://myapi.com/v1/getitems) on GitHub, assuming that the endpoint has several security measures that are not exposed such as CORS and JWT Token Bearer Authentication. I would assume not, since, if someone were to take the endpoint and send requests, they would need a token and be allowed to do so by CORS.
Is there any security risk in doing so?
Yes. Don't add the base url of your api on github in plain view. Even though you might have CORS and Authorization, that doesn't stop a malicious actor to keep spamming your back-end.
What you do is create a .env file in your root folder. You can use a library like #beam-australia/react-env and there are others as well.
You add in the .env file the values that are important for your environment and that are usually secrets, and you want them to not be visible in your code. You do it like so:
API_URL="https://myapi.com/v1"
And then you access this variable in your code with env("API-URL") ( in the #beam-australia/react-env case, but others libraries work the same). Keep in mind that you need to add .env in .gitignore so that the .env file is not pushed to github.
Regarding requests, you can make one like so:
fetch(`${env("API_URL}/getitems`)
This way your code will be stripped of the API's base url and if someone sees your code it will see only the endpoint, not the full url.
Publishing the code of the API is risky on its own. Somebody can find a vulnerability in it and instantly hack it. If you add the address of the API to the code you help this kind of attacks. They can get the address with some investigation; OSINT and social engineering too, but better to reduce the attack surface.
As of the secrets, they must never be near to the code, because you or another developer can accidentally publish it. It happened too many times with many developers, so better to take this seriously. If you want to keep the address in secret, then you must extract it from the code and put it in the configuration of the production environment which is imported from a totally different location than your code. Using environment variables like Alex suggested is a good idea for this. Nowadays it is common to use docker, which has a way to manage secrets, so you don't need to reinvent the wheel: https://docs.docker.com/engine/swarm/secrets/ Another aspect that the configuration belongs to the actual instance. In OOP terms you want to describe the injected properties of an object in its class or in a global variable, which is an antipattern.
As of client side REST clients like javascript applications running in the browser or Android/iOS apps, you must not publish your secrets along with the REST client, otherwise it is not a secret anymore. In that case you need a server side part for the REST client and for example sign and encrypt JWT there with a secret key. It is your decision whether this server side part of the REST client sends the HTTP request to the REST API and in that case you can hide the URI of the REST API or it just manages the JWT and the client side part of the REST client sends it. If the server side part of the REST client sends the HTTP request to the REST API, then you can even use traditional sessions with session cookies between the client side and the server side parts of the REST client, but you cannot use them between the server side part of the REST client and the REST API where the communication must be stateless. Though it does not make much sense to have a separate REST API if you don't have multiple different REST clients in this scenario e.g. browser clients for JS and JSless browsers, Android and iOS clients, fully automated clients running on servers, etc. So don't confuse the REST client - REST API relationship with the browser - HTTP server relationship, because they are not necessarily the same. Most of the REST clients run on servers, not in the browser.

node paymentMethods.list equivalent in #stripe/react-stripe-js

I am trying to retrieve all payment methods listed for a customer in stripe using react. I have access to publishable key and client secret.
But, I am unable to find a method to retrieve the payment methods (similar to the one in node - stripe.paymentMethods.list or PaymentMethodsRetrievalListener in Android).
Any help, much appreciated.
Regards,
There isn't such a method unfortunately!
The backend API for listing PaymentMethods (https://stripe.com/docs/api/payment_methods/customer_list) generally requires a secret key(which is what stripe-node uses), not something you can use in a React frontend.
The mobile SDKs like Android use the ephemeral key they get from your backend (https://stripe.com/docs/payments/accept-a-payment?platform=android&ui=payment-sheet#add-server-endpoint) to call the same API — it's technically possible to do this yourself on the web too but it's not documented in any way so it's not really a good option.
Overall you would normally just have your frontend call your backend, your backend(written in e.g. Node and using your secret API key) can call https://stripe.com/docs/api/payment_methods/customer_list and return the information the frontend is looking for.

Is API key exposed through get request?

I am building a Node/React app in which I have placed my API keys in a .env file which is in my .gitignore. The frontend makes a get request to the API endpoint using Axios and the UseEffect hook with the API key provided via process.env. I understand why it is good practice to obscure the API key and not commit that information to git however my question is whether something still needs to be done (or can be done) about the API key getting exposed through inspection of the requests in chrome developer tools?
//on component mount fetch the images
useEffect(async ()=>{
const results = await axios(
`https://pixabay.com/api/?key=${process.env.PIXA_API_KEY}`
);
},[])
For instance below if a user were to use chrome tools in the browser on my project they can still see my API key as part of the request. In my case it's not much of a concern as this particular API is free and the project is for personal use only, but I wondered how this problem is approached in a commercial project where a payed for API might be in use? What's to stop me using chrome dev tools on another persons app and stealing their API key to make my own requests?
That is a very good observation. The truth is that you cannot have any secrets in your client code. No amount of obscuring, obfuscation or even encryption will prevent attackers from stealing your secrets. The client code is out there for anyone to read and needs to be approached as such.
If private APIs with keys you do not want to expose are involved, you need to call them from a server. So the flow would look something like this:

Using Firebase Remote Config instead of .env file

I am building a react application with firebase integration and the environment variables we are using can be inspected out by taking the page source of the page in a deployed website.
I am interested in knowing some ways to make it safer. the only way I can think is of take values from an API so that its not shown with the code at any point.
To connect to firebase I can use the reserved url method to automatically connect.Firebase remote config allows you to store key value pairs. I was thinking of moving all my env variables out to remove config setup and use it from there. So I can remove my .env file altogether and avoid exposing any hardcoded values.
Have anyone tried this already? what could be the recommended way to make .env values safer?
You should never load any values that you don't want users to be able to access into the browser, period. The browser is an open book and while you may be able to obscure values by changing where and how they are loaded, you cannot prevent a motivated attacker from reading absolutely anything and everything you do on the client.
This is why Firebase is designed to have API keys and configuration that are safe to be publicly readable -- when you write security rules you are essentially drawing boundaries around what clients can do.
Firebase Remote Config can and should be used for values that are safe for clients to have -- things like feature flags or environment-specific URLs for APIs. It should not be used for sensitive things like private API keys and secrets.

React JS - Best practice to hide http call credentials

What's the best practices to hide or prevent the user see the credentials (implemented in WebService calls). The development is ReactJS and use Heroku to deploy the WebApp.
I have this code:
I want to prevent the user can see the credentials and some security details.
I started using the node module dotenv recently and really like how easy it is to use. All you need to do is install it and create a .env file with your environment variables like this:
.env
SECRET_KEY=123456
ANOTHER_KEY=78901
Then, require it as early as possible in your application:
require('dotenv').config().
I do this inside my server.js file (or whatever you name it).
That's it! Anything stored in the file can now be accessed by doing process.env.{name}
For example:
let secret = process.env.SECRET_KEY;
console.log(secret); // 123456
This is not really possible to do in a client side because all the HTTP calls can be easily visible in Network tab in Chrome Inspect Elements(or any web browser).
I would suggest you work on the security so you don't care if a user will see your HTTP endpoints or not.
You can also consider making your HTTP request on a server which will act as a bridge between your client and an API.

Resources