41

I have installed mongodb and enabled auth. and its working find. I can connect it from remote notebook using robomongo application:

Host: SERVER_IP
PORT: 27017
DATEBASE: prod-db
USERNAME: user_name
PASS: user_password
Auth Mechanism: MONGODB-CR

and We can connect from server shell locally using:

$ mongo prod-db -u user_name -p user_password

Everything works fine, but when we try it using pymongo api. authentications failed. below is the python code:

from pymongo import MongoClient

client = MongoClient()
client.prod_db.authenticate('user_name', 'user_password', mechanism='MONGODB-CR')
db = client.prod_db
result = db.users.find()

for document in result:
    print(document)

Tools used:

python 2.7
pymongo versiob 3.3.1
MongoDB shell version: 2.6.10
$ mongod --version
db version v2.6.10
2016-10-31T16:34:59.868+0000 git version: nogitversion
2016-10-31T16:34:59.868+0000 OpenSSL version: OpenSSL 1.0.2g  1 Mar 2016

Error trace:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/pymongo/database.py", line 1018, in authenticate
    connect=True)
  File "/usr/local/lib/python2.7/dist-packages/pymongo/mongo_client.py", line 444, in _cache_credentials
    sock_info.authenticate(credentials)
  File "/usr/local/lib/python2.7/dist-packages/pymongo/pool.py", line 343, in authenticate
    auth.authenticate(credentials, self)
  File "/usr/local/lib/python2.7/dist-packages/pymongo/auth.py", line 464, in authenticate
    auth_func(credentials, sock_info)
  File "/usr/local/lib/python2.7/dist-packages/pymongo/auth.py", line 439, in _authenticate_mongo_cr
    sock_info.command(source, query)
  File "/usr/local/lib/python2.7/dist-packages/pymongo/pool.py", line 239, in command
    read_concern)
  File "/usr/local/lib/python2.7/dist-packages/pymongo/network.py", line 102, in command
    helpers._check_command_response(response_doc, None, allowable_errors)
  File "/usr/local/lib/python2.7/dist-packages/pymongo/helpers.py", line 205, in _check_command_response
    raise OperationFailure(msg % errmsg, code, response)

Solution: problem was with database name, following code works fine:

from pymongo import MongoClient

client = MongoClient('mongodb://user_name:user_password@localhost:27017/prod-db')
db = client['prod-db']

result = db.users.find()
for document in result:
    print document
sharafjaffri
  • 2,134
  • 3
  • 30
  • 47
  • Looks like the user only access to the database specified. So you have to include the full db path to let mongo know that you are only interested authenticating against that particular database. – F.O.O Mar 08 '20 at 11:44

5 Answers5

60

Please try something like this:

client = MongoClient("mongodb://user_name:user_password@SERVER_IP/prod-db")
db = client['prod-db']
milos.ai
  • 3,882
  • 7
  • 31
  • 33
32

If you've tried the above answers (from milos.ai) and you're still getting an error:

pymongo.errors.OperationFailure: Authentication failed.

There's a good chance you need to add ?authSource=admin to the end of your uri.

Here's a working solution that I'm using with MongoDB server version 4.2.6 and MongoDB shell version v3.6.9.

from pymongo import MongoClient

# Replace these with your server details
MONGO_HOST = "XX.XXX.XXX.XXX" 
MONGO_PORT = "27017"
MONGO_DB = "database"
MONGO_USER = "admin"
MONGO_PASS = "pass"

uri = "mongodb://{}:{}@{}:{}/{}?authSource=admin".format(MONGO_USER, MONGO_PASS, MONGO_HOST, MONGO_PORT, MONGO_DB)
client = MongoClient(uri)

And if you're using command line, you'll get the same fix by adding the argument --authenticationDatabase admin

Nathan
  • 541
  • 5
  • 6
16

For pymongo,

Try below for MongoDB 4:

Add authSource : This is the name of the database that has the collection with the user credentials.

Ex:

client = MongoClient(host=<<hostname>>,
                     port=<<port>>, 
                     username=<<user_name>>, 
                     password=<<password>>,
                    authSource="admin")
db_obj = client[db_name]

Edit 1: I have tried this on Mongo 3.x version as well. Working for that too.

Harsha Biyani
  • 7,049
  • 9
  • 37
  • 61
3

This worked for me ....

import pymongo

client = pymongo.MongoClient("mongodb://username:12%40password@ip:27017/sample_db",authSource="admin") 
db = client['sample_db']

Remember if you have special characters in your password (e.g. #,@) you will need to encode them (see %40) in the password. If you do not do authSource="admin" you will receive authentication errors. username - your mongodb username, ip - ip address as this assumes database is hosted on a remote server. sample_db is the database that you would like to access.

user8291021
  • 326
  • 2
  • 9
0

I solved my similar problem like below;

As pymongo documentation state, you should use urllib for username and pass. https://pymongo.readthedocs.io/en/stable/examples/authentication.html

my code is here;

import os, urllib

user = urllib.parse.quote_plus(os.environ.get('MONGO_USER'))
password = urllib.parse.quote_plus(os.environ.get('MONGO_PASS'))

uri = "mongodb://{}:{}@{}:{}".format(user, password, os.environ.get('MONGO_HOST'), os.environ.get('MONGO_PORT'))
## if you have an admin user you should not specify any database name in uri. After connection established you can call get_database('your_db_name')
client = MongoClient(uri)

Note: Authentication requires a username, a password, and a database name. The default database name is “admin”, this can be overridden with the authSource option. So you do not have to specify authSource if you have a root user which can be accessed any database. Default is already .

Tuncay Elvanagac
  • 1,048
  • 11
  • 13