Skip to content

Commit 679c93a

Browse files
authored
Disallow comma character in authMechanismProperties (#1412)
JAVA-5486 # Conflicts: # driver-sync/src/test/functional/com/mongodb/internal/connection/OidcAuthenticationProseTests.java
1 parent fe3e406 commit 679c93a

File tree

5 files changed

+27
-52
lines changed

5 files changed

+27
-52
lines changed

driver-core/src/main/com/mongodb/ConnectionString.java

Lines changed: 3 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
import java.net.URLDecoder;
3939
import java.nio.charset.StandardCharsets;
4040
import java.util.ArrayList;
41-
import java.util.Arrays;
4241
import java.util.Collections;
4342
import java.util.HashMap;
4443
import java.util.HashSet;
@@ -240,9 +239,7 @@
240239
* mechanism (the default).
241240
* </li>
242241
* <li>{@code authMechanismProperties=PROPERTY_NAME:PROPERTY_VALUE,PROPERTY_NAME2:PROPERTY_VALUE2}: This option allows authentication
243-
* mechanism properties to be set on the connection string. Property values must be percent-encoded individually, when
244-
* special characters are used, including {@code ,} (comma), {@code =}, {@code +}, {@code &}, and {@code %}. The
245-
* entire substring following the {@code =} should not itself be encoded.
242+
* mechanism properties to be set on the connection string.
246243
* </li>
247244
* <li>{@code gssapiServiceName=string}: This option only applies to the GSSAPI mechanism and is used to alter the service name.
248245
* Deprecated, please use {@code authMechanismProperties=SERVICE_NAME:string} instead.
@@ -908,7 +905,6 @@ private MongoCredential createCredentials(final Map<String, List<String>> option
908905
}
909906
}
910907

911-
912908
MongoCredential credential = null;
913909
if (mechanism != null) {
914910
credential = createMongoCredentialWithMechanism(mechanism, userName, password, authSource, gssapiServiceName);
@@ -926,9 +922,6 @@ private MongoCredential createCredentials(final Map<String, List<String>> option
926922
}
927923
String key = mechanismPropertyKeyValue[0].trim().toLowerCase();
928924
String value = mechanismPropertyKeyValue[1].trim();
929-
if (decodeValueOfKeyValuePair(credential.getMechanism())) {
930-
value = urldecode(value);
931-
}
932925
if (MECHANISM_KEYS_DISALLOWED_IN_CONNECTION_STRING.contains(key)) {
933926
throw new IllegalArgumentException(format("The connection string contains disallowed mechanism properties. "
934927
+ "'%s' must be set on the credential programmatically.", key));
@@ -944,27 +937,6 @@ private MongoCredential createCredentials(final Map<String, List<String>> option
944937
return credential;
945938
}
946939

947-
private static boolean decodeWholeOptionValue(final boolean isOidc, final String key) {
948-
// The "whole option value" is the entire string following = in an option,
949-
// including separators when the value is a list or list of key-values.
950-
// This is the original parsing behaviour, but implies that users can
951-
// encode separators (much like they might with URL parameters). This
952-
// behaviour implies that users cannot encode "key-value" values that
953-
// contain a comma, because this will (after this "whole value decoding)
954-
// be parsed as a key-value separator, rather than part of a value.
955-
return !(isOidc && key.equals("authmechanismproperties"));
956-
}
957-
958-
private static boolean decodeValueOfKeyValuePair(@Nullable final String mechanismName) {
959-
// Only authMechanismProperties should be individually decoded, and only
960-
// when the mechanism is OIDC. These will not have been decoded.
961-
return AuthenticationMechanism.MONGODB_OIDC.getMechanismName().equals(mechanismName);
962-
}
963-
964-
private static boolean isOidc(final List<String> options) {
965-
return options.contains("authMechanism=" + AuthenticationMechanism.MONGODB_OIDC.getMechanismName());
966-
}
967-
968940
private MongoCredential createMongoCredentialWithMechanism(final AuthenticationMechanism mechanism, final String userName,
969941
@Nullable final char[] password,
970942
@Nullable final String authSource,
@@ -1049,9 +1021,7 @@ private Map<String, List<String>> parseOptions(final String optionsPart) {
10491021
return optionsMap;
10501022
}
10511023

1052-
List<String> options = Arrays.asList(optionsPart.split("&|;"));
1053-
boolean isOidc = isOidc(options);
1054-
for (final String part : options) {
1024+
for (final String part : optionsPart.split("&|;")) {
10551025
if (part.isEmpty()) {
10561026
continue;
10571027
}
@@ -1063,10 +1033,7 @@ private Map<String, List<String>> parseOptions(final String optionsPart) {
10631033
if (valueList == null) {
10641034
valueList = new ArrayList<>(1);
10651035
}
1066-
if (decodeWholeOptionValue(isOidc, key)) {
1067-
value = urldecode(value);
1068-
}
1069-
valueList.add(value);
1036+
valueList.add(urldecode(value));
10701037
optionsMap.put(key, valueList);
10711038
} else {
10721039
throw new IllegalArgumentException(format("The connection string contains an invalid option '%s'. "

driver-core/src/main/com/mongodb/MongoCredential.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,9 @@ public final class MongoCredential {
267267
* Mechanism property key for specifying he URI of the target resource (sometimes called the audience),
268268
* used in some OIDC environments.
269269
*
270+
* <p>A TOKEN_RESOURCE with a comma character must be given as a `MongoClient` configuration and not as
271+
* part of the connection string. The TOKEN_RESOURCE value can contain a colon character.
272+
*
270273
* @see MongoCredential#ENVIRONMENT_KEY
271274
* @see #createOidcCredential(String)
272275
* @since 5.1

driver-core/src/test/resources/auth/legacy/connection-string.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,7 @@
565565
},
566566
{
567567
"description": "should handle a complicated url-encoded TOKEN_RESOURCE (MONGODB-OIDC)",
568-
"uri": "mongodb://user@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:azure,TOKEN_RESOURCE:abc%2Cd%25ef%3Ag%26hi",
568+
"uri": "mongodb://user@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:azure,TOKEN_RESOURCE:abcd%25ef%3Ag%26hi",
569569
"valid": true,
570570
"credential": {
571571
"username": "user",
@@ -574,7 +574,7 @@
574574
"mechanism": "MONGODB-OIDC",
575575
"mechanism_properties": {
576576
"ENVIRONMENT": "azure",
577-
"TOKEN_RESOURCE": "abc,d%ef:g&hi"
577+
"TOKEN_RESOURCE": "abcd%ef:g&hi"
578578
}
579579
}
580580
},

driver-core/src/test/resources/connection-string/valid-options.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,25 @@
2020
"options": {
2121
"authmechanism": "MONGODB-CR"
2222
}
23+
},
24+
{
25+
"description": "Colon in a key value pair",
26+
"uri": "mongodb://example.com/?authMechanism=MONGODB-OIDC&authMechanismProperties=TOKEN_RESOURCE:mongodb://test-cluster",
27+
"valid": true,
28+
"warning": false,
29+
"hosts": [
30+
{
31+
"type": "hostname",
32+
"host": "example.com",
33+
"port": null
34+
}
35+
],
36+
"auth": null,
37+
"options": {
38+
"authmechanismProperties": {
39+
"TOKEN_RESOURCE": "mongodb://test-cluster"
40+
}
41+
}
2342
}
2443
]
2544
}

driver-core/src/test/unit/com/mongodb/ConnectionStringUnitTest.java

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -39,20 +39,6 @@ void defaults() {
3939
assertAll(() -> assertNull(connectionStringDefault.getServerMonitoringMode()));
4040
}
4141

42-
@Test
43-
public void mustDecodeOidcIndividually() {
44-
String string = "abc,d!@#$%^&*;ef:ghi";
45-
// encoded tags will fail parsing with an "invalid read preference tag"
46-
// error if decoding is skipped.
47-
String encodedTags = encode("dc:ny,rack:1");
48-
ConnectionString cs = new ConnectionString(
49-
"mongodb://localhost/?readPreference=primaryPreferred&readPreferenceTags=" + encodedTags
50-
+ "&authMechanism=MONGODB-OIDC&authMechanismProperties="
51-
+ "ENVIRONMENT:azure,TOKEN_RESOURCE:" + encode(string));
52-
MongoCredential credential = Assertions.assertNotNull(cs.getCredential());
53-
assertEquals(string, credential.getMechanismProperty("TOKEN_RESOURCE", null));
54-
}
55-
5642
@Test
5743
public void mustDecodeNonOidcAsWhole() {
5844
// this string allows us to check if there is no double decoding

0 commit comments

Comments
 (0)