Intro
This is my second MongoDB post of many planned, so I’ve decided to start the Mini Mongo Series, catchy right?
The first problem I faced when setting up my own MongoDB instance on AWS was figuring out how to do simple authentication. If there are no users configured in myDatabase.system.users
, anyone can access the database without authenticating. E.g. to prevent anyone from simply going to ec2-xx-xx-xxx.compute-1.amazonaws.com:27017
and accessing the data.
There are a lot of great tutorials on how to add security and authenticate using drivers but they come as many separate small tutorials. So here it is in one unified place and my experiences setting it up. If you you have any questions or comments feel free to comment below.
1. Add a user to the database
We are going to add a user to our database and allow them to use credentials to authenticate later.
First make sure mongod is running without the auth flag.
Then run mongo in another command line to access the interactive MongoDB shell. Lets add a user to our pets database.
$ mongod ... $ mongo > use pets > db.addUser('petar','myPassword');
Now that we have a user created an account, lets allow them to authenticate. Documentation here
> db.auth('petar', 'myPassword');
You can confirm this user was added by running the following.
> db.system.users.find()
2. Confirm that authentication works
A simple test case to ensure our authentication works is to run mongod --auth
and try to connect from the mongo command line
with and without the user credentials we previously created.
With credentials we expect to see the list of databases
$ mongod --auth ... $ mongo -u petar -p myPassword > show dbs admin 0.203125GB pets 0.203125GB
Without credentials we expect to see an error saying we are unauthorized
$ mongod --auth ... $ mongo > show dbs failed:{ "ok" : 0, "errmsg" : "unauthorized" }
You’ll see that since we didn’t provide our user credentials, we get an error.
Connect MongoDB to Node.js
Using the MongoDB driver from 10gen and some boilerplate code, we can connect and authenticate to the database using the user we just setup.
// use 10gen's mongodb driver | |
var mongo = require('mongodb'), | |
Server = mongo.Server, | |
Db = mongo.Db, | |
db; | |
// These variables can be passed in from the commmand line or defined in your environment | |
var mongoServer = process.env.PETAR_MONGODB_DB_HOST, | |
mongoPort = process.env.PETAR_MONGODB_DB_PORT, | |
mongoDb = process.env.PETAR_DB_NAME, | |
mongoUser = process.env.PETAR_MONGODB_DB_USERNAME, | |
mongoPass = process.env.PETAR_MONGODB_DB_PASSWORD; | |
// Print out the environment variables to make sure they exist | |
console.log(mongoServer, mongoPort, mongoDb, mongoUser, mongoPass); | |
// Initialize the server connection object | |
var server = new Server(mongoServer, mongoPort, {}); | |
db = new Db(mongoDb, server); | |
// Open the connection | |
db.open(function(err, client) { | |
// Authenticate the user | |
client.authenticate(mongoUser, mongoPass, function(err, success) { | |
if (err) { | |
console.log('error connecting to MongoDB: ', err); | |
} | |
else { | |
// Do Something ... | |
console.log('successfully auth to open MongoDB: ', success); | |
} | |
}); | |
}); |
Run the Node.js app with environment variables
In order not to hard code the env variables in your app, which is generally a bad practice, we can pass in the credentials from the command line and have them available under process.env
$ PETAR_MONGODB_DB_HOST=aws.xxx.com \
PETAR_MONGODB_DB_PORT=27018 \
PETAR_DB_NAME=myDbName \
PETAR_MONGODB_DB_USERNAME=authUser \
PETAR_MONGODB_DB_PASSWORD=authUserPass \
node app.js
Conclusion
We’ve managed to create a user, enable authentication, put that authentication to use, and confirm that it is working. Our Node.js app is now connected to our MongoDB instance using an authenticated user, preventing unauthorized access.
$ successfully auth to open AWS MongoDB: true
In-depth Resources