I would like to use environment variables to securely hold secrets with pm2.
I have a reverse proxy to an express backed server that uses a database with a password each time it connects to preform a query.
I would like to access it normally from the program:
procsess.env.my_secret
but I'm assuming that simply setting the variable at run time like the following isn't safe:
MY_SECRET="secret password" pm2/node my_api_server.js
How should I set the secret password considering I'm using pm2 and I would like the variable to persist through restarts/crashes?
I should note that different environment handling and passing code to other developers through the VCN is less important to me.
Storing API keys or credentials using .env gets exposed to the client on Production!
By React docs -
WARNING: Do not store any secrets (such as private API keys) in your React app!
Environment variables are embedded into the build, meaning anyone can view them by inspecting your app's files.
It's advised to store all env keys directly on the server and the server should be used as a mid point between the client and the API. This way the key is applied directly on the server and is not exposed in the front end. You can check out respective documentation on how to set up env variables on your particular server.
Front End Code
fetchData = () => {
fetch('/users', { method: 'POST', body: JSON.stringify(data) }
.then(res => res.json())
}
Server Code
app.post('/users', (req, res) => {
const API_KEY = process.env.API_KEY;
connection.query(`/apiPath/${API_KEY}`)
}
In past ReactJS projects with Express backends that need to connect to a database, I've used the dotenv package on NPM. Once added as a dependency to your project, you will create a hidden .env file in the root of your server filestructure.
In that .env file, you can create environment variables. These variables will need to be prefixed with REACT_APP like the following:
REACT_APP_DBURI=<conn string here>
REACT_APP_MAILGUN_API_KEY=<key string here>
REACT_APP_CAPTCHA_SECRET_KEY=<key string here>
You need to require the package as follows in your code:
require('dotenv').config();
You can reference them in your server.js (or whatever) code as:
process.env.REACT_APP_VARIABLE_NAME
This Medium article has a full explanation.
Hope this helps!
Related
I am writing a headless solution for a WordPress website and noticed that for one particular endpoint, I need to authenticate to pull some data that will be used publicly. But, I'm concerned that where I'm using it will expose it to the web.
In my store/index.js I use the nuxtServerInit action method to execute some actions and I pass them some objects they need to fulfill their tasks:
async nuxtServerInit ({ dispatch }, { $axios, app }) {
await dispatch('initialize', { $axios, app })
},
$axios is passed because it will be used to query the API, and app is passed to help build the options to authenticate the request.
Is this a security vulnerability in Nuxt SSR? I think it is. If so, where are the only valid areas you can use secrets? asyncData ()?
If you're using SSR, you can use the privateRuntimeConfig runtime object and pass your secret in the nuxt.config.js file
export default {
privateRuntimeConfig: {
apiSecret: process.env.API_SECRET
}
}
If you read the documentation of nuxtServerInit, you can see that
Vuex action that is called only on server-side to pre-populate the store
Since this method is server-side only, you can use apiSecret (in my example) and it should be totally fine security-wise.
PS: Keep in mind that everything beyond what is generated on the server (hence, with NodeJS or nuxtServerInit) is "public". So your VueJS's client code lifecycle hooks are public: mounted(), fetch(), asyncData() because they will be visible on your browser's devtools.
Also, should your endpoint be that critical? If so, nuxtServerInit is the good way to go. If you need to fetch some more data in a "private way", you'll need to proxy it through some backend to hide the sensitive info and retrieve only the useful public data.
I'm using mern stack in a project I'm working on.
Currently I'm making requests to the rest api like so.
const { data } = await axios.get('http://localhost:5000/api/testimonials/');
The API is available at http://localhost:5000/
but when I will deploy this app that url will change.
With the current approach I have replace http://localhost:5000/ with the live url.
Instead of doing that I want to store the root url in a variable.
What is the best location to store the API root in React JS?
So I can use it in every request I make and when I have to update the url I just have to update that variable.
You can do two things ,
storing them in env variables by creating .env file for each environment
CRA - .env
Don't forget to prefix your names with REACT_APP_ , else it won't work
using proxy in package.json .(This is the preferred way of using api in docs)
It avoids cors error as mentioned in docs
CRA - proxy
You will have to use .env file to save the root url. .env should be located in the root directory.
.env file content:
rooturl=http://yourproductiondomain.com
and you can use process on your code:
const rooturl = process.env.rooturl || 'http://localhost:5000'; // for lcoalhost.. **.env** file does not work on localhost.
const { data } = await axios.get(rooturl + '/api/testimonials/');
I am currently using heroku to store my environmental variables for my firebase authentication initialisation. I am using my server to get the environmental variables and send it to the client using socket.io. Below is what I mean.
1) Example of sending environmental variable to client from server:
socket.emit('value', process.env.apiKey);
2) storing it as data[0] in the client:
socket.on('value', function(data) {
firebase.initializeApp({
apiKey: data[0],
});
})
Is this safe? Can someone from the client retrieve the value of the apiKey if I save it like this on the client?
Thanks
If the data is used from the client, it can be gotten from there by a malicious user. Looking up the data dynamically like you do here, merely adds an extra step.
But the data that you pass to initializeApp is basic configuration data that allows the code to find your Firebase project on the servers. It is not a secret, it's not a security mechanism ,and it can be safely shared with your users. See my answer here, for why you don't have to try and secure this data: Is it safe to expose Firebase apiKey to the public?
I am building a node.js app (script?) that is using google-auth-library and there is something that I don't understand.
I have generated the JSON file containing my OAuth2 client id keys using Google Developers Console, and I am using it in my script the following way :
const keys = require('../client_secret.json');
const oAuth2Client = new OAuth2Client(
keys.web.client_id,
keys.web.client_secret,
keys.web.redirect_uris[0]
);
// Generate the url that will be used for the consent dialog.
const authorizeUrl = oAuth2Client.generateAuthUrl({
access_type: 'offline',
scope: [
'https://mail.google.com',
'https://www.googleapis.com/auth/drive'
]
});
Then, I am opening the consent dialog, and getting my token back, etc. My app has the will to be open source, so my question is: should I let my client_secret.json file in my repository so other users can use it using their Google account?
The client token must be kept secret: extract from Google documentation
After creating your credentials, download the client_secret.json file from the API Console. Securely store the file in a location that only your application can access.
Your application will remain open source as authentication is a service not source code.
To manage your secret, I would suggest you to use environment variables accessible via process.env.YOUR_VARIABLE.
It does exit packages that will make it easy to handle between you different environments, my favorite is dotenv. dotenv loads environment variables from a non required .env file. You would typically use it in your development environment, you must not commit it!
Dotenv do not require the presence of the .env file, and won't override an environment variable that is already set anyway. You will have to define the environment variables in production and test environment the way your prefer.
You can also see this article
Is it possible to access ENV variables from angularjs?
I've got an angular 1.2.8 app being compiled via Brunch.io
It's hosted as a basic node app on heroku. (I do compiling locally; then push)
I've read a few things about token replacement during the compile stage for ENV variables.
However I'd much rather be able to push up the code to several different servers and have it resolve the correct local settings using just the ENV variables.
Thanks!
You cannot get ENV variables on browser. You can send request to a rest service on your server, and get env on backend, then response back to client
Quick example: (Express.js)
app.get("/rest/getenv", function(req, res) {
var env = process.env.ENV_VARIABLE;
res.json({result: env});
});
Edit:
You need to protect this rest url with token like strings. Or else, anyone can reach that url and get your environment variable value. This can be security concern
There are multiple ways of doing it and as mentioned above you could simply make and API call, however that creates an unnecessary delay in your app.
I would recommend to inject your env variables into your angular constant service on your server. That probably sounds a bit confusing, but it's simpler than it sounds.
I have written a blog post comparing different ways of injecting env varialbes into angular and explaining why you should take this approach: https://medium.com/#kudresov/a-better-way-to-inject-environmental-variables-in-angular-d3b2d01a3c5e
Also I have created sample Node Angular project to show how it works: https://github.com/kudresov/angular-config-vars