From c59c9321409cd6db9b664f86c3e15854045dafd1 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Mon, 29 Apr 2024 15:42:55 -0500 Subject: [PATCH] DRIVERS-2836 OIDC: Clarify that TOKEN_RESOURCE must be url-encoded (#1569) --- source/auth/auth.md | 27 +++++---- .../auth/tests/legacy/connection-string.json | 60 +++++++++++++++++++ .../auth/tests/legacy/connection-string.yml | 44 ++++++++++++++ .../unified-test-format.md | 7 +-- 4 files changed, 123 insertions(+), 15 deletions(-) diff --git a/source/auth/auth.md b/source/auth/auth.md index ccd1b8be46..918957b92b 100644 --- a/source/auth/auth.md +++ b/source/auth/auth.md @@ -1201,6 +1201,15 @@ in the MONGODB-OIDC specification, including sections or blocks that specificall #### [MongoCredential](#mongocredential) Properties +> [!NOTE] +> Drivers MUST NOT url-decode the entire `authMechanismProperties` given in an connection string when the +> `authMechanism` is `MONGODB-OIDC`. This is because the `TOKEN_RESOURCE` itself will typically be a URL and may contain +> a `,` character. The values of the individual `authMechanismProperties` MUST still be url-decoded when given as part +> of the connection string, and MUST NOT be url-decoded when not given as part of the connection string, such as through +> a `MongoClient` or `Credential` property. Drivers MUST parse the `TOKEN_RESOURCE` by splitting only on the first `:` +> character. Drivers MUST document that users must url-encode `TOKEN_RESOURCE` when it is provided in the connection +> string and it contains and of the special characters in \[`,`, `+`, `&`, `%`\]. + - username\ MAY be specified. Its meaning varies depending on the OIDC provider integration used. @@ -1292,18 +1301,16 @@ Accept: application/json Metadata: true ``` -where `` is the value of the `TOKEN_RESOURCE` mechanism property and `` is the `username` from the -connection string. If a `username` is not provided, the `client_id` query parameter should be omitted. The timeout -should equal the `callbackTimeoutMS` parameter given to the callback. - -Example code for the above using curl, where `$TOKEN_RESOURCE` is the value of the `TOKEN_RESOURCE` mechanism property. +where `` is the url-encoded value of the `TOKEN_RESOURCE` mechanism property and `` is the +`username` from the connection string. If a `username` is not provided, the `client_id` query parameter should be +omitted. The timeout should equal the `callbackTimeoutMS` parameter given to the callback. ```bash curl -X GET \ -H "Accept: application/json" \ -H "Metadata: true" \ --max-time $CALLBACK_TIMEOUT_MS \ - "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=$TOKEN_RESOURCE" + "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=$ENCODED_TOKEN_RESOURCE" ``` The JSON response will be in this format: @@ -1352,16 +1359,14 @@ with headers Metadata-Flavor: Google ``` -where `` is the value of the `TOKEN_RESOURCE` mechanism property. The timeout should equal the +where `` is the url-encoded value of the `TOKEN_RESOURCE` mechanism property. The timeout should equal the `callbackTimeoutMS` parameter given to the callback. -Example code for the above using curl, where `$TOKEN_RESOURCE` is the value of the `TOKEN_RESOURCE` mechanism property. - ```bash curl -X GET \ -H "Metadata-Flavor: Google" \ --max-time $CALLBACK_TIMEOUT_MS \ - "http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?audience=$TOKEN_RESOURCE" + "http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?audience=$ENCODED_TOKEN_RESOURCE" ``` The response body will be the access token itself. @@ -2044,6 +2049,8 @@ to EC2 instance metadata in ECS, for security reasons, Amazon states it's best p ## Changelog +- 2024-04-24: Clarify that TOKEN_RESOURCE for MONGODB-OIDC must be url-encoded. + - 2024-04-22: Fix API description for GCP built-in OIDC provider. - 2024-04-22: Updated OIDC authentication flow and prose tests. diff --git a/source/auth/tests/legacy/connection-string.json b/source/auth/tests/legacy/connection-string.json index e4a03a0d9c..f4c7f8c88e 100644 --- a/source/auth/tests/legacy/connection-string.json +++ b/source/auth/tests/legacy/connection-string.json @@ -569,6 +569,66 @@ } } }, + { + "description": "should accept a url-encoded TOKEN_RESOURCE (MONGODB-OIDC)", + "uri": "mongodb://user@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:azure,TOKEN_RESOURCE:mongodb%3A%2F%2Ftest-cluster", + "valid": true, + "credential": { + "username": "user", + "password": null, + "source": "$external", + "mechanism": "MONGODB-OIDC", + "mechanism_properties": { + "ENVIRONMENT": "azure", + "TOKEN_RESOURCE": "mongodb://test-cluster" + } + } + }, + { + "description": "should accept an un-encoded TOKEN_RESOURCE (MONGODB-OIDC)", + "uri": "mongodb://user@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:azure,TOKEN_RESOURCE:mongodb://test-cluster", + "valid": true, + "credential": { + "username": "user", + "password": null, + "source": "$external", + "mechanism": "MONGODB-OIDC", + "mechanism_properties": { + "ENVIRONMENT": "azure", + "TOKEN_RESOURCE": "mongodb://test-cluster" + } + } + }, + { + "description": "should handle a complicated url-encoded TOKEN_RESOURCE (MONGODB-OIDC)", + "uri": "mongodb://user@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:azure,TOKEN_RESOURCE:abc%2Cd%25ef%3Ag%26hi", + "valid": true, + "credential": { + "username": "user", + "password": null, + "source": "$external", + "mechanism": "MONGODB-OIDC", + "mechanism_properties": { + "ENVIRONMENT": "azure", + "TOKEN_RESOURCE": "abc,d%ef:g&hi" + } + } + }, + { + "description": "should url-encode a TOKEN_RESOURCE (MONGODB-OIDC)", + "uri": "mongodb://user@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:azure,TOKEN_RESOURCE:a$b", + "valid": true, + "credential": { + "username": "user", + "password": null, + "source": "$external", + "mechanism": "MONGODB-OIDC", + "mechanism_properties": { + "ENVIRONMENT": "azure", + "TOKEN_RESOURCE": "a$b" + } + } + }, { "description": "should accept a username and throw an error for a password with azure provider (MONGODB-OIDC)", "uri": "mongodb://user:pass@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:azure,TOKEN_RESOURCE:foo", diff --git a/source/auth/tests/legacy/connection-string.yml b/source/auth/tests/legacy/connection-string.yml index cf10cbf8db..c88eb1edce 100644 --- a/source/auth/tests/legacy/connection-string.yml +++ b/source/auth/tests/legacy/connection-string.yml @@ -412,6 +412,50 @@ tests: mechanism_properties: ENVIRONMENT: azure TOKEN_RESOURCE: foo +- description: should accept a url-encoded TOKEN_RESOURCE (MONGODB-OIDC) + uri: mongodb://user@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:azure,TOKEN_RESOURCE:mongodb%3A%2F%2Ftest-cluster + valid: true + credential: + username: user + password: null + source: $external + mechanism: MONGODB-OIDC + mechanism_properties: + ENVIRONMENT: azure + TOKEN_RESOURCE: 'mongodb://test-cluster' +- description: should accept an un-encoded TOKEN_RESOURCE (MONGODB-OIDC) + uri: mongodb://user@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:azure,TOKEN_RESOURCE:mongodb://test-cluster + valid: true + credential: + username: user + password: null + source: $external + mechanism: MONGODB-OIDC + mechanism_properties: + ENVIRONMENT: azure + TOKEN_RESOURCE: 'mongodb://test-cluster' +- description: should handle a complicated url-encoded TOKEN_RESOURCE (MONGODB-OIDC) + uri: mongodb://user@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:azure,TOKEN_RESOURCE:abc%2Cd%25ef%3Ag%26hi + valid: true + credential: + username: user + password: null + source: $external + mechanism: MONGODB-OIDC + mechanism_properties: + ENVIRONMENT: azure + TOKEN_RESOURCE: 'abc,d%ef:g&hi' +- description: should url-encode a TOKEN_RESOURCE (MONGODB-OIDC) + uri: mongodb://user@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:azure,TOKEN_RESOURCE:a$b + valid: true + credential: + username: user + password: null + source: $external + mechanism: MONGODB-OIDC + mechanism_properties: + ENVIRONMENT: azure + TOKEN_RESOURCE: a$b - description: should accept a username and throw an error for a password with azure provider (MONGODB-OIDC) uri: mongodb://user:pass@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:azure,TOKEN_RESOURCE:foo valid: false diff --git a/source/unified-test-format/unified-test-format.md b/source/unified-test-format/unified-test-format.md index a0031935df..01158817b6 100644 --- a/source/unified-test-format/unified-test-format.md +++ b/source/unified-test-format/unified-test-format.md @@ -328,9 +328,7 @@ The structure of this object is as follows: matching a "sharded" topology, test runners MUST accept any type of sharded cluster (i.e. "sharded" implies "sharded-replicaset", but not vice versa). - The "sharded-replicaset" topology type is deprecated. MongoDB 3.6+ requires that all shard servers be replica sets - (see: - [release notes](https://www.mongodb.com/docs/manual/release-notes/3.6-upgrade-sharded-cluster/#shard-replica-sets)). + The "sharded-replicaset" topology type is deprecated. MongoDB 3.6+ requires that all shard servers be replica sets. Therefore, tests SHOULD use "sharded" instead of "sharded-replicaset" when targeting 3.6+ server versions in order to avoid unnecessary overhead. @@ -3330,8 +3328,7 @@ Each shard in the cluster is represented by a document in this collection. If th the `host` field will contain a single host. If the shard is backed by a replica set, the `host` field contain the name of the replica followed by a forward slash and a comma-delimited list of hosts. -Note: MongoDB 3.6+ requires that all shard servers be replica sets (see: -[release notes](https://www.mongodb.com/docs/manual/release-notes/3.6-upgrade-sharded-cluster/#shard-replica-sets)). +Note: MongoDB 3.6+ requires that all shard servers be replica sets. ## Design Rationale