From 6e09e499f40b67c66d633fd36b90eb0b721f8895 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Tue, 19 Mar 2024 07:50:02 -0500 Subject: [PATCH 01/25] DRIVERS-2836 Only invalidate cached OIDC access tokens if the server returns error 18 --- source/auth/auth.md | 26 +++++++------ source/auth/tests/mongodb-oidc.md | 38 +++++++++++++++++-- .../tests/unified/mongodb-oidc-no-retry.json | 10 ++--- .../tests/unified/mongodb-oidc-no-retry.yml | 12 +++--- 4 files changed, 61 insertions(+), 25 deletions(-) diff --git a/source/auth/auth.md b/source/auth/auth.md index d96016be9e..f8d521bd95 100644 --- a/source/auth/auth.md +++ b/source/auth/auth.md @@ -1575,8 +1575,8 @@ Use the following algorithm to authenticate a new connection: - Check if the the *Client Cache* has an access token. - If it does, cache the access token in the *Connection Cache* and perform a `One-Step` SASL conversation using the - access token in the *Client Cache*. If the server returns an error, invalidate that access token, sleep 100ms then - continue. + access token in the *Client Cache*. If the server returns a Authentication error (18), invalidate that access token, + sleep 100ms then continue. - Call the configured built-in provider integration or the OIDC callback to retrieve a new access token. - Cache the new access token in the *Client Cache* and *Connection Cache*. - Perform a `One-Step` SASL conversation using the new access token. Raise any errors to the user. @@ -1588,18 +1588,21 @@ def auth(connection): access_token, is_cache = get_access_token() # If there is a cached access token, try to authenticate with it. If - # authentication fails, it's possible the cached access token is expired. In + # authentication fails with an Authentication error (18), + # it's possible the cached access token is expired. In # that case, invalidate the access token, fetch a new access token, and try # to authenticate again. + # If the server fails for any other reason, do not clear the cache. if is_cache: try: connection.oidc_cache.access_token = access_token sasl_start(connection, payload={"jwt": access_token}) return - except ServerError: - invalidate(access_token) - sleep(0.1) - access_token, _ = get_access_token() + except ServerError as e: + if e.code == 18: + invalidate(access_token) + sleep(0.1) + access_token, _ = get_access_token() connection.oidc_cache.access_token = access_token sasl_start(connection, payload={"jwt": access_token}) @@ -1610,14 +1613,15 @@ authenticate a new connection when a [OIDC Human Callback](#oidc-human-callback) - Check if the *Client Cache* has an access token. - If it does, cache the access token in the *Connection Cache* and perform a [One-Step](#one-step) SASL conversation - using the access token. If the server returns an error, invalidate the access token token from the *Client Cache*, - clear the *Connection Cache*, and continue. + using the access token. If the server returns an Authentication error (18), invalidate the access token token from + the *Client Cache*, clear the *Connection Cache*, and continue. If the server returns another error, continue. - Check if the *Client Cache* has a refresh token. - If it does, call the [OIDC Human Callback](#oidc-human-callback) with the cached refresh token and `IdpInfo` to get a new access token. Cache the new access token in the *Client Cache* and *Connection Cache*. Perform a [One-Step](#one-step) SASL conversation using the new access token. If the - [OIDC Human Callback](#oidc-human-callback) or the server return an error, invalidate the access token from the - *Client Cache*, clear the *Connection Cache*, and continue. + [OIDC Human Callback](#oidc-human-callback) or the server returns an Authentication error (18), invalidate the + access token from the *Client Cache*, clear the *Connection Cache*, and continue. If the server returns another + error, continue. - Start a new [Two-Step](#two-step) SASL conversation. - Run a `PrincipalStepRequest` to get the `IdpInfo`. - Call the [OIDC Human Callback](#oidc-human-callback) with the new `IdpInfo` to get a new access token and optional diff --git a/source/auth/tests/mongodb-oidc.md b/source/auth/tests/mongodb-oidc.md index f0a2053b2a..db66e5be3a 100644 --- a/source/auth/tests/mongodb-oidc.md +++ b/source/auth/tests/mongodb-oidc.md @@ -240,12 +240,14 @@ Drivers MUST be able to authenticate using OIDC callback(s) when there is one pr ```javascript { configureFailPoint: "failCommand", - mode: "alwaysOn", + mode: { + times: 1 + }, data: { failCommands: [ "saslStart" ], - errorCode: 20 + errorCode: 18 } } ``` @@ -261,17 +263,45 @@ Drivers MUST be able to authenticate using OIDC callback(s) when there is one pr ```javascript { configureFailPoint: "failCommand", - mode: "alwaysOn", + mode: { + times: 1 + }, + data: { + failCommands: [ + "saslStart" + ], + errorCode: 18 + } +} +``` + +- Perform a `find` operation that fails. +- Close the client. + +**3.3 Unexpected error code does not clear the cache** + +- Create a `MongoClient` with a human callback that returns a valid token. +- Set a fail point for `saslStart` commands of the form: + +```javascript +{ + configureFailPoint: "failCommand", + mode: { + times: 1 + }, data: { failCommands: [ "saslStart" ], - errorCode: 20 // IllegalOperation + errorCode: 20 } } ``` - Perform a `find` operation that fails. +- Assert that the human callback has been called once. +- Perform a `find` operation that succeeds. +- Assert that the human callback has been called once. - Close the client. ### (4) Reauthentication diff --git a/source/auth/tests/unified/mongodb-oidc-no-retry.json b/source/auth/tests/unified/mongodb-oidc-no-retry.json index 83d73e4e50..f9daaf24ac 100644 --- a/source/auth/tests/unified/mongodb-oidc-no-retry.json +++ b/source/auth/tests/unified/mongodb-oidc-no-retry.json @@ -324,12 +324,12 @@ "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", - "mode": "alwaysOn", + "mode": { "times": 1 }, "data": { "failCommands": [ "saslStart" ], - "errorCode": 20 + "errorCode": 18 } } } @@ -399,12 +399,12 @@ "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", - "mode": "alwaysOn", + "mode": { "times": 1}, "data": { "failCommands": [ "saslStart" ], - "errorCode": 20 + "errorCode": 18 } } } @@ -419,7 +419,7 @@ } }, "expectError": { - "errorCode": 20 + "errorCode": 18 } } ] diff --git a/source/auth/tests/unified/mongodb-oidc-no-retry.yml b/source/auth/tests/unified/mongodb-oidc-no-retry.yml index b500fb7db6..94375744b7 100644 --- a/source/auth/tests/unified/mongodb-oidc-no-retry.yml +++ b/source/auth/tests/unified/mongodb-oidc-no-retry.yml @@ -173,11 +173,12 @@ tests: client: failPointClient failPoint: configureFailPoint: failCommand - mode: "alwaysOn" + mode: + times: 1 data: failCommands: - saslStart - errorCode: 20 # IllegalOperation + errorCode: 18 - name: insertOne object: collection0 arguments: @@ -211,11 +212,12 @@ tests: client: failPointClient failPoint: configureFailPoint: failCommand - mode: "alwaysOn" + mode: + times: 1 data: failCommands: - saslStart - errorCode: 20 # IllegalOperation + errorCode: 18 - name: insertOne object: collection0 arguments: @@ -223,7 +225,7 @@ tests: _id: 1 x: 1 expectError: - errorCode: 20 # IllegalOperation + errorCode: 18 - description: Read commands should fail if reauthentication fails operations: - name: find From ed669eb65fc2b984c521dc03eefcf4355b05dc75 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Tue, 19 Mar 2024 08:52:14 -0500 Subject: [PATCH 02/25] regenerate json --- source/auth/auth.md | 2 + .../tests/unified/mongodb-oidc-no-retry.json | 51 +++++++------------ 2 files changed, 21 insertions(+), 32 deletions(-) diff --git a/source/auth/auth.md b/source/auth/auth.md index f8d521bd95..aaf0e5e6e9 100644 --- a/source/auth/auth.md +++ b/source/auth/auth.md @@ -1920,6 +1920,8 @@ to EC2 instance metadata in ECS, for security reasons, Amazon states it's best p ## Changelog +- 2024-03-19: Specify to only invalidate cached OIDC access tokens if the server returns error 18. + - 2024-01-31: Migrated from reStructuredText to Markdown. - 2024-01-17: Added MONGODB-OIDC machine auth flow spec and combine with human\ diff --git a/source/auth/tests/unified/mongodb-oidc-no-retry.json b/source/auth/tests/unified/mongodb-oidc-no-retry.json index f9daaf24ac..613af87347 100644 --- a/source/auth/tests/unified/mongodb-oidc-no-retry.json +++ b/source/auth/tests/unified/mongodb-oidc-no-retry.json @@ -52,9 +52,7 @@ { "collectionName": "collName", "databaseName": "test", - "documents": [ - - ] + "documents": [] } ], "tests": [ @@ -65,12 +63,9 @@ "name": "find", "object": "collection0", "arguments": { - "filter": { - } + "filter": {} }, - "expectResult": [ - - ] + "expectResult": [] } ], "expectEvents": [ @@ -81,8 +76,7 @@ "commandStartedEvent": { "command": { "find": "collName", - "filter": { - } + "filter": {} } } }, @@ -161,12 +155,9 @@ "name": "find", "object": "collection0", "arguments": { - "filter": { - } + "filter": {} }, - "expectResult": [ - - ] + "expectResult": [] } ], "expectEvents": [ @@ -177,8 +168,7 @@ "commandStartedEvent": { "command": { "find": "collName", - "filter": { - } + "filter": {} } } }, @@ -191,8 +181,7 @@ "commandStartedEvent": { "command": { "find": "collName", - "filter": { - } + "filter": {} } } }, @@ -324,7 +313,9 @@ "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", - "mode": { "times": 1 }, + "mode": { + "times": 1 + }, "data": { "failCommands": [ "saslStart" @@ -399,7 +390,9 @@ "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", - "mode": { "times": 1}, + "mode": { + "times": 1 + }, "data": { "failCommands": [ "saslStart" @@ -431,12 +424,9 @@ "name": "find", "object": "collection0", "arguments": { - "filter": { - } + "filter": {} }, - "expectResult": [ - - ] + "expectResult": [] }, { "name": "failPoint", @@ -462,8 +452,7 @@ "name": "find", "object": "collection0", "arguments": { - "filter": { - } + "filter": {} }, "expectError": { "errorCode": 391 @@ -478,8 +467,7 @@ "commandStartedEvent": { "command": { "find": "collName", - "filter": { - } + "filter": {} } } }, @@ -492,8 +480,7 @@ "commandStartedEvent": { "command": { "find": "collName", - "filter": { - } + "filter": {} } } }, From a25518c7bb7731fb29eaf4f5ef7a6bdbab15caeb Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Tue, 19 Mar 2024 08:57:30 -0500 Subject: [PATCH 03/25] restore comment --- source/auth/tests/mongodb-oidc.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/auth/tests/mongodb-oidc.md b/source/auth/tests/mongodb-oidc.md index db66e5be3a..26332d6a63 100644 --- a/source/auth/tests/mongodb-oidc.md +++ b/source/auth/tests/mongodb-oidc.md @@ -293,7 +293,7 @@ Drivers MUST be able to authenticate using OIDC callback(s) when there is one pr failCommands: [ "saslStart" ], - errorCode: 20 + errorCode: 20 // IllegalOperation } } ``` From 06e0110e1b6fe5f0a160cec232570f9a18c53c80 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Tue, 19 Mar 2024 20:31:05 -0500 Subject: [PATCH 04/25] add spec test for Refresh Token Is Passed To The Callback --- source/auth/tests/mongodb-oidc.md | 71 +++++++++++++++++++++---------- 1 file changed, 48 insertions(+), 23 deletions(-) diff --git a/source/auth/tests/mongodb-oidc.md b/source/auth/tests/mongodb-oidc.md index 26332d6a63..ec1363f1ed 100644 --- a/source/auth/tests/mongodb-oidc.md +++ b/source/auth/tests/mongodb-oidc.md @@ -95,6 +95,32 @@ method, use `mongodb://localhost/?authMechanism=MONGODB-OIDC` for `MONGODB_URI`. - Assert that the callback was called 1 time. - Close the client. +**3.3 Unexpected error code does not clear the cache** + +- Create a `MongoClient` with a human callback that returns a valid token. +- Set a fail point for `saslStart` commands of the form: + +```javascript +{ + configureFailPoint: "failCommand", + mode: { + times: 1 + }, + data: { + failCommands: [ + "saslStart" + ], + errorCode: 20 // IllegalOperation + } +} +``` + +- Perform a `find` operation that fails. +- Assert that the human callback has been called once. +- Perform a `find` operation that succeeds. +- Assert that the human callback has been called once. +- Close the client. + ### (4) Reauthentication - Create a `MongoClient` configured with an OIDC callback that implements the AWS provider logic. @@ -205,18 +231,17 @@ Drivers MUST be able to authenticate using OIDC callback(s) when there is one pr including the timeout parameter if possible. - Close the client. -**2.3 Human Callback Returns Missing Data** +**2.2 Human Callback Returns Missing Data** - Create a `MongoClient` with a human callback that returns data not conforming to the `OIDCCredential` with missing fields. - Perform a `find` operation that fails. - Close the client. -### (3) Speculative Authentication +**2.3 Refresh Token Is Passed To The Callback** -**3.1 Uses speculative authentication if there is a cached token** - -- Create a `MongoClient` with a human callback that returns a valid token. +- Create a `MongoClien`t with a human callback that checks for the presence of a refresh token. +- Perform a find operation that succeeds. - Set a fail point for `find` commands of the form: ```javascript @@ -229,13 +254,21 @@ Drivers MUST be able to authenticate using OIDC callback(s) when there is one pr failCommands: [ "find" ], - closeConnection: true + errorCode: 391 } } ``` -- Perform a `find` operation that fails. -- Set a fail point for `saslStart` commands of the form: +- Perform a `find` operation that succeeds. +- Assert that the callback has been called twice. +- Assert that the refresh token was used once. + +### (3) Speculative Authentication + +**3.1 Uses speculative authentication if there is a cached token** + +- Create a `MongoClient` with a human callback that returns a valid token. +- Set a fail point for `find` commands of the form: ```javascript { @@ -245,19 +278,14 @@ Drivers MUST be able to authenticate using OIDC callback(s) when there is one pr }, data: { failCommands: [ - "saslStart" + "find" ], - errorCode: 18 + closeConnection: true } } ``` -- Perform a `find` operation that succeeds. -- Close the client. - -**3.2 Does not use speculative authentication if there is no cached token** - -- Create a `MongoClient` with a human callback that returns a valid token. +- Perform a `find` operation that fails. - Set a fail point for `saslStart` commands of the form: ```javascript @@ -275,10 +303,10 @@ Drivers MUST be able to authenticate using OIDC callback(s) when there is one pr } ``` -- Perform a `find` operation that fails. +- Perform a `find` operation that succeeds. - Close the client. -**3.3 Unexpected error code does not clear the cache** +**3.2 Does not use speculative authentication if there is no cached token** - Create a `MongoClient` with a human callback that returns a valid token. - Set a fail point for `saslStart` commands of the form: @@ -293,15 +321,12 @@ Drivers MUST be able to authenticate using OIDC callback(s) when there is one pr failCommands: [ "saslStart" ], - errorCode: 20 // IllegalOperation + errorCode: 18 } } ``` - Perform a `find` operation that fails. -- Assert that the human callback has been called once. -- Perform a `find` operation that succeeds. -- Assert that the human callback has been called once. - Close the client. ### (4) Reauthentication @@ -367,7 +392,7 @@ Drivers MUST be able to authenticate using OIDC callback(s) when there is one pr **4.3 Succeeds after refresh fails** -- Create a default OIDC client. +- Create a default OIDC client with a human callback that returns an invalid refresh token. - Perform a `find` operation that succeeds. - Assert that the human callback has been called once. - Force a reauthenication using a fail point of the form: From 739ae61233da03e6a718839ae038bde29bbbabc4 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Thu, 21 Mar 2024 12:18:51 -0500 Subject: [PATCH 05/25] address review --- source/auth/tests/mongodb-oidc.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/auth/tests/mongodb-oidc.md b/source/auth/tests/mongodb-oidc.md index 45eee60184..c2435f34f0 100644 --- a/source/auth/tests/mongodb-oidc.md +++ b/source/auth/tests/mongodb-oidc.md @@ -420,7 +420,7 @@ Drivers MUST be able to authenticate using OIDC callback(s) when there is one pr **4.3 Succeeds after refresh fails** -- Create a default OIDC client with a human callback that returns an invalid refresh token. +- Create a default client with a callback that returns the `test_user1` access token and a bad refresh token. - Perform a `find` operation that succeeds. - Assert that the human callback has been called once. - Force a reauthenication using a fail point of the form: From 6ed2c945c2d11f39dbdf41d0f9cf2e5ab59f523e Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Tue, 2 Apr 2024 19:39:56 -0500 Subject: [PATCH 06/25] Update source/auth/auth.md Co-authored-by: Maxim Katcharov --- source/auth/auth.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/auth/auth.md b/source/auth/auth.md index dddfee8990..5afa9dbef3 100644 --- a/source/auth/auth.md +++ b/source/auth/auth.md @@ -1661,8 +1661,7 @@ def auth(connection): # If there is a cached access token, try to authenticate with it. If # authentication fails with an Authentication error (18), - # it's possible the cached access token is expired. In - # that case, invalidate the access token, fetch a new access token, and try + # invalidate the access token, fetch a new access token, and try # to authenticate again. # If the server fails for any other reason, do not clear the cache. if is_cache: From 958148ef5dc5899ce1db97a4757a14d9d74d0e3c Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 3 Apr 2024 11:02:20 -0500 Subject: [PATCH 07/25] Update source/auth/tests/mongodb-oidc.md Co-authored-by: Maxim Katcharov --- source/auth/tests/mongodb-oidc.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/auth/tests/mongodb-oidc.md b/source/auth/tests/mongodb-oidc.md index edcc53d91f..c29db7fb67 100644 --- a/source/auth/tests/mongodb-oidc.md +++ b/source/auth/tests/mongodb-oidc.md @@ -265,7 +265,7 @@ Drivers MUST be able to authenticate using OIDC callback(s) when there is one pr - Perform a `find` operation that succeeds. - Assert that the callback has been called twice. -- Assert that the refresh token was used once. +- Assert that the refresh token was provided to the callback once. ### (3) Speculative Authentication From 83952e7da08ca31d083c529fa1446853c53cef1d Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Mon, 8 Apr 2024 06:30:26 -0500 Subject: [PATCH 08/25] OIDC spec updates --- source/auth/auth.md | 27 ++++++++++--------- .../auth/tests/legacy/connection-string.yml | 4 +-- source/auth/tests/mongodb-oidc.md | 18 +++++++++++++ 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/source/auth/auth.md b/source/auth/auth.md index 2ec49e974d..9f7ba3bbd4 100644 --- a/source/auth/auth.md +++ b/source/auth/auth.md @@ -53,7 +53,7 @@ Drivers SHOULD contain a type called `MongoCredential`. It SHOULD contain some o - username (string) - Applies to all mechanisms. - - Optional for MONGODB-X509 and MONGODB-AWS. + - Optional for MONGODB-X509, MONGODB-AWS, and MONGODB-OIDC. - source (string) @@ -1361,10 +1361,10 @@ The driver MUST pass the following information to the callback: The callback MUST be able to return the following information: - `accessToken`: An OIDC access token string. The driver MUST NOT attempt to validate `accessToken` directly. -- `expiresIn`: An optional expiry duration for the access token. Drivers MUST interpret the value 0 as an infinite - duration and error if a negative value is returned. Drivers SHOULD use the most idiomatic type for representing a - duration in the driver's language. Note that the access token expiry value is currently not used in - [Credential Caching](#credential-caching), but is intended to support future caching optimizations. +- `expiresIn`: An optional expiry duration for the access token. Drivers with optional parameters MAY interpret a + missing value as infinite. Drivers MUST error if a negative value is returned. Drivers SHOULD use the most idiomatic + type for representing a duration in the driver's language. Note that the access token expiry value is currently not + used in [Credential Caching](#credential-caching), but is intended to support future caching optimizations. The signature and naming of the callback API is up to the driver's discretion. Drivers MUST ensure that additional optional input parameters and return values can be added to the callback signature in the future without breaking @@ -1418,7 +1418,7 @@ An example human callback API might look like: ```typescript interface IdpInfo { issuer: string; - clientId: string; + clientId: Optional; requestScopes: Optional>; } @@ -1647,9 +1647,9 @@ Use the following algorithm to authenticate a new connection: - Check if the the *Client Cache* has an access token. - If it does, cache the access token in the *Connection Cache* and perform a `One-Step` SASL conversation using the - access token in the *Client Cache*. If the server returns a Authentication error (18), invalidate that access token, - sleep 100ms then continue. -- Call the configured built-in provider integration or the OIDC callback to retrieve a new access token. + access token in the *Client Cache*. If the server returns a Authentication error (18), invalidate that access token. +- Call the configured built-in provider integration or the OIDC callback to retrieve a new access token. Wait until it + has been at least 100ms since the last callback invocation, to avoid overloading the callback. - Cache the new access token in the *Client Cache* and *Connection Cache*. - Perform a `One-Step` SASL conversation using the new access token. Raise any errors to the user. @@ -1685,14 +1685,15 @@ authenticate a new connection when a [OIDC Human Callback](#oidc-human-callback) - Check if the *Client Cache* has an access token. - If it does, cache the access token in the *Connection Cache* and perform a [One-Step](#one-step) SASL conversation using the access token. If the server returns an Authentication error (18), invalidate the access token token from - the *Client Cache*, clear the *Connection Cache*, and continue. If the server returns another error, continue. + the *Client Cache*, clear the *Connection Cache*, and restart the loop. If the server returns another error, restart + the authentication flow. - Check if the *Client Cache* has a refresh token. - If it does, call the [OIDC Human Callback](#oidc-human-callback) with the cached refresh token and `IdpInfo` to get a new access token. Cache the new access token in the *Client Cache* and *Connection Cache*. Perform a [One-Step](#one-step) SASL conversation using the new access token. If the [OIDC Human Callback](#oidc-human-callback) or the server returns an Authentication error (18), invalidate the - access token from the *Client Cache*, clear the *Connection Cache*, and continue. If the server returns another - error, continue. + access token from the *Client Cache*, clear the *Connection Cache*, and restart the authentication flow. If the + server returns another error, restart the authentication flow. - Start a new [Two-Step](#two-step) SASL conversation. - Run a `PrincipalStepRequest` to get the `IdpInfo`. - Call the [OIDC Human Callback](#oidc-human-callback) with the new `IdpInfo` to get a new access token and optional @@ -1714,7 +1715,7 @@ Use the following algorithm to perform speculative authentication: - If it does, cache the access token in the *Connection Cache* and send a `JwtStepRequest` with the cached access token in the speculative authentication SASL payload. If the response is missing a speculative authentication document or the speculative authentication document indicates authentication was not successful, clear the the - *Connection Cache* and continue. + *Connection Cache* and proceed to the next step. - Authenticate with the standard authentication handshake. Example code for speculative authentication using the `auth` function described above: diff --git a/source/auth/tests/legacy/connection-string.yml b/source/auth/tests/legacy/connection-string.yml index 8c3d46d01a..081b14ba1c 100644 --- a/source/auth/tests/legacy/connection-string.yml +++ b/source/auth/tests/legacy/connection-string.yml @@ -374,7 +374,7 @@ tests: uri: mongodb://user:pass@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:test valid: false credential: -- description: should throw an exception if username is specified for aws (MONGODB-OIDC) +- description: should throw an exception if username is specified for test (MONGODB-OIDC) uri: mongodb://principalName@localhost/?authMechanism=MONGODB-OIDC&ENVIRONMENT:test valid: false credential: @@ -389,4 +389,4 @@ tests: - description: should throw an exception when unsupported auth property is specified (MONGODB-OIDC) uri: mongodb://localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=UnsupportedProperty:unexisted valid: false - credential: + credential: \ No newline at end of file diff --git a/source/auth/tests/mongodb-oidc.md b/source/auth/tests/mongodb-oidc.md index edcc53d91f..638e8d836c 100644 --- a/source/auth/tests/mongodb-oidc.md +++ b/source/auth/tests/mongodb-oidc.md @@ -226,6 +226,24 @@ Drivers MUST be able to authenticate using OIDC callback(s) when there is one pr - Assert that a `find` operation fails with a client-side error. - Close the client. +**1.7 Allowed Hosts in Connection String Ignored** + +- Create an OIDC configured client with the connection string: + `mongodb+srv://example.com/?authMechanism=MONGODB-OIDC&authMechanismProperties=ALLOWED_HOSTS:%5B%22example.com%22%5D` + and a Human Callback. +- Assert that the creation of the client raises a configuration error. + +**1.8 Machine IdP with Human Callback** + +This test MUST only be run when `OIDC_IS_LOCAL` is set. This indicates that the server is local and not using Atlas. In +this case, `MONGODB_URI_SINGLE` will be configured with a human user `test_user1`, and a machine user `test_machine`. +This test uses the machine user with a human callback, ensuring that the missing `clientId` in the +`PrincipalStepRequest` response is handled by the driver. + +- Create an OIDC configured client with `MONGODB_URI_SINGLE` and a username of `test_machine`. +- Perform a find operation that succeeds. +- Close the client. + ### (2) OIDC Human Callback Validation **2.1 Valid Callback Inputs** From b4e7905c85b65be2d42726c223eb124f6807e2e2 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Tue, 9 Apr 2024 07:43:07 -0500 Subject: [PATCH 09/25] update auth logic --- source/auth/auth.md | 10 +++++----- source/auth/tests/mongodb-oidc.md | 15 ++++++++------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/source/auth/auth.md b/source/auth/auth.md index 89c89067f3..4da95b957b 100644 --- a/source/auth/auth.md +++ b/source/auth/auth.md @@ -1747,15 +1747,15 @@ authenticate a new connection when a [OIDC Human Callback](#oidc-human-callback) - Check if the *Client Cache* has an access token. - If it does, cache the access token in the *Connection Cache* and perform a [One-Step](#one-step) SASL conversation using the access token. If the server returns an Authentication error (18), invalidate the access token token from - the *Client Cache*, clear the *Connection Cache*, and restart the loop. If the server returns another error, restart - the authentication flow. + the *Client Cache*, clear the *Connection Cache*, and restart the authentication flow. If the server returns another + error, restart the authentication flow. - Check if the *Client Cache* has a refresh token. - If it does, call the [OIDC Human Callback](#oidc-human-callback) with the cached refresh token and `IdpInfo` to get a new access token. Cache the new access token in the *Client Cache* and *Connection Cache*. Perform a [One-Step](#one-step) SASL conversation using the new access token. If the - [OIDC Human Callback](#oidc-human-callback) or the server returns an Authentication error (18), invalidate the - access token from the *Client Cache*, clear the *Connection Cache*, and restart the authentication flow. If the - server returns another error, restart the authentication flow. + [OIDC Human Callback](#oidc-human-callback) or the server returns an Authentication error (18), clear the refresh + token, invalidate the access token from the *Client Cache*, clear the *Connection Cache*, and restart the + authentication flow. If the server returns another error, restart the authentication flow. - Start a new [Two-Step](#two-step) SASL conversation. - Run a `PrincipalStepRequest` to get the `IdpInfo`. - Call the [OIDC Human Callback](#oidc-human-callback) with the new `IdpInfo` to get a new access token and optional diff --git a/source/auth/tests/mongodb-oidc.md b/source/auth/tests/mongodb-oidc.md index 70882fedfa..63b4571a20 100644 --- a/source/auth/tests/mongodb-oidc.md +++ b/source/auth/tests/mongodb-oidc.md @@ -423,11 +423,11 @@ This test uses the machine user with a human callback, ensuring that the missing { configureFailPoint: "failCommand", mode: { - times: 2 + times: 1 }, data: { failCommands: [ - "find", "saslStart" + "find", ], errorCode: 391 // ReauthenticationRequired } @@ -435,12 +435,13 @@ This test uses the machine user with a human callback, ensuring that the missing ``` - Perform a `find` operation that succeeds. -- Assert that the human callback has been called 3 times. +- Assert that the human callback has been called 2 times. - Close the client. **4.4 Fails** -- Create an OIDC configured client. +- Create an OIDC configured client that returns invalid refresh tokens and returns invalid access tokens after the first + access. - Perform a find operation that succeeds (to force a speculative auth). - Assert that the human callback has been called once. - Force a reauthenication using a failCommand of the form: @@ -449,11 +450,11 @@ This test uses the machine user with a human callback, ensuring that the missing { configureFailPoint: "failCommand", mode: { - times: 3 + times: 1 }, data: { failCommands: [ - "find", "saslStart" + "find", ], errorCode: 391 // ReauthenticationRequired } @@ -461,5 +462,5 @@ This test uses the machine user with a human callback, ensuring that the missing ``` - Perform a find operation that fails. -- Assert that the human callback has been called twice. +- Assert that the human callback has been called three times. - Close the client. From 6815eb40d739dc5c0a60a904052fc940f6ef154b Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Tue, 9 Apr 2024 10:43:07 -0500 Subject: [PATCH 10/25] update error handling --- source/auth/auth.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/source/auth/auth.md b/source/auth/auth.md index 4da95b957b..c7482659de 100644 --- a/source/auth/auth.md +++ b/source/auth/auth.md @@ -1747,15 +1747,14 @@ authenticate a new connection when a [OIDC Human Callback](#oidc-human-callback) - Check if the *Client Cache* has an access token. - If it does, cache the access token in the *Connection Cache* and perform a [One-Step](#one-step) SASL conversation using the access token. If the server returns an Authentication error (18), invalidate the access token token from - the *Client Cache*, clear the *Connection Cache*, and restart the authentication flow. If the server returns another - error, restart the authentication flow. + the *Client Cache*, clear the *Connection Cache*, and restart the authentication flow. Raise any other errors to the + user. - Check if the *Client Cache* has a refresh token. - If it does, call the [OIDC Human Callback](#oidc-human-callback) with the cached refresh token and `IdpInfo` to get a new access token. Cache the new access token in the *Client Cache* and *Connection Cache*. Perform a - [One-Step](#one-step) SASL conversation using the new access token. If the - [OIDC Human Callback](#oidc-human-callback) or the server returns an Authentication error (18), clear the refresh - token, invalidate the access token from the *Client Cache*, clear the *Connection Cache*, and restart the - authentication flow. If the server returns another error, restart the authentication flow. + [One-Step](#one-step) SASL conversation using the new access token. If the the server returns an Authentication + error (18), clear the refresh token, invalidate the access token from the *Client Cache*, clear the *Connection + Cache*, and restart the authentication flow. Raise any other errors to the user. - Start a new [Two-Step](#two-step) SASL conversation. - Run a `PrincipalStepRequest` to get the `IdpInfo`. - Call the [OIDC Human Callback](#oidc-human-callback) with the new `IdpInfo` to get a new access token and optional @@ -2054,6 +2053,8 @@ to EC2 instance metadata in ECS, for security reasons, Amazon states it's best p ## Changelog +- 2024-04-09: Updated OIDC authentication flow and prose tests. + - 2024-04-03: Added GCP built-in OIDC provider integration. - 2024-03-29: Updated OIDC test setup and descriptions. From 59673530722fdcb2c699d329755eb8b1495a4db0 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 10 Apr 2024 07:32:34 -0500 Subject: [PATCH 11/25] Update source/auth/auth.md Co-authored-by: Maxim Katcharov --- source/auth/auth.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/auth/auth.md b/source/auth/auth.md index c7482659de..c3eee14b3d 100644 --- a/source/auth/auth.md +++ b/source/auth/auth.md @@ -1748,7 +1748,7 @@ authenticate a new connection when a [OIDC Human Callback](#oidc-human-callback) - If it does, cache the access token in the *Connection Cache* and perform a [One-Step](#one-step) SASL conversation using the access token. If the server returns an Authentication error (18), invalidate the access token token from the *Client Cache*, clear the *Connection Cache*, and restart the authentication flow. Raise any other errors to the - user. + user. On success, exit the algorithm. - Check if the *Client Cache* has a refresh token. - If it does, call the [OIDC Human Callback](#oidc-human-callback) with the cached refresh token and `IdpInfo` to get a new access token. Cache the new access token in the *Client Cache* and *Connection Cache*. Perform a From 3242bea3cc14b3386d0ec5f754ebd444ef188d36 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 10 Apr 2024 07:32:40 -0500 Subject: [PATCH 12/25] Update source/auth/auth.md Co-authored-by: Maxim Katcharov --- source/auth/auth.md | 1 + 1 file changed, 1 insertion(+) diff --git a/source/auth/auth.md b/source/auth/auth.md index c3eee14b3d..ece4103031 100644 --- a/source/auth/auth.md +++ b/source/auth/auth.md @@ -1755,6 +1755,7 @@ authenticate a new connection when a [OIDC Human Callback](#oidc-human-callback) [One-Step](#one-step) SASL conversation using the new access token. If the the server returns an Authentication error (18), clear the refresh token, invalidate the access token from the *Client Cache*, clear the *Connection Cache*, and restart the authentication flow. Raise any other errors to the user. + On success, exit the algorithm. - Start a new [Two-Step](#two-step) SASL conversation. - Run a `PrincipalStepRequest` to get the `IdpInfo`. - Call the [OIDC Human Callback](#oidc-human-callback) with the new `IdpInfo` to get a new access token and optional From ddd40549cefa71173d17cc071432eeb7590852c2 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 10 Apr 2024 07:32:49 -0500 Subject: [PATCH 13/25] Update source/auth/auth.md Co-authored-by: Maxim Katcharov --- source/auth/auth.md | 1 + 1 file changed, 1 insertion(+) diff --git a/source/auth/auth.md b/source/auth/auth.md index ece4103031..6976bdce8e 100644 --- a/source/auth/auth.md +++ b/source/auth/auth.md @@ -1710,6 +1710,7 @@ Use the following algorithm to authenticate a new connection: - Check if the the *Client Cache* has an access token. - If it does, cache the access token in the *Connection Cache* and perform a `One-Step` SASL conversation using the access token in the *Client Cache*. If the server returns a Authentication error (18), invalidate that access token. + Raise any other errors to the user. On success, exit the algorithm. - Call the configured built-in provider integration or the OIDC callback to retrieve a new access token. Wait until it has been at least 100ms since the last callback invocation, to avoid overloading the callback. - Cache the new access token in the *Client Cache* and *Connection Cache*. From c263ad2bf8ecad0869eb31025a124dbddf2c4b31 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 10 Apr 2024 07:32:57 -0500 Subject: [PATCH 14/25] Update source/auth/auth.md Co-authored-by: Maxim Katcharov --- source/auth/auth.md | 1 - 1 file changed, 1 deletion(-) diff --git a/source/auth/auth.md b/source/auth/auth.md index 6976bdce8e..88389bd686 100644 --- a/source/auth/auth.md +++ b/source/auth/auth.md @@ -1735,7 +1735,6 @@ def auth(connection): except ServerError as e: if e.code == 18: invalidate(access_token) - sleep(0.1) access_token, _ = get_access_token() connection.oidc_cache.access_token = access_token From 119fce13b933bd19cb85bdf6ca92d00b8ffacad9 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 10 Apr 2024 07:34:07 -0500 Subject: [PATCH 15/25] address review --- source/auth/auth.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/source/auth/auth.md b/source/auth/auth.md index 88389bd686..a7bd0b0454 100644 --- a/source/auth/auth.md +++ b/source/auth/auth.md @@ -1219,8 +1219,7 @@ in the MONGODB-OIDC specification, including sections or blocks that specificall the same `MongoClient`, the driver MUST raise an error. - TOKEN_RESOURCE\ - The URI of the target resource. This property is currently only used and required by the Azure - built-in OIDC provider integration. If `TOKEN_RESOURCE` is provided and `ENVIRONMENT` is not one of + The URI of the target resource. If `TOKEN_RESOURCE` is provided and `ENVIRONMENT` is not one of `["azure", "gcp"]` or `TOKEN_RESOURCE` is not provided and `ENVIRONMENT` is one of `["azure", "gcp"]`, the driver MUST raise an error. @@ -1754,8 +1753,7 @@ authenticate a new connection when a [OIDC Human Callback](#oidc-human-callback) a new access token. Cache the new access token in the *Client Cache* and *Connection Cache*. Perform a [One-Step](#one-step) SASL conversation using the new access token. If the the server returns an Authentication error (18), clear the refresh token, invalidate the access token from the *Client Cache*, clear the *Connection - Cache*, and restart the authentication flow. Raise any other errors to the user. - On success, exit the algorithm. + Cache*, and restart the authentication flow. Raise any other errors to the user. On success, exit the algorithm. - Start a new [Two-Step](#two-step) SASL conversation. - Run a `PrincipalStepRequest` to get the `IdpInfo`. - Call the [OIDC Human Callback](#oidc-human-callback) with the new `IdpInfo` to get a new access token and optional From 0f6f3bc8fb2f4514bf0f6d3cb1084033c5f84da9 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 10 Apr 2024 20:23:25 -0500 Subject: [PATCH 16/25] Update source/auth/tests/mongodb-oidc.md Co-authored-by: Patrick Meredith --- source/auth/tests/mongodb-oidc.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/auth/tests/mongodb-oidc.md b/source/auth/tests/mongodb-oidc.md index 63b4571a20..853068929b 100644 --- a/source/auth/tests/mongodb-oidc.md +++ b/source/auth/tests/mongodb-oidc.md @@ -262,7 +262,7 @@ This test uses the machine user with a human callback, ensuring that the missing **2.3 Refresh Token Is Passed To The Callback** -- Create a `MongoClien`t with a human callback that checks for the presence of a refresh token. +- Create a `MongoClient` with a human callback that checks for the presence of a refresh token. - Perform a find operation that succeeds. - Set a fail point for `find` commands of the form: From 94ef18d91bbf5eaaf4886427f434e56a294bcbd8 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 10 Apr 2024 20:31:55 -0500 Subject: [PATCH 17/25] fix connection string tests --- source/auth/tests/legacy/connection-string.json | 4 ++-- source/auth/tests/legacy/connection-string.yml | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/source/auth/tests/legacy/connection-string.json b/source/auth/tests/legacy/connection-string.json index 3c7a6b1d14..e4a03a0d9c 100644 --- a/source/auth/tests/legacy/connection-string.json +++ b/source/auth/tests/legacy/connection-string.json @@ -482,7 +482,7 @@ } }, { - "description": "should recognise the mechanism with test integration (MONGODB-OIDC)", + "description": "should recognise the mechanism with test environment (MONGODB-OIDC)", "uri": "mongodb://localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:test", "valid": true, "credential": { @@ -609,4 +609,4 @@ "credential": null } ] -} +} \ No newline at end of file diff --git a/source/auth/tests/legacy/connection-string.yml b/source/auth/tests/legacy/connection-string.yml index b35e5c520d..cf10cbf8db 100644 --- a/source/auth/tests/legacy/connection-string.yml +++ b/source/auth/tests/legacy/connection-string.yml @@ -390,7 +390,6 @@ tests: uri: mongodb://localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=UnsupportedProperty:unexisted valid: false credential: - credential: - description: should recognise the mechanism with azure provider (MONGODB-OIDC) uri: mongodb://localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:azure,TOKEN_RESOURCE:foo valid: true From 13dc54c48176e864f13ca1d26e017aaa96571094 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Mon, 15 Apr 2024 19:09:07 -0500 Subject: [PATCH 18/25] clarify test conditions --- source/auth/tests/mongodb-oidc.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/source/auth/tests/mongodb-oidc.md b/source/auth/tests/mongodb-oidc.md index 853068929b..3bb15d1017 100644 --- a/source/auth/tests/mongodb-oidc.md +++ b/source/auth/tests/mongodb-oidc.md @@ -10,17 +10,21 @@ ______________________________________________________________________ ## Unified Spec Tests -Drivers MUST run the unified spec tests in all supported OIDC environments. +Drivers MUST run the unified spec tests in all supported OIDC environments. Drivers MUST set the placeholder +authMechanism properties (`ENVIRONMENT` and `TOKEN_RESOURCE`, if applicable). ______________________________________________________________________ -## Prose Tests +## Machine Authentication Flow Prose Tests + +Drivers MUST run the machine prose tests when `OIDC_TOKEN_DIR` is set. Drivers can either set the `ENVIRONMENT:test` +auth mechanism property, or use a custom callback that also reads the file. + +Drivers can also choose to run the machine prose tests on GCP or Azure VMs. Drivers MUST implement all prose tests in this section. Unless otherwise noted, all `MongoClient` instances MUST be configured with `retryReads=false`. -Drivers MUST run the prose tests in all supported OIDC environments. - > [!NOTE] > For test cases that create fail points, drivers MUST either use a unique `appName` or explicitly remove the fail point > callback to prevent interaction between test cases. @@ -29,9 +33,6 @@ After setting up your OIDC [environment](https://github.com/mongodb-labs/drivers-evergreen-tools/blob/master/.evergreen/auth_oidc/README.md), source the `secrets-export.sh` file and use the associated env variables in your tests. -An OIDC configured client MUST set the appropriate `ENVIRONMENT` auth mechanism property and include a callback that -gets the appropriate token for the given environment. - ### Callback Authentication **1.1 Callback is called during authentication** @@ -167,7 +168,7 @@ ______________________________________________________________________ Drivers that support the [Human Authentication Flow](../auth.md#human-authentication-flow) MUST implement all prose tests in this section. Unless otherwise noted, all `MongoClient` instances MUST be configured with `retryReads=false`. -The human workflow tests MUST only be run when in `ENVIRONMENT:test`. +The human workflow tests MUST only be run when `OIDC_TOKEN_DIR` is set. > [!NOTE] > For test cases that create fail points, drivers MUST either use a unique `appName` or explicitly remove the fail point From 134c1f497056323d819df22c39eaa7550d46bc37 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 17 Apr 2024 10:05:17 -0500 Subject: [PATCH 19/25] clarify spec test --- source/auth/tests/mongodb-oidc.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/auth/tests/mongodb-oidc.md b/source/auth/tests/mongodb-oidc.md index 3bb15d1017..de21f1cf07 100644 --- a/source/auth/tests/mongodb-oidc.md +++ b/source/auth/tests/mongodb-oidc.md @@ -11,7 +11,8 @@ ______________________________________________________________________ ## Unified Spec Tests Drivers MUST run the unified spec tests in all supported OIDC environments. Drivers MUST set the placeholder -authMechanism properties (`ENVIRONMENT` and `TOKEN_RESOURCE`, if applicable). +authMechanism properties (`ENVIRONMENT` and `TOKEN_RESOURCE`, if applicable). These will typically be read from +environment variables set by the test runner, e,g. `AZUREOIDC_RESOURCE`. ______________________________________________________________________ From f24a075aeb151664f8473b578c298dee45ca4699 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Thu, 18 Apr 2024 20:24:09 -0500 Subject: [PATCH 20/25] fix SASL conversation --- source/auth/auth.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/auth/auth.md b/source/auth/auth.md index a7bd0b0454..acde6c9d86 100644 --- a/source/auth/auth.md +++ b/source/auth/auth.md @@ -1540,6 +1540,7 @@ An example OIDC one-step SASL conversation with access token string "abcd1234" l { saslStart: 1, mechanism: "MONGODB-OIDC", + db: "$external" // payload is a BSON generic binary field containing a JwtStepRequest BSON // document: {"jwt": "abcd1234"} payload: BinData(0, "FwAAAAJqd3QACQAAAGFiY2QxMjM0AAA=") @@ -1614,6 +1615,7 @@ An example OIDC two-step SASL conversation with username "myidp" and access toke { saslStart: 1, mechanism: "MONGODB-OIDC", + db: "$external", // payload is a BSON generic binary field containing a PrincipalStepRequest // BSON document: {"n": "myidp"} payload: BinData(0, "EgAAAAJuAAYAAABteWlkcAAA") From 5f63fea4a3dd64896a71efbd22010c9b06a50fc2 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Fri, 19 Apr 2024 09:57:21 -0500 Subject: [PATCH 21/25] fix grammar --- source/auth/auth.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/auth/auth.md b/source/auth/auth.md index acde6c9d86..fa6d0993a3 100644 --- a/source/auth/auth.md +++ b/source/auth/auth.md @@ -1261,9 +1261,9 @@ purposes, and is not meant to be documented as a user-facing feature. If enabled, drivers MUST generate a token using a script in the `auth_oidc` [folder](https://github.com/mongodb-labs/drivers-evergreen-tools/tree/master/.evergreen/auth_oidc#readme) in Drivers -Evergreen Tools. The must then set the `OIDC_TOKEN_FILE` environment variable to the path to that file. At runtime, the -driver MUST use the `OIDC_TOKEN_FILE` environment variable and read the OIDC access token from that path. The driver -MUST use the contents of that file as value in the `jwt` field of the `saslStart` payload. +Evergreen Tools. The driver MUST then set the `OIDC_TOKEN_FILE` environment variable to the path to that file. At +runtime, the driver MUST use the `OIDC_TOKEN_FILE` environment variable and read the OIDC access token from that path. +The driver MUST use the contents of that file as value in the `jwt` field of the `saslStart` payload. Drivers MAY implement the "test" integration so that it conforms to the function signature of the [OIDC Callback](#oidc-callback) to prevent having to re-implement the "test" integration logic in the OIDC prose tests. From 9e268e7f6ab0c9eeba20e9b57cd76e865347d27b Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Mon, 22 Apr 2024 05:29:20 -0500 Subject: [PATCH 22/25] convert two unified tests to prose tests --- source/auth/auth.md | 2 +- source/auth/tests/mongodb-oidc.md | 52 ++++++ .../tests/unified/mongodb-oidc-no-retry.json | 167 ------------------ .../tests/unified/mongodb-oidc-no-retry.yml | 89 +--------- 4 files changed, 54 insertions(+), 256 deletions(-) diff --git a/source/auth/auth.md b/source/auth/auth.md index fa6d0993a3..6b4e2b574a 100644 --- a/source/auth/auth.md +++ b/source/auth/auth.md @@ -2054,7 +2054,7 @@ to EC2 instance metadata in ECS, for security reasons, Amazon states it's best p ## Changelog -- 2024-04-09: Updated OIDC authentication flow and prose tests. +- 2024-04-20: Updated OIDC authentication flow and prose tests. - 2024-04-03: Added GCP built-in OIDC provider integration. diff --git a/source/auth/tests/mongodb-oidc.md b/source/auth/tests/mongodb-oidc.md index de21f1cf07..22439c1787 100644 --- a/source/auth/tests/mongodb-oidc.md +++ b/source/auth/tests/mongodb-oidc.md @@ -122,6 +122,8 @@ source the `secrets-export.sh` file and use the associated env variables in your ### (4) Reauthentication +\*\*4.1 Reauthentication Succeeds + - Create an OIDC configured client. - Set a fail point for `find` commands of the form: @@ -144,6 +146,56 @@ source the `secrets-export.sh` file and use the associated env variables in your - Assert that the callback was called 2 times (once during the connection handshake, and again during reauthentication). - Close the client. +\*\*4.2 Read Commands Fail If Reauthentication Fails + +- Create a `MongoClient` whose OIDC callback returns one good token and then bad tokens after the first call. +- Perform a `find` operation that succeeds. +- Set a fail point for `find` commands of the form: + +```javascript +{ + configureFailPoint: "failCommand", + mode: { + times: 1 + }, + data: { + failCommands: [ + "find" + ], + errorCode: 391 // ReauthenticationRequired + } +} +``` + +- Perform a `find` operation that fails. +- Assert that the callback was called 2 times. +- Close the client. + +\*\*4.3 Write Commands Fail If Reauthentication Fails + +- Create a `MongoClient` whose OIDC callback returns one good token and then bad tokens after the first call. +- Perform an `insert` operation that succeeds. +- Set a fail point for `inter` commands of the form: + +```javascript +{ + configureFailPoint: "failCommand", + mode: { + times: 1 + }, + data: { + failCommands: [ + "insert" + ], + errorCode: 391 // ReauthenticationRequired + } +} +``` + +- Perform a `find` operation that fails. +- Assert that the callback was called 2 times. +- Close the client. + ## (5) Azure Tests Drivers MUST only run the Azure tests when testing on an Azure VM. See instructions in diff --git a/source/auth/tests/unified/mongodb-oidc-no-retry.json b/source/auth/tests/unified/mongodb-oidc-no-retry.json index 613af87347..9dbe198270 100644 --- a/source/auth/tests/unified/mongodb-oidc-no-retry.json +++ b/source/auth/tests/unified/mongodb-oidc-no-retry.json @@ -416,173 +416,6 @@ } } ] - }, - { - "description": "Read commands should fail if reauthentication fails", - "operations": [ - { - "name": "find", - "object": "collection0", - "arguments": { - "filter": {} - }, - "expectResult": [] - }, - { - "name": "failPoint", - "object": "testRunner", - "arguments": { - "client": "failPointClient", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "find", - "saslStart" - ], - "errorCode": 391 - } - } - } - }, - { - "name": "find", - "object": "collection0", - "arguments": { - "filter": {} - }, - "expectError": { - "errorCode": 391 - } - } - ], - "expectEvents": [ - { - "client": "client0", - "events": [ - { - "commandStartedEvent": { - "command": { - "find": "collName", - "filter": {} - } - } - }, - { - "commandSucceededEvent": { - "commandName": "find" - } - }, - { - "commandStartedEvent": { - "command": { - "find": "collName", - "filter": {} - } - } - }, - { - "commandFailedEvent": { - "commandName": "find" - } - } - ] - } - ] - }, - { - "description": "Write commands should fail if reauthentication fails", - "operations": [ - { - "name": "insertOne", - "object": "collection0", - "arguments": { - "document": { - "_id": 1, - "x": 1 - } - } - }, - { - "name": "failPoint", - "object": "testRunner", - "arguments": { - "client": "failPointClient", - "failPoint": { - "configureFailPoint": "failCommand", - "mode": { - "times": 2 - }, - "data": { - "failCommands": [ - "insert", - "saslStart" - ], - "errorCode": 391 - } - } - } - }, - { - "name": "insertOne", - "object": "collection0", - "arguments": { - "document": { - "_id": 2, - "x": 2 - } - }, - "expectError": { - "errorCode": 391 - } - } - ], - "expectEvents": [ - { - "client": "client0", - "events": [ - { - "commandStartedEvent": { - "command": { - "insert": "collName", - "documents": [ - { - "_id": 1, - "x": 1 - } - ] - } - } - }, - { - "commandSucceededEvent": { - "commandName": "insert" - } - }, - { - "commandStartedEvent": { - "command": { - "insert": "collName", - "documents": [ - { - "_id": 2, - "x": 2 - } - ] - } - } - }, - { - "commandFailedEvent": { - "commandName": "insert" - } - } - ] - } - ] } ] } diff --git a/source/auth/tests/unified/mongodb-oidc-no-retry.yml b/source/auth/tests/unified/mongodb-oidc-no-retry.yml index 8923b6f995..426fd72466 100644 --- a/source/auth/tests/unified/mongodb-oidc-no-retry.yml +++ b/source/auth/tests/unified/mongodb-oidc-no-retry.yml @@ -225,91 +225,4 @@ tests: _id: 1 x: 1 expectError: - errorCode: 18 -- description: Read commands should fail if reauthentication fails - operations: - - name: find - object: collection0 - arguments: - filter: {} - expectResult: [] - - name: failPoint - object: testRunner - arguments: - client: failPointClient - failPoint: - configureFailPoint: failCommand - mode: - times: 2 - data: - failCommands: - - find - - saslStart - errorCode: 391 # ReauthenticationRequired - - name: find - object: collection0 - arguments: - filter: {} - expectError: { errorCode: 391 } - expectEvents: - - client: client0 - events: - - commandStartedEvent: - command: - find: collName - filter: {} - - commandSucceededEvent: - commandName: find - - commandStartedEvent: - command: - find: collName - filter: {} - - commandFailedEvent: - commandName: find -- description: Write commands should fail if reauthentication fails - operations: - - name: insertOne - object: collection0 - arguments: - document: - _id: 1 - x: 1 - - name: failPoint - object: testRunner - arguments: - client: failPointClient - failPoint: - configureFailPoint: failCommand - mode: - times: 2 - data: - failCommands: - - insert - - saslStart - errorCode: 391 # ReauthenticationRequired - - name: insertOne - object: collection0 - arguments: - document: - _id: 2 - x: 2 - expectError: { errorCode: 391 } - expectEvents: - - client: client0 - events: - - commandStartedEvent: - command: - insert: collName - documents: - - _id: 1 - x: 1 - - commandSucceededEvent: - commandName: insert - - commandStartedEvent: - command: - insert: collName - documents: - - _id: 2 - x: 2 - - commandFailedEvent: - commandName: insert + errorCode: 18 \ No newline at end of file From 8cef9deb9a43d44529b3d88c9058c02163d14e5c Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Mon, 22 Apr 2024 14:35:24 -0500 Subject: [PATCH 23/25] Update source/auth/tests/mongodb-oidc.md Co-authored-by: Maxim Katcharov --- source/auth/tests/mongodb-oidc.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/auth/tests/mongodb-oidc.md b/source/auth/tests/mongodb-oidc.md index 22439c1787..1e6a2750de 100644 --- a/source/auth/tests/mongodb-oidc.md +++ b/source/auth/tests/mongodb-oidc.md @@ -175,7 +175,7 @@ source the `secrets-export.sh` file and use the associated env variables in your - Create a `MongoClient` whose OIDC callback returns one good token and then bad tokens after the first call. - Perform an `insert` operation that succeeds. -- Set a fail point for `inter` commands of the form: +- Set a fail point for `insert` commands of the form: ```javascript { From 8471762ce4307f5b8b9a8f67b7e7684c0817a3bf Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Mon, 22 Apr 2024 14:35:30 -0500 Subject: [PATCH 24/25] Update source/auth/tests/mongodb-oidc.md Co-authored-by: Maxim Katcharov --- source/auth/tests/mongodb-oidc.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/auth/tests/mongodb-oidc.md b/source/auth/tests/mongodb-oidc.md index 1e6a2750de..d1cdb20254 100644 --- a/source/auth/tests/mongodb-oidc.md +++ b/source/auth/tests/mongodb-oidc.md @@ -294,7 +294,7 @@ this case, `MONGODB_URI_SINGLE` will be configured with a human user `test_user1 This test uses the machine user with a human callback, ensuring that the missing `clientId` in the `PrincipalStepRequest` response is handled by the driver. -- Create an OIDC configured client with `MONGODB_URI_SINGLE` and a username of `test_machine`. +- Create an OIDC configured client with `MONGODB_URI_SINGLE` and a username of `test_machine` that uses the `test_machine` token. - Perform a find operation that succeeds. - Close the client. From 531753e88c699e7a97b30222b517fa6393f7055d Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Mon, 22 Apr 2024 14:39:12 -0500 Subject: [PATCH 25/25] lint --- source/auth/tests/mongodb-oidc.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/auth/tests/mongodb-oidc.md b/source/auth/tests/mongodb-oidc.md index d1cdb20254..28588c89c4 100644 --- a/source/auth/tests/mongodb-oidc.md +++ b/source/auth/tests/mongodb-oidc.md @@ -294,7 +294,8 @@ this case, `MONGODB_URI_SINGLE` will be configured with a human user `test_user1 This test uses the machine user with a human callback, ensuring that the missing `clientId` in the `PrincipalStepRequest` response is handled by the driver. -- Create an OIDC configured client with `MONGODB_URI_SINGLE` and a username of `test_machine` that uses the `test_machine` token. +- Create an OIDC configured client with `MONGODB_URI_SINGLE` and a username of `test_machine` that uses the + `test_machine` token. - Perform a find operation that succeeds. - Close the client.