Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PYTHON-4922 Remove Support for MONGODB-CR Authentication #1978

Merged
merged 5 commits into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 <https://docs.python.org/3.13/whatsnew/3.13.html#whatsnew313-free-threaded-cpython>`_.
- :attr:`~pymongo.asynchronous.mongo_client.AsyncMongoClient.address` and
Expand Down
21 changes: 1 addition & 20 deletions doc/examples/authentication.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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:[email protected]/?authSource=the_database&authMechanism=MONGODB-CR"
>>> client = MongoClient(uri)

Default Authentication Mechanism
--------------------------------

Expand Down Expand Up @@ -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:[email protected]/?authMechanism=PLAIN"
Expand Down
16 changes: 0 additions & 16 deletions pymongo/asynchronous/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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]
Expand Down
1 change: 0 additions & 1 deletion pymongo/auth_shared.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
MECHANISMS = frozenset(
[
"GSSAPI",
"MONGODB-CR",
"MONGODB-OIDC",
"MONGODB-X509",
"MONGODB-AWS",
Expand Down
16 changes: 0 additions & 16 deletions pymongo/synchronous/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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]
Expand Down
41 changes: 0 additions & 41 deletions test/auth/legacy/connection-string.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
27 changes: 3 additions & 24 deletions test/connection_string/test/valid-auth.json
Original file line number Diff line number Diff line change
Expand Up @@ -220,29 +220,8 @@
"options": null
},
{
"description": "Escaped user info and database (MONGODB-CR)",
"uri": "mongodb://%24am:f%3Azzb%40z%2Fz%[email protected]/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://!$&'()*+,;=:!$&'()*+,;[email protected]/admin?authMechanism=MONGODB-CR",
"description": "Subdelimiters in user/pass don't need escaping (PLAIN)",
"uri": "mongodb://!$&'()*+,;=:!$&'()*+,;[email protected]/admin?authMechanism=PLAIN",
"valid": true,
"warning": false,
"hosts": [
Expand All @@ -258,7 +237,7 @@
"db": "admin"
},
"options": {
"authmechanism": "MONGODB-CR"
"authmechanism": "PLAIN"
}
},
{
Expand Down
4 changes: 2 additions & 2 deletions test/connection_string/test/valid-options.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"tests": [
{
"description": "Option names are normalized to lowercase",
"uri": "mongodb://alice:[email protected]/admin?AUTHMechanism=MONGODB-CR",
"uri": "mongodb://alice:[email protected]/admin?AUTHMechanism=PLAIN",
"valid": true,
"warning": false,
"hosts": [
Expand All @@ -18,7 +18,7 @@
"db": "admin"
},
"options": {
"authmechanism": "MONGODB-CR"
"authmechanism": "PLAIN"
}
},
{
Expand Down
27 changes: 0 additions & 27 deletions test/test_uri_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
)
Expand Down Expand Up @@ -294,32 +293,6 @@ def test_parse_uri(self):
self.assertEqual(res, parse_uri("mongodb://localhost/?readPreference=secondary"))

# Various authentication tests
res = copy.deepcopy(orig)
res["options"] = {"authmechanism": "MONGODB-CR"}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than removing these tests, can you update then to use SCRAM-SHA-256?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

res["username"] = "user"
res["password"] = "password"
self.assertEqual(
res, parse_uri("mongodb://user:password@localhost/?authMechanism=MONGODB-CR")
)

res = copy.deepcopy(orig)
res["options"] = {"authmechanism": "MONGODB-CR", "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"
),
)

res = copy.deepcopy(orig)
res["options"] = {"authmechanism": "MONGODB-CR"}
res["username"] = "user"
res["password"] = ""
self.assertEqual(res, parse_uri("mongodb://user:@localhost/?authMechanism=MONGODB-CR"))

res = copy.deepcopy(orig)
res["username"] = "[email protected]"
res["password"] = "password"
Expand Down
Loading