mongodb / flask-pymongo

PyMongo support for Flask applications
BSD 2-Clause "Simplified" License
721 stars 175 forks source link

Authentication issue #132

Closed cliveyg closed 5 years ago

cliveyg commented 5 years ago

I had an authentication issue when using flask-pymongo. More details can be found on StackOverflow but a basic summary is as follows:

When using flask_pymongo I kept receiving an authenication error when attempting any operation after initialising flask_pymongo via my create_app method (I was using the application factory design pattern).

from app.extensions import mongo

def create_app(config_class=Config):

    app = Flask(__name__)
    # set app configs
    app.config.from_object(config_class)
    # initial flask extensions
    mongo.init_app(app)
    return app

Error message: Error message: pymongo.errors.OperationFailure: Authentication failed.

I used the MONGO_URI parameter and my setup was:

Python Version: 3.6

Flask Version: 1.1.1

Pymongo Version: 3.8.0

Flask-PyMongo version: 2.3.0

Changing my password fixed the issue. My original password was very long (25 characters) and did contain the following characters as well as normal alphanumerics:

)+{*

The error may be in PyMongo rather than flask_pymongo as I didn't do any more debugging after changing my password. Mongo itself gave no errors when creating a user with the 'bad' password via the cli but again I didn't do any more investigations after realizing the password change fixed my issue so the issue could lie with Mongo itself.

dcrosta commented 5 years ago

Yes, I think this is a bug in PyMongo's URI parser -- it seems to be treating the + in the password as a space character (like would happen in a URL). If you want to use "+" in your password, you can escape it as %2B:

>>> conn = pymongo.MongoClient("mongodb://localhost:32839/admin")
>>> conn.admin.command("createUser", "admin", pwd="foo)+{*", roles=["root"])
{'ok': 1.0}
>>> conn = pymongo.MongoClient("mongodb://admin:foo)+{*@localhost:32839/test?authSource=admin")
>>> conn.test.foo.insert_one({"hello": "world"})
Traceback (most recent call last):
[...]
    raise OperationFailure(msg % errmsg, code, response)
pymongo.errors.OperationFailure: Authentication failed.
>>> conn = pymongo.MongoClient("mongodb://admin:foo)%2B{*@localhost:32839/test?authSource=admin")
>>> conn.test.foo.insert_one({"hello": "world"})
<pymongo.results.InsertOneResult object at 0x10e7a00c8>
>>>

I'm going to close this as it seems not to be an issue with Flask-PyMongo, but I'd suggest you follow up with the PyMongo authors on the MongoDB JIRA.