'How to escape @ in a password in pymongo connection?

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?



Solution 1:[1]

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.quote("p@ssword") + "@127.0.0.1:27001/"
client = pymongo.MongoClient(mongo_uri)

The above snippet was tested for MongoDB v3.2.x, Python v2.7, 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

For Python 3.x, you can utilise urllib.parse.quote() to replace special characters in your password using the %xx escape. An example of the same:

urllib.parse.quote("p@ssword")

Solution 2:[2]

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:%[email protected]: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:%[email protected]:27001/' % (username, password))

Solution 3:[3]

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']

Solution 4:[4]

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.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Prabhatika Vij
Solution 2 TofferJ
Solution 3 BrainCity
Solution 4 kujiy