Skip to content

DRIVERS-2836 OIDC: Clarify that TOKEN_RESOURCE must be url-encoded #1569

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

Merged
merged 11 commits into from
Apr 29, 2024
27 changes: 17 additions & 10 deletions source/auth/auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down Expand Up @@ -1292,18 +1301,16 @@ Accept: application/json
Metadata: true
```

where `<resource>` is the value of the `TOKEN_RESOURCE` mechanism property and `<client_id>` 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 `<resource>` is the url-encoded value of the `TOKEN_RESOURCE` mechanism property and `<client_id>` 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:
Expand Down Expand Up @@ -1352,16 +1359,14 @@ with headers
Metadata-Flavor: Google
```

where `<resource>` is the value of the `TOKEN_RESOURCE` mechanism property. The timeout should equal the
where `<resource>` 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.
Expand Down Expand Up @@ -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.
Expand Down
60 changes: 60 additions & 0 deletions source/auth/tests/legacy/connection-string.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

44 changes: 44 additions & 0 deletions source/auth/tests/legacy/connection-string.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Member

@sanych-sun sanych-sun Apr 26, 2024

Choose a reason for hiding this comment

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

Is this Uri valid? Should we have : in the mongodb://test-cluster encoded as %3A? Having more then one value separator confuses our parser. And it's kind of ambiguous:
TOKEN_RESOURCE:mongodb://test-cluster
should it be parsed as TOKEN_RESOURCE=mongodb://test-cluster or TOKEN_RESOURCE:mongodb=//test-cluster

Copy link
Contributor

Choose a reason for hiding this comment

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

This usage is against the advice we give to users in the spec, but I think we should optimistically decode this (like this in Java), rather than failing. Although it is indeed ambiguous, I think we will never put a : in the name of any property (precisely because it is a separator).

Copy link
Member

Choose a reason for hiding this comment

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

Yep, can do the same, just want to double check if we see this as expected behavior.

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
Expand Down
7 changes: 2 additions & 5 deletions source/unified-test-format/unified-test-format.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down Expand Up @@ -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

Expand Down