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

DRIVERS-2836 OIDC Spec Cleanup #1551

Merged
merged 31 commits into from
Apr 22, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
6e09e49
DRIVERS-2836 Only invalidate cached OIDC access tokens if the server …
blink1073 Mar 19, 2024
ed669eb
regenerate json
blink1073 Mar 19, 2024
a25518c
restore comment
blink1073 Mar 19, 2024
06e0110
add spec test for Refresh Token Is Passed To The Callback
blink1073 Mar 20, 2024
fd9481a
Merge branch 'master' of github.com:mongodb/specifications into DRIVE…
blink1073 Mar 21, 2024
739ae61
address review
blink1073 Mar 21, 2024
6ed2c94
Update source/auth/auth.md
blink1073 Apr 3, 2024
cef1ad2
Merge branch 'master' of github.com:mongodb/specifications into DRIVE…
blink1073 Apr 3, 2024
7ae7fea
Merge branch 'DRIVERS-2836' of github.com:blink1073/specifications in…
blink1073 Apr 3, 2024
958148e
Update source/auth/tests/mongodb-oidc.md
blink1073 Apr 3, 2024
83952e7
OIDC spec updates
blink1073 Apr 8, 2024
9027606
Merge branch 'master' of github.com:mongodb/specifications into DRIVE…
blink1073 Apr 8, 2024
3d98b29
Merge branch 'DRIVERS-2836' of github.com:blink1073/specifications in…
blink1073 Apr 8, 2024
b4e7905
update auth logic
blink1073 Apr 9, 2024
6815eb4
update error handling
blink1073 Apr 9, 2024
5967353
Update source/auth/auth.md
blink1073 Apr 10, 2024
3242bea
Update source/auth/auth.md
blink1073 Apr 10, 2024
ddd4054
Update source/auth/auth.md
blink1073 Apr 10, 2024
c263ad2
Update source/auth/auth.md
blink1073 Apr 10, 2024
119fce1
address review
blink1073 Apr 10, 2024
0f6f3bc
Update source/auth/tests/mongodb-oidc.md
blink1073 Apr 11, 2024
94ef18d
fix connection string tests
blink1073 Apr 11, 2024
13dc54c
clarify test conditions
blink1073 Apr 16, 2024
134c1f4
clarify spec test
blink1073 Apr 17, 2024
f24a075
fix SASL conversation
blink1073 Apr 19, 2024
5f63fea
fix grammar
blink1073 Apr 19, 2024
9e268e7
convert two unified tests to prose tests
blink1073 Apr 22, 2024
8cef9de
Update source/auth/tests/mongodb-oidc.md
blink1073 Apr 22, 2024
8471762
Update source/auth/tests/mongodb-oidc.md
blink1073 Apr 22, 2024
1716f23
Merge branch 'master' into DRIVERS-2836
blink1073 Apr 22, 2024
531753e
lint
blink1073 Apr 22, 2024
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
28 changes: 17 additions & 11 deletions source/auth/auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -1575,8 +1575,8 @@ Use the following algorithm to authenticate a new connection:

- Check if the the *Client Cache* has an access token.
katcharov marked this conversation as resolved.
Show resolved Hide resolved
- 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.
katcharov marked this conversation as resolved.
Show resolved Hide resolved
- 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.
Expand All @@ -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
blink1073 marked this conversation as resolved.
Show resolved Hide resolved
# 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)
blink1073 marked this conversation as resolved.
Show resolved Hide resolved
access_token, _ = get_access_token()

connection.oidc_cache.access_token = access_token
sasl_start(connection, payload={"jwt": access_token})
Expand All @@ -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.
katcharov marked this conversation as resolved.
Show resolved Hide resolved
- 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
Expand Down Expand Up @@ -1916,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\
Expand Down
67 changes: 61 additions & 6 deletions source/auth/tests/mongodb-oidc.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -205,13 +231,38 @@ 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.

**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.
blink1073 marked this conversation as resolved.
Show resolved Hide resolved
blink1073 marked this conversation as resolved.
Show resolved Hide resolved
- 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
}
}
```

- Perform a `find` operation that succeeds.
- Assert that the callback has been called twice.
- Assert that the refresh token was used once.
blink1073 marked this conversation as resolved.
Show resolved Hide resolved

### (3) Speculative Authentication

**3.1 Uses speculative authentication if there is a cached token**
Expand Down Expand Up @@ -240,12 +291,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
}
}
```
Expand All @@ -261,12 +314,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 // IllegalOperation
errorCode: 18
}
}
```
Expand Down Expand Up @@ -337,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:
Expand Down
57 changes: 22 additions & 35 deletions source/auth/tests/unified/mongodb-oidc-no-retry.json

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

12 changes: 7 additions & 5 deletions source/auth/tests/unified/mongodb-oidc-no-retry.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -211,19 +212,20 @@ tests:
client: failPointClient
failPoint:
configureFailPoint: failCommand
mode: "alwaysOn"
mode:
times: 1
data:
failCommands:
- saslStart
errorCode: 20 # IllegalOperation
errorCode: 18
- name: insertOne
object: collection0
arguments:
document:
_id: 1
x: 1
expectError:
errorCode: 20 # IllegalOperation
errorCode: 18
- description: Read commands should fail if reauthentication fails
operations:
- name: find
Expand Down
Loading