How to setup user authentication in MongoDB 4.0
A recent analysis showed that there are at least 30.000 instances of MongoDB left unsecured on the Internet, meaning that anyone can access the data without any kind of authentication.
The official MongoDB documentation might feel a little bit complicated on how to properly setup authentication on a MongoDB instance, so this article will hopefully help with an initial basic configuration.
NOTE: this article was updated multiple times, particularly in March 2018 for a check for compatibility with MongoDB 3.6.x, and in March 2019 for compatibility with MongoDB 4.0. The instructions should actually be the same when using any MongoDB 3.x/4.0 version.
Before we start: I’ll assume that you already have MongoDB installed on your system. As said, the version you have doesn’t make much difference, as long as you have at least 3.0.x.
Also note that MongoDB supports more than one authentication mechanisms, which are basically the specifications of the process of authenticating with a password.
Remember that authentication (authn) is the process of verifying the identity of an entity, while authorization (authz) relates to granting or denying specific access requests to resources (database collections, for example).
MongoDB 4.0 removes compatibility for the authentication mechanism called MONGODB-CR, and instead uses by default both SCRAM-SHA-1 and SCRAM-SHA-256. The difference is the hashing algorithm used in the process. Since SHA-1 is starting to be considered weak with respect to collision resistance, SHA-256 is now supported by MongoDB.
To sum up, in MongoDB 3.x the default authn mechanism is SCRAM-SHA-1, while in MongoDB 4.0 both SCRAM-SHA-1 and SCRAM-SHA-256 are enabled by default. You likely won’t need to worry about this, but you’ll have to make sure that the client you’re using to connect to MongoDB supports one of the two authentication mechanisms mentioned above.
You can learn more about SCRAM here, and about security changes in MongoDB 4.0 here.
In this guide, we are going to create 2 users.
- the first one will be an admin user. It’s going to have permissions for managing users on every database of the MongoDB instance, and you will use this user only with the mongo CLI. The role that will be given to this user is called userAdminAnyDatabase. You can find the details of it here;
- the other user will be the owner of a single database, and it’s going to have read and write privileges on the database. You can create as many users as you want, so that every database will have its own user. You will use this user account in your applications to connect to the database of your interest. The details for the dbOwner role are available here, but what you need to know is that it’s a combination of roles that allows to create collections and read and write data in a database.
Note that the role “admin” differs from the role “owner”. A *database admin* is able to perform administrative operations on the database, like creating a new collection, dropping it, viewing stats. A *user admin* is able to manage users for a specific database. A *database owner* has all the privileges listed above, plus the full read and write permission on the database.
Creating the users
Let’s start, for real, by creating the actual users. Open your mongo
shell and switch to the admin
database:
use admin
Create the “admin” user (you can call it whatever you want)
db.createUser({ user: "admin", pwd: "adminpassword", roles: [{ role: "userAdminAnyDatabase", db: "admin" }] })
Don’t panic with all these brackets. We’re passing an “user” object to the createUser function, which contains a “roles” array. In the array we have one “role” object, which defines what the user can do and on which database.
In this case we’re giving the user the userAdminAnyDatabase
role. This means that the admin
user will be able manage (create, update, delete) users on all the databases of the MongoDB instance.
Make sure you use a safe password for the admin
user, preferably generated by a password manager.
You can check that the user has been correctly created with this command:
db.auth("admin", "adminpassword")
The command will log you in as admin
. Now exit the shell:
exit
We are now going to enable authentication on the MongoDB instance, by modifying the mongod.conf
file. If you’re on Linux:
sudo nano /etc/mongod.conf
Add these lines at the bottom of the YAML config file:
security:
authorization: enabled
This will enable authentication on your database instance. With nano, save with CTRL+X and confirm with y
.
Now restart the mongod service (Ubuntu syntax).
sudo service mongod restart
You can check if the service is up with:
sudo service mongod status
Let’s go back in the mongo
shell. Switch to the database admin
and authenticate with the previously created user (called “admin”). Given that the user has the “userAdmin” role, it will be able to create and manage other users.
use admin
db.auth("admin", "adminpassword")
Now we will switch to an already created database and create a new user specifically for the database.
The following command will create an user with the role of dbOwner
on the database. The dbOwner
role will give to the user read and write permissions on all the collections of the database. Read more here.
use yourdatabase
db.createUser({ user: "youruser", pwd: "yourpassword", roles: [{ role: "dbOwner", db: "yourdatabase" }] })
Check that everything went fine by trying to authenticate, with the db.auth(user, pwd)
function.
db.auth("youruser", "yourpassword")
show collections
And that’s it, your MongoDB instance is now secured, provided that you used strong passwords.
When connecting with your favourite MongoDB Client from an application, use a connection string that will look like this:
mongodb://youruser:yourpassword@localhost/yourdatabase
Now, one last thing…
Protecting from external access
We’re now going to check that the MongoDB instance is listening on the local loopback interface only. This means that the DBMS will be accepting connections to the databases only when they come from the host itself.
You can of course adapt this to your needs, for example by enabling access on a private network interface, but the important thing to understand is that you should carefully decide which interfaces MongoDB should listen on. You should therefore avoid to expose the instance on the Internet if you don’t require to access it from the outside. And even if you do, there are much better ways to do that, for example by using an SSH tunnel. But that’s another story.
So, open mongod.conf
in edit mode again, as we’re going to check out the net.bindIp
option. That option tells the mongod process on which interfaces it should listen.
Examples of bindIp configuration
net:
bindIp: 127.0.0.1
With this configuration, MongoDB will listen on 127.0.0.1 only (localhost). It means that you’ll be able to connect to your database only from the local machine.
NOTE: 127.0.0.1 is the default bind interface starting with MongoDB 3.6.0.
net:
bindIp: 0.0.0.0
With this configuration, MongoDB will be listening on 0.0.0.0 (“all the networks”). It means that mongod will listen on all the interfaces configured on your system. Pay attention that in this way you are likely going to allow everyone on the Internet to access your database (as far as they have the credentials, of course, so pay particular attention to poor passwords).
You can also make MongoDB listen on more than one interface, by separing them with commas. This is useful if you want to make MongoDB listen on localhost and a private network interface.
net:
bindIp: 127.0.0.1,172.21.200.200
A solution that you could consider is to set the bindIp
option to 0.0.0.0
and then configure a firewall (like FireHOL) to filter incoming TCP requests on the MongoDB port and allow them only on specific interfaces.
Wrapping up
If your MongoDB instance was among the unsecured ones on the Internet, you should now be safe, or at least safer than before.
There are other steps you can follow for the security of your MongoBD instance, including the configuration of a firewall and TLS for client-server communication. These topics are covered in the official Security Manual.
If you have any questions, suggestions or just want to say hello, feel free to leave a comment, I hope this helped :)