diff --git a/doc/changelog.rst b/doc/changelog.rst index 29fddb7b5c..94d991868d 100644 --- a/doc/changelog.rst +++ b/doc/changelog.rst @@ -12,6 +12,7 @@ PyMongo 4.11 brings a number of changes including: - Dropped support for Python 3.8. - Dropped support for MongoDB 3.6. +- Dropped support for the MONGODB-CR authenticate mechanism, which is no longer supported by MongoDB 4.0+. - Added support for free-threaded Python with the GIL disabled. For more information see: `Free-threaded CPython `_. - :attr:`~pymongo.asynchronous.mongo_client.AsyncMongoClient.address` and diff --git a/doc/examples/authentication.rst b/doc/examples/authentication.rst index 6c89910f3c..b319df814c 100644 --- a/doc/examples/authentication.rst +++ b/doc/examples/authentication.rst @@ -76,24 +76,6 @@ For best performance on Python versions older than 2.7.8 install `backports.pbkd .. _backports.pbkdf2: https://pypi.python.org/pypi/backports.pbkdf2/ -MONGODB-CR ----------- - -.. warning:: MONGODB-CR was deprecated with the release of MongoDB 3.6 and - is no longer supported by MongoDB 4.0. - -Before MongoDB 3.0 the default authentication mechanism was MONGODB-CR, -the "MongoDB Challenge-Response" protocol:: - - >>> from pymongo import MongoClient - >>> client = MongoClient('example.com', - ... username='user', - ... password='password', - ... authMechanism='MONGODB-CR') - >>> - >>> uri = "mongodb://user:password@example.com/?authSource=the_database&authMechanism=MONGODB-CR" - >>> client = MongoClient(uri) - Default Authentication Mechanism -------------------------------- @@ -221,8 +203,7 @@ SASL PLAIN (RFC 4616) MongoDB Enterprise Edition version 2.6 and newer support the SASL PLAIN authentication mechanism, initially intended for delegating authentication -to an LDAP server. Using the PLAIN mechanism is very similar to MONGODB-CR. -These examples use the $external virtual database for LDAP support:: +to an LDAP server. These examples use the $external virtual database for LDAP support:: >>> from pymongo import MongoClient >>> uri = "mongodb://user:password@example.com/?authMechanism=PLAIN" diff --git a/pymongo/asynchronous/auth.py b/pymongo/asynchronous/auth.py index 1fb28f6c49..fc563ec48f 100644 --- a/pymongo/asynchronous/auth.py +++ b/pymongo/asynchronous/auth.py @@ -329,21 +329,6 @@ async def _authenticate_x509(credentials: MongoCredential, conn: AsyncConnection await conn.command("$external", cmd) -async def _authenticate_mongo_cr(credentials: MongoCredential, conn: AsyncConnection) -> None: - """Authenticate using MONGODB-CR.""" - source = credentials.source - username = credentials.username - password = credentials.password - # Get a nonce - response = await conn.command(source, {"getnonce": 1}) - nonce = response["nonce"] - key = _auth_key(nonce, username, password) - - # Actually authenticate - query = {"authenticate": 1, "user": username, "nonce": nonce, "key": key} - await conn.command(source, query) - - async def _authenticate_default(credentials: MongoCredential, conn: AsyncConnection) -> None: if conn.max_wire_version >= 7: if conn.negotiated_mechs: @@ -365,7 +350,6 @@ async def _authenticate_default(credentials: MongoCredential, conn: AsyncConnect _AUTH_MAP: Mapping[str, Callable[..., Coroutine[Any, Any, None]]] = { "GSSAPI": _authenticate_gssapi, - "MONGODB-CR": _authenticate_mongo_cr, "MONGODB-X509": _authenticate_x509, "MONGODB-AWS": _authenticate_aws, "MONGODB-OIDC": _authenticate_oidc, # type:ignore[dict-item] diff --git a/pymongo/auth_shared.py b/pymongo/auth_shared.py index 7e3acd9dfb..11d08ffe9c 100644 --- a/pymongo/auth_shared.py +++ b/pymongo/auth_shared.py @@ -34,7 +34,6 @@ MECHANISMS = frozenset( [ "GSSAPI", - "MONGODB-CR", "MONGODB-OIDC", "MONGODB-X509", "MONGODB-AWS", diff --git a/pymongo/synchronous/auth.py b/pymongo/synchronous/auth.py index 9a3477679d..7b370843c5 100644 --- a/pymongo/synchronous/auth.py +++ b/pymongo/synchronous/auth.py @@ -326,21 +326,6 @@ def _authenticate_x509(credentials: MongoCredential, conn: Connection) -> None: conn.command("$external", cmd) -def _authenticate_mongo_cr(credentials: MongoCredential, conn: Connection) -> None: - """Authenticate using MONGODB-CR.""" - source = credentials.source - username = credentials.username - password = credentials.password - # Get a nonce - response = conn.command(source, {"getnonce": 1}) - nonce = response["nonce"] - key = _auth_key(nonce, username, password) - - # Actually authenticate - query = {"authenticate": 1, "user": username, "nonce": nonce, "key": key} - conn.command(source, query) - - def _authenticate_default(credentials: MongoCredential, conn: Connection) -> None: if conn.max_wire_version >= 7: if conn.negotiated_mechs: @@ -360,7 +345,6 @@ def _authenticate_default(credentials: MongoCredential, conn: Connection) -> Non _AUTH_MAP: Mapping[str, Callable[..., None]] = { "GSSAPI": _authenticate_gssapi, - "MONGODB-CR": _authenticate_mongo_cr, "MONGODB-X509": _authenticate_x509, "MONGODB-AWS": _authenticate_aws, "MONGODB-OIDC": _authenticate_oidc, # type:ignore[dict-item] diff --git a/test/auth/legacy/connection-string.json b/test/auth/legacy/connection-string.json index 57fd9d4a11..ab559582ae 100644 --- a/test/auth/legacy/connection-string.json +++ b/test/auth/legacy/connection-string.json @@ -127,47 +127,6 @@ "uri": "mongodb://localhost/?authMechanism=GSSAPI", "valid": false }, - { - "description": "should recognize the mechanism (MONGODB-CR)", - "uri": "mongodb://user:password@localhost/?authMechanism=MONGODB-CR", - "valid": true, - "credential": { - "username": "user", - "password": "password", - "source": "admin", - "mechanism": "MONGODB-CR", - "mechanism_properties": null - } - }, - { - "description": "should use the database when no authSource is specified (MONGODB-CR)", - "uri": "mongodb://user:password@localhost/foo?authMechanism=MONGODB-CR", - "valid": true, - "credential": { - "username": "user", - "password": "password", - "source": "foo", - "mechanism": "MONGODB-CR", - "mechanism_properties": null - } - }, - { - "description": "should use the authSource when specified (MONGODB-CR)", - "uri": "mongodb://user:password@localhost/foo?authMechanism=MONGODB-CR&authSource=bar", - "valid": true, - "credential": { - "username": "user", - "password": "password", - "source": "bar", - "mechanism": "MONGODB-CR", - "mechanism_properties": null - } - }, - { - "description": "should throw an exception if no username is supplied (MONGODB-CR)", - "uri": "mongodb://localhost/?authMechanism=MONGODB-CR", - "valid": false - }, { "description": "should recognize the mechanism (MONGODB-X509)", "uri": "mongodb://CN%3DmyName%2COU%3DmyOrgUnit%2CO%3DmyOrg%2CL%3DmyLocality%2CST%3DmyState%2CC%3DmyCountry@localhost/?authMechanism=MONGODB-X509", diff --git a/test/connection_string/test/valid-auth.json b/test/connection_string/test/valid-auth.json index 4f684ff185..12192fab4c 100644 --- a/test/connection_string/test/valid-auth.json +++ b/test/connection_string/test/valid-auth.json @@ -220,29 +220,8 @@ "options": null }, { - "description": "Escaped user info and database (MONGODB-CR)", - "uri": "mongodb://%24am:f%3Azzb%40z%2Fz%3D@127.0.0.1/admin%3F?authMechanism=MONGODB-CR", - "valid": true, - "warning": false, - "hosts": [ - { - "type": "ipv4", - "host": "127.0.0.1", - "port": null - } - ], - "auth": { - "username": "$am", - "password": "f:zzb@z/z=", - "db": "admin?" - }, - "options": { - "authmechanism": "MONGODB-CR" - } - }, - { - "description": "Subdelimiters in user/pass don't need escaping (MONGODB-CR)", - "uri": "mongodb://!$&'()*+,;=:!$&'()*+,;=@127.0.0.1/admin?authMechanism=MONGODB-CR", + "description": "Subdelimiters in user/pass don't need escaping (PLAIN)", + "uri": "mongodb://!$&'()*+,;=:!$&'()*+,;=@127.0.0.1/admin?authMechanism=PLAIN", "valid": true, "warning": false, "hosts": [ @@ -258,7 +237,7 @@ "db": "admin" }, "options": { - "authmechanism": "MONGODB-CR" + "authmechanism": "PLAIN" } }, { diff --git a/test/connection_string/test/valid-options.json b/test/connection_string/test/valid-options.json index 3c79fe7ae5..6c86172d08 100644 --- a/test/connection_string/test/valid-options.json +++ b/test/connection_string/test/valid-options.json @@ -2,7 +2,7 @@ "tests": [ { "description": "Option names are normalized to lowercase", - "uri": "mongodb://alice:secret@example.com/admin?AUTHMechanism=MONGODB-CR", + "uri": "mongodb://alice:secret@example.com/admin?AUTHMechanism=PLAIN", "valid": true, "warning": false, "hosts": [ @@ -18,7 +18,7 @@ "db": "admin" }, "options": { - "authmechanism": "MONGODB-CR" + "authmechanism": "PLAIN" } }, { diff --git a/test/test_uri_parser.py b/test/test_uri_parser.py index 2a68e9a2cd..f95717e95f 100644 --- a/test/test_uri_parser.py +++ b/test/test_uri_parser.py @@ -142,7 +142,6 @@ def test_split_options(self): self.assertEqual({"fsync": True}, split_options("fsync=true")) self.assertEqual({"fsync": False}, split_options("fsync=false")) self.assertEqual({"authmechanism": "GSSAPI"}, split_options("authMechanism=GSSAPI")) - self.assertEqual({"authmechanism": "MONGODB-CR"}, split_options("authMechanism=MONGODB-CR")) self.assertEqual( {"authmechanism": "SCRAM-SHA-1"}, split_options("authMechanism=SCRAM-SHA-1") ) @@ -295,30 +294,30 @@ def test_parse_uri(self): # Various authentication tests res = copy.deepcopy(orig) - res["options"] = {"authmechanism": "MONGODB-CR"} + res["options"] = {"authmechanism": "SCRAM-SHA-256"} res["username"] = "user" res["password"] = "password" self.assertEqual( - res, parse_uri("mongodb://user:password@localhost/?authMechanism=MONGODB-CR") + res, parse_uri("mongodb://user:password@localhost/?authMechanism=SCRAM-SHA-256") ) res = copy.deepcopy(orig) - res["options"] = {"authmechanism": "MONGODB-CR", "authsource": "bar"} + res["options"] = {"authmechanism": "SCRAM-SHA-256", "authsource": "bar"} res["username"] = "user" res["password"] = "password" res["database"] = "foo" self.assertEqual( res, parse_uri( - "mongodb://user:password@localhost/foo?authSource=bar;authMechanism=MONGODB-CR" + "mongodb://user:password@localhost/foo?authSource=bar;authMechanism=SCRAM-SHA-256" ), ) res = copy.deepcopy(orig) - res["options"] = {"authmechanism": "MONGODB-CR"} + res["options"] = {"authmechanism": "SCRAM-SHA-256"} res["username"] = "user" res["password"] = "" - self.assertEqual(res, parse_uri("mongodb://user:@localhost/?authMechanism=MONGODB-CR")) + self.assertEqual(res, parse_uri("mongodb://user:@localhost/?authMechanism=SCRAM-SHA-256")) res = copy.deepcopy(orig) res["username"] = "user@domain.com"