33

My question is a specification of how can i validate username password for mongodb authentication through pymongo?.

I'm trying to connect to a MongoDB instance using PyMongo 3.2.2 and a URL that contains the user and password, as explained in MongoDB Docs. The difference is that the password I'm using contains a '@'.

At first I simply tried to connect without escaping, like this:

prefix = 'mongodb://'

user = 'user:passw_with_@_'

suffix = '@127.0.0.1:27001/'

conn = pymongo.MongoClient(prefix + user + suffix)

Naturally I got the following error:

InvalidURI: ':' or '@' characters in a username or password must be escaped according to RFC 2396.

So I tried escaping the user:pass part using urllib.quote() like this:

prefix = 'mongodb://'

user = urllib.quote('user:passw_with_@_')

suffix = '@127.0.0.1:27001/'

conn = pymongo.MongoClient(prefix + user + suffix)

but then I got a:

OperationFailure: Authentication failed.

(Important to say that using a GUI MongoDB Management Tool (Robomongo, if that matters) I'm able to connect to the MongoDB using the (real) address and credentials.)

Printing user variable in the code above generated a 'user:passw_with_%40_' String (that is '@' became '%40') and according to wikipedia that's the expected escaping.

I even tried escaping the @ with single and double backslashes (user = 'user:passw_with_\\@_' and user = 'user:passw_with_\@_'), but those failed with the InvalidURI exception.

TL;DR;

My question is: How do I escape a '@' in the password part of a MongoDB URL?

Community
  • 1
  • 1
gmauch
  • 1,316
  • 4
  • 25
  • 39

5 Answers5

54

You should be able to escape the password using urllib.quote(). Although you should only quote/escape the password, and exclude the username: ; otherwise the : will also be escaped into %3A.

For example:

import pymongo 
import urllib 

mongo_uri = "mongodb://username:" + urllib.parse.quote("p@ssword") + "@127.0.0.1:27001/"
client = pymongo.MongoClient(mongo_uri)

The above snippet was tested for MongoDB v3.2.x and PyMongo v3.2.2.

The example above assumed in the MongoDB URI connection string:

  • The user is created in the admin database.
  • The host mongod running on is 127.0.0.1 (localhost)
  • The port mongod assigned to is 27001
abe
  • 355
  • 2
  • 9
Wan B.
  • 18,367
  • 4
  • 54
  • 71
  • 28
    Python 3: `urllib.parse.quote` – luckydonald Oct 28 '16 at 10:37
  • There is a pending edit from Conor. Lacking any other way to address the editor directly, I'm hoping this comment will be read. Conor, your edit adds such good information that it should be an answer of its own. I rejected the edit, because it would serve (you and) the community better as an answer on its own. – Scott Mermelstein Jul 10 '18 at 13:59
11

Python 3.6.5 - PyMongo 3.7.0 version for connecting to an mlab instance:

from pymongo import MongoClient
import urllib.parse

username = urllib.parse.quote_plus('username')
password = urllib.parse.quote_plus('password')
client = MongoClient('mongodb://%s:%s@ds00000.mlab.com:000000/recipe_app_testing' % (username, password))

This is the only way I have managed to connect to the mlab MongoDB instance without using flask-pymongo spun up app, I needed to create fixtures for unit tests.

Python 3.6.5 - PyMongo 3.7.0 localhost version:

from pymongo import MongoClient
import urllib.parse 

username = urllib.parse.quote_plus('username')
password = urllib.parse.quote_plus('password')
client = MongoClient('mongodb://%s:%s@127.0.0.1:27001/' % (username, password))
TofferJ
  • 4,678
  • 1
  • 37
  • 49
Conor
  • 426
  • 7
  • 22
2

run in terminal :

python -m pip install pymongo[srv]

python file:

import pymongo
from pymongo import MongoClient
import urllib.parse

username = urllib.parse.quote_plus('username')
password = urllib.parse.quote_plus("password")

url = "mongodb+srv://{}:{}@cluster0-0000.mongodb.net/<dbname>?retryWrites=true&w=majority".format(username, password)
# url is just an example (your url will be different)

cluster = MongoClient(url)
db = cluster['Sample']
collection = db['temporary']
KailasMM
  • 106
  • 1
  • 5
1

Whenever you have '@' in your MongoDB password and would want to connect with your URI, simply replace it using

%40
Chukwunazaekpere
  • 906
  • 1
  • 6
  • 13
0

Just information:

MongoDB, pymongo and mongoengine cannot handle several symbols in a password;

Restrictions on Database Names for Windows

/\. "$*<>:|?

Restrictions on Database Names for Unix and Linux Systems

/\. "$

https://docs.mongodb.com/manual/reference/limits/#Restrictions-on-Field-Names

Escaping does not work when containing illegal symbols.

kujiy
  • 5,833
  • 1
  • 29
  • 35