Question concerns setting up the development environment (later on other environment like production)....
Using latest of Node, Passport, and Grunt but Express still in the 3 chain.
Working on an application leveraging external authentication only (i.e. no local Passport strategy). The oauth client id, secret key and callback configuration per strategy (i.e. Google, Facebook etc.) is nothing (obviously) to be housed in Git.
Wondering how people tackle this with different environments? Just getting my feet wet with Grunt so I am currently registering a task (after the initConfig which reads my package.json) that reads a authentication configuration (excepting an authentication property in package.json):
grunt.registerTask('auth', function() {
var pkg = grunt.config('pkg');
var util = require('util');
if (grunt.file.exists(pkg.authentication)) {
grunt.log.writeln(util.format('Setting up authentication with %s', pkg.authentication));
var auth = grunt.file.readJSON(pkg.authentication);
.... // move auth data into a auth.js read by the application
} else
grunt.fail.warn(util.format('%s not found (authentication property in package.json), neccessary for authentication but not managaged by Git', pkg.authentication));
});
Basically, the developer/installer is responsible for having a private (not managed by Git), local settings for authentication. Something like:
{
'googleAuth' : {
'clientID' : 'your-secret-clientID-here',
'clientSecret' : 'your-client-secret-here',
'callbackURL' : 'http://localhost:8080/auth/google/callback'
}
}
A simple copy of the JSON contents into a auth.js file put in the build directory required by the application will work.
Better way?
Related
I am working on an inventory management system RESTful API in NodeJS right now. The API will be accessed by a standalone VueJS application through HTTP requests. I want to use CAS to prevent access to API resources to unauthenticated users. I have settled on using the library found here: https://www.npmjs.com/package/node-cas-authentication
I have got the library working for CAS authentication, but I have to duplicate the initializing code across all of my route files.
The initializing code I have to keep repeating:
const CASAuth = require('node-cas-authentication');
const cas = new CASAuth({
cas_url : 'https://my-cas-host.com/cas',
service_url : 'https://my-service-host.com',
is_dev_mode : true
});
My file structure:
I wanted to know if there is a better way to organize my code so that I do not have to continuously repeat the initializing code in each file. If there is so way to include the CAS Authentication via a separate file and I require, this would be beneficial for organization and for maintenance. I am fairly new to NodeJS, so any suggestions would be helpful!
One option is to create a new module, say cas-middleware.js, which performs the initialization and exports the resulting object:
// cas-middleware.js
const CASAuth = require('node-cas-authentication');
const cas = new CASAuth({
cas_url : 'https://my-cas-host.com/cas',
service_url : 'https://my-service-host.com',
is_dev_mode : true
});
module.exports = cas; // Add this line
You can then reference that same object from all of your other modules using require:
// e.g., routes.js
const cas = require('../cas-middleware')
Each module that imports the object from cas-middleware.js will receive a reference to the same CASAuth object.
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!
I am finishing up a node express App where I have an API key for Sendgrid and Stripe but I am not sure how to store these in my app that will be deployed on Heroku (also a few other variable I would like to store similarly like db password and what not). I saw online many people were using process.env so after some looking I tried using dotenv npm and even with some problems with the structure of the app after trying to use the dotenv for my sendgrid key I got an error every time.
My question is can somebody supply some detailed instructions or a way to securely store API keys in my node express app that I will be deploying to Heroku?
P.S. I followed a tutorial to implement Passport.js for Oauth2 through facebook, google and linkedIn so users can easily log in to the application. The app secrets, id and callbacks are retrieved from a json file in a folder call config in my application. Is this information secure at least in its placement and retrieval in the application? Should I do something similar for my sendgrip and stripe api keys? (picture below)
You can set up your folder directory like this:
config.js
var config = {};
//development
var env = process.env.NODE_ENV || 'development';
if(env === 'development'){
config = require('./env/development');
}else if (env === 'test'){
config = require('./env/test');
} else if(env === 'production'){
config = require('./env/production');
}
module.exports = config;
development.js
var envFile = __dirname + '/env.json';
var jsonfile = require('jsonfile');
var envVars = jsonfile.readFileSync(envFile);
module.exports = {
value: envVars["VALUE"]
};
production.js
module.exports = {
value: process.env.VALUE
};
test.js
module.exports = {
value: 'Some value'
};
The basic idea here is that each developer can configure their own keys in their own env.json file. For production, you can store these in a secure file somewhere and load them into the environment however you want prior to running your application. Using heroku, it makes it easy to configure these environment variables and stores them for you. Check it out here
You can also ommit any details you may not need like development or test stuff.
Edit: An example
Try this from the command line first to get an idea of what is happening. In this example I am using linux. If you are using anything else just research how to set the environment variables in the command line you are using.
app.js
var config = require('./config/config');
//get value from config
var value = config.value;
Set environment variables from bash command line
$: VALUE="my value"
$: NODE_ENV="production"
$: export VALUE
$: export NODE_ENV
Run the application
$: node app.js
or if you are using npm scripts
$: npm start
When you run the application node will automatically load process.env with every environment varaible defined within the command line shell. Now, if you are using heroku you can follow the link I posted earlier in this answer and you don't have to set them. Just define them in heroku interface and it will load them for you.
I'm trying to make a NodeJS application on Heroku private so that only developers can see it. Is there a simply way to do that, like basic auth? (All of the solutions I keep finding are specific to Ruby apps).
If you want to leverage basic authentication, here are two options: http-auth and Passport. http-auth is a very simple module and Passport is a powerful module with alternatives for authentication. Both modules provide code examples ranging from basic code to Express framework integration.
I have the same problem. I managed to get one solution working that may work for you but wasn't suitable for me as it seems to interfere with the built in user login from angular-fullstack.
I just wanted a quick way to password protect the app so that only developers and stakeholders could see it. https://www.npmjs.org/package/http-auth seems to do the trick.
This involves add http-auth to your project (npm install http-auth --save). Then you'll need to find the file where your createServer is defined and the code there.
If you're using Express you can do something like this
// HTTP Authentication
var preAuth = require('http-auth');
var basic = preAuth.basic({
realm: "Restricted Access! Please login to proceed"
}, function (username, password, callback) {
callback( (username === "user" && password === "password"));
}
);
// Setup server
var app = express();
app.use(preAuth.connect(basic));
var server = require('http').createServer(app);
If not then you can try one of the options from the http-auth documentation e.g.
// Authentication module.
var auth = require('http-auth');
var basic = auth.basic({
realm: "Simon Area."
}, function (username, password, callback) { // Custom authentication method.
callback(username === "Tina" && password === "Bullock");
}
);
// Creating new HTTP server.
http.createServer(basic, function(req, res) {
res.end("Welcome to private area - " + req.user + "!");
}).listen(1337);
Here are also a couple of related threads with somewhat similar approaches.
express.basicAuth throwing error
Basic HTTP authentication in Node.JS?
I'm facing the following situation. In order to further modulize my software development, I've written a few standard modules stand alone. Think for instance of an login module based upon Express and Passport, allowing users to login with all kinds of social services. The module also contains UI for user management, login, registration, profile, etc.
Now, the thing I'm trying to do is to just drop the Auth app folder (containing the express app, all it's routes, views, models, settings and dependecies) into another Express app (for instance, a CMS) and then load it with something like require('./lib/auth/app.js'). I know this is possible, take a look at Kue.
How would I go about doing this? And how do I manage namespacing problems? I could of cours append /auth/ to each route, but I can imagine the settings (app.use()'s) and public folder would conflict with the 'parent' app.js' settings and public folder.
Thanks in advance,
Fabian
Think I found my answer. So, I found this question, and this one. Guess my terminology was off.
I solved my problem by doing a few things. First of all, I changed all routes and url's to be "namespaced" (not really, but this does the job). All routes now have /auth/ in front of them. I did the same to all links, so that's all working.
Next, I removed the server part from my app.js. So, in stead of doing:
require('http').createServer(app).listen(app.get('port'));
I just do:
module.exports = app;
And I add some custom methods to the app object:
app.isLoggedIn = auth.isLoggedIn;
app.notLoggedIn = auth.notLoggedIn;
Then, in my root app, I just do the following to load the auth app in. Routing, public files, and all other stuff happens magically. pretty cool.
var auth = require('./vendor/auth/app');
var app = express();
app.configure(function() {
app.use(auth); // use our auth app
// do a lot of root-app related stuff...
});
Things still to do:
My auth app uses some session stuff. According to the second link, if I understand correctly, the app.use(session...) stuff in my auth app gets overridden by app.use. Also, I want to define an EJS helper to generate my urls (something like site_url('/facebook/callback') which then points to /auth/facebook/callback). Finally, I need to include settings from my root app. I'm thinking of wrapping my entire app.js (in auth) in a function, to which I pass a config object. Like this:
module.exports = function(config) {
var app = express();
app.set('config', config);
// various app settings, routes, etc
// return app so it's available in my root.
return app;
}
I hope this helps, if you need a bit more information I'll see if I can post some code to a gist. just let me know!