MongoDB authentication configuration example using Shell and Java Driver

Filed Under: MongoDB

Authentication enables user to verify identity before connecting to the database. At first, a user with admin privileges should be created and then additional users can be added.

Let’s now create a user having admin privileges

  1. Start the MongoDB server without authentication (using mongod in command line)
  2. Create the user with admin privilege as specified below
    
    >use admin
    switched to db admin
    >db.createUser(
      {
        user: "Adam",
        pwd: "admin",
        roles:
        [
          {
            role: "userAdminAnyDatabase",
            db: "admin"
          }
        ]
      }
    )
    Successfully added user: {
    	"user" : "Adam",
    	"roles" : [
    		{
    			"role" : "userAdminAnyDatabase",
    			"db" : "admin"
    		}
    	]
    }
    > 
    

    The createUser command creates a user “Adam” authenticated by the pwd field with the role being an admin role userAdminAnyDatabase in the database “admin“.

  3. Specify the authorization –auth in the mongodb service file and restart the mongodb service with authentication.
  4. Login to the mongo shell with admin user credentials as;
    
    mongo -u  Adam -p admin --authenticationDatabase admin
    

    Let’s verify the privileges for the user we just created as

    
    >db.runCommand(               
     {  usersInfo:  { user: "Adam", db: "admin" },   showPrivileges: true  } 
    )
    {
    	"users" : [
    		{
    			"_id" : "admin.Adam",
    			"user" : "Adam",
    			"db" : "admin",
    			"roles" : [
    				{
    					"role" : "userAdminAnyDatabase",
    					"db" : "admin"
    				}
    			],
    ... continues listing many attributes.
    

    The runCommand accepts the usersInfo fields that holds the user name and showprivileges is set to true. This displays the privleges granted to the user “Adam”. The above command list quite a lot of data pertaining to the privileges of the user.

Assigning Roles while creating user

Let’s create the new user with the CreateUser command and associate a role to it.


>use admin
switched to db admin
>db.createUser(
    {
      user: "Jack",
      pwd: "jack",
      roles: [
         { role: "read", db: "test" },
         { role: "read", db: "car" },
         ]
    }
)
Successfully added user: {
	"user" : "Jack",
	"roles" : [
		{
			"role" : "read",
			"db" : "test"
		},
		{
			"role" : "read",
			"db" : "car"
		}
	]
}
>

The user “Jack” is added with the role “read” on databases car and test. If we try to insert documents we get an error since we have specified a read only role.


WriteResult({
	"writeError" : {
		"code" : 13,
		"errmsg" : "not authorized on test to execute command { insert: \"products\", documents: [ { _id: ObjectId('5479b0dc9d9c8808eadff8b7'), item: \"card\", qty: 15.0 } ], ordered: true }"
	}
})

Creating Role

The createRole command is used to create a new role to the user.


>use admin
switched to db admin
>db.createRole(
   {
     role: "userRole",
     privileges: [
       { resource: { cluster: true }, actions: [ "killop", "inprog" ] },
       { resource: { db: "", collection: "" }, actions: [ "killCursors" ] }
     ],
     roles: []
   }
)
{
	"role" : "userRole",
	"privileges" : [
		{
			"resource" : {
				"cluster" : true
			},
			"actions" : [
				"killop",
				"inprog"
			]
		},
		{
			"resource" : {
				"db" : "",
				"collection" : ""
			},
			"actions" : [
				"killCursors"
			]
		}
	],
	"roles" : [ ]
}
> 

The “userRole” has the permission to kill any operation as specified in the create role command. inprog is a system level role that shows the active or pending operations. There are numerous built in roles like read, readwrite, dbadmin etc. each of which are associated with actions like killop, inprog etc.

Granting a Role

Grant a role to the user with grantRolesToUser method as;


>use admin
switched to db admin
>db.grantRolesToUser(
  "Jack",
  [
    {
      role: "readWrite", db: "admin"
    },
    {
      role: "readAnyDatabase", db:"admin"
    }
  ]
)

Identify user role

The usersInfo command or db.getUser() method is used to fetch user information.


>db.getUser("Jack")
{
	"_id" : "admin.Jack",
	"user" : "Jack",
	"db" : "admin",
	"roles" : [
		{
			"role" : "readWrite",
			"db" : "admin"
		},
		{
			"role" : "read",
			"db" : "car"
		},
		{
			"role" : "readAnyDatabase",
			"db" : "admin"
		},
		{
			"role" : "read",
			"db" : "test"
		}
	]
}

As you can see we have now provided readwrite role to jack user.

Revoking a Role

If you want to revoke any of the roles, we can do it as below


>db.revokeRolesFromUser(
    "Jack",
   [
    { role: "readWrite", db: "admin" }
    ]
 )

As you can see below, readwrite is no more associated with this user.


db.getUser("Jack")
{
	"_id" : "admin.Jack",
	"user" : "Jack",
	"db" : "admin",
	"roles" : [
		{
			"role" : "read",
			"db" : "car"
		},
		{
			"role" : "readAnyDatabase",
			"db" : "admin"
		},
		{
			"role" : "read",
			"db" : "test"
		}
	]
}

Change User Password

To change the password use changeUserPassword method as;


db.changeUserPassword("Jack", "rem123")

Now if we try to login with the old password an exception “login failed exception” is thrown.

MongoDB Java Program for Authentication

Below is a simple program showing how to pass MongoDB database user/password details programatically. Note that I am using mongo-java-driver version 2.13.0-rc0, if you are on some other version then there might be some changes required in the way MongoCredentials are created.


package com.journaldev.mongodb;

import java.net.UnknownHostException;
import java.util.Arrays;

import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.MongoClient;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;

public class MongoDBAuthenticationExample {

	public static void main(String[] args) throws UnknownHostException {

		// create user with username,password and specify the database name
		MongoCredential credential = MongoCredential.createCredential(
				"journaldev", "admin", "journaldev".toCharArray());

		// create an instance of mongoclient
		MongoClient mongoClient = new MongoClient(new ServerAddress(),
				Arrays.asList(credential));

		// get the test db useyour own here
		DB db = mongoClient.getDB("admin");

		// get the car collection
		DBCollection coll = db.getCollection("car");

		// create new car object to insert
		BasicDBObject b1 = new BasicDBObject("name", "Qualis");

		// shows user privileges
		DBObject d1 = new BasicDBObject("usersInfo", new BasicDBObject("user",
				"journaldev").append("db", "admin")).append("showPrivileges", true);

		// insert new document
		coll.insert(b1);

		// execute the command for privileges
		System.out.println(db.command(d1));

		// cursor to store the result
		DBCursor c = coll.find();
		// iterate through cursor
		try {
			while (c.hasNext()) {

				System.out.println(c.next());
			}
		} finally {
			c.close();
		}

	}

}

Above program produces following output.


{ "serverUsed" : "127.0.0.1:27017" , "users" : [ { "_id" : "admin.journaldev" , "user" : "journaldev" , "db" : "admin" , "roles" : [ { "role" : "readWrite" , "db" : "admin"} , { "role" : "readAnyDatabase" , "db" : "admin"} , { "role" : "userAdminAnyDatabase" , "db" : "admin"}] , "inheritedRoles" : [ { "role" : "readWrite" , "db" : "admin"} , { "role" : "readAnyDatabase" , "db" : "admin"} , { "role" : "userAdminAnyDatabase" , "db" : "admin"}] , "inheritedPrivileges" : [ { "resource" : { "db" : "admin" , "collection" : ""} , "actions" : [ "collStats" , "convertToCapped" , "createCollection" , "createIndex" , "dbHash" , "dbStats" , "dropCollection" , "dropIndex" , "emptycapped" , "find" , "insert" , "killCursors" , "planCacheRead" , "remove" , "renameCollectionSameDB" , "update"]} , { "resource" : { "db" : "admin" , "collection" : "system.indexes"} , "actions" : [ "collStats" , "dbHash" , "dbStats" , "find" , "killCursors" , "planCacheRead"]} , { "resource" : { "db" : "admin" , "collection" : "system.js"} , "actions" : [ "collStats" , "convertToCapped" , "createCollection" , "createIndex" , "dbHash" , "dbStats" , "dropCollection" , "dropIndex" , "emptycapped" , "find" , "insert" , "killCursors" , "planCacheRead" , "remove" , "renameCollectionSameDB" , "update"]} , { "resource" : { "db" : "admin" , "collection" : "system.namespaces"} , "actions" : [ "collStats" , "dbHash" , "dbStats" , "find" , "killCursors" , "planCacheRead"]} , { "resource" : { "db" : "" , "collection" : ""} , "actions" : [ "changeCustomData" , "changePassword" , "collStats" , "createRole" , "createUser" , "dbHash" , "dbStats" , "dropRole" , "dropUser" , "find" , "grantRole" , "killCursors" , "planCacheRead" , "revokeRole" , "viewRole" , "viewUser"]} , { "resource" : { "cluster" : true} , "actions" : [ "authSchemaUpgrade" , "invalidateUserCache" , "listDatabases"]} , { "resource" : { "db" : "" , "collection" : "system.indexes"} , "actions" : [ "collStats" , "dbHash" , "dbStats" , "find" , "killCursors" , "planCacheRead"]} , { "resource" : { "db" : "" , "collection" : "system.js"} , "actions" : [ "collStats" , "dbHash" , "dbStats" , "find" , "killCursors" , "planCacheRead"]} , { "resource" : { "db" : "" , "collection" : "system.namespaces"} , "actions" : [ "collStats" , "dbHash" , "dbStats" , "find" , "killCursors" , "planCacheRead"]} , { "resource" : { "db" : "" , "collection" : "system.users"} , "actions" : [ "collStats" , "dbHash" , "dbStats" , "find" , "killCursors" , "planCacheRead"]} , { "resource" : { "db" : "admin" , "collection" : "system.users"} , "actions" : [ "collStats" , "dbHash" , "dbStats" , "find" , "killCursors" , "planCacheRead"]} , { "resource" : { "db" : "admin" , "collection" : "system.roles"} , "actions" : [ "collStats" , "dbHash" , "dbStats" , "find" , "killCursors" , "planCacheRead"]} , { "resource" : { "db" : "admin" , "collection" : "system.version"} , "actions" : [ "collStats" , "dbHash" , "dbStats" , "find" , "killCursors" , "planCacheRead"]} , { "resource" : { "db" : "admin" , "collection" : "system.new_users"} , "actions" : [ "collStats" , "dbHash" , "dbStats" , "find" , "killCursors" , "planCacheRead"]} , { "resource" : { "db" : "admin" , "collection" : "system.backup_users"} , "actions" : [ "collStats" , "dbHash" , "dbStats" , "find" , "killCursors" , "planCacheRead"]}]}] , "ok" : 1.0}
{ "_id" : { "$oid" : "5493dffbc26bbdbbe1ba044f"} , "name" : "Toyota"}
{ "_id" : { "$oid" : "5493e21f036442627943d846"} , "name" : "Qualis"}

That’s all for authentication in MongoDB using simple user/password mechanism.

Comments

  1. Hafeez says:

    MongoCredential.createCredential() is not supported with mongo java driver 2.12.3. I changed the pom to look for 2.13.2 and got it resolved

Leave a Reply

Your email address will not be published. Required fields are marked *

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages