From 184451378fcbdd3af36510bcb903ba387d7c2b37 Mon Sep 17 00:00:00 2001 From: Alex Bevilacqua Date: Wed, 13 Nov 2024 08:34:51 -0500 Subject: [PATCH 01/10] added a docs/ directory --- docs/README.md | 3 + ...Workforce (Human) OIDC Auth For MongoDB.md | 166 ++++++++++++++++++ 2 files changed, 169 insertions(+) create mode 100644 docs/README.md create mode 100644 docs/Requirements for Client Applications implementing Workforce (Human) OIDC Auth For MongoDB.md diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000000..4291b7272b --- /dev/null +++ b/docs/README.md @@ -0,0 +1,3 @@ +# MongoDB Non-Drivers Specifications + +Supporting material for various MongoDB Drivers Specifications lives here diff --git a/docs/Requirements for Client Applications implementing Workforce (Human) OIDC Auth For MongoDB.md b/docs/Requirements for Client Applications implementing Workforce (Human) OIDC Auth For MongoDB.md new file mode 100644 index 0000000000..146cd70d8e --- /dev/null +++ b/docs/Requirements for Client Applications implementing Workforce (Human) OIDC Auth For MongoDB.md @@ -0,0 +1,166 @@ +# Requirements for Client Applications implementing Workforce (Human) OIDC Auth For MongoDB + +# Overview + +## Abstract + +MongoDB offers OpenID Connect (OIDC) authentication and authorization for database users. OIDC auth in clients generally falls into one of two categories; either Workflow OIDC targeting programmatic users, which is [fully specified here](https://github.com/mongodb/specifications/blob/master/source/auth/auth.md#mongodb-oidc) and does not involve user interaction, or Workforce OIDC targeting human users, which authenticate explicitly through means such as browsers. + +## Audience + +This document is intended for authors and maintainers of MongoDB client applications that implement Workforce OIDC authentication, or those who wish to understand existing implementations of it. This document does NOT describe the server implementation of OIDC, nor the details of OIDC protocol interactions that are part of external standards and generally implemented through the use of a third-party library. + +## Meta + +The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt). + +## Token acquisition flows + +Currently, all workforce OIDC clients in MongoDB support one or two mechanisms for acquiring OIDC tokens: + +* Authorization Code Flow with PKCE (short: Auth Code, PKCE is pronounced “pixie”) +* Device Authorization Grant (short: Device Auth) + +Auth Code Flow is generally the preferred mechanism. If an application decides to only support one of these flows, that should be the typical choice. If an application supports both flows, it MAY default to Auth Code Flow and fall back to Device Auth only if + +* The former is unavailable under specific circumstances, which are described in the Auth Code Flow section; and +* The user has explicitly indicated that Device Auth is enabled for this connection attempt. + +In both of these cases, the general chain of events is as follows: + +1. The user passes a connection string to the client application and indicates (possibly through said connection string) that they desire to use `MONGODB-OIDC` as their authentication mechanism. +2. The application connects to the MongoDB endpoint and asks it for information about the Identity Provider (IdP)[^1] it is supposed to authenticate with. If there was a username in the connection string, the application sends that as well. +3. The MongoDB endpoint responds with information about the IdP, in the form of an `issuer` URL identifying the IdP and other metadata about it. +4. The application looks up the public metadata document for the IdP, which includes information about user-facing URL endpoints. +5. The application composes a URL based on those endpoints and presents it to the user in some form (the details depend on the exact flow chosen). +6. The user visits that URL, which can result in any number of steps to authenticate the user. +7. The application receives a token from the IdP (the details again depend on the exact flow chosen). +8. The application presents this token to the MongoDB endpoint. + +Since in these steps the client application performs actions depending on information supplied by external sources, this document specifies mechanisms that help ensure that these actions are carried out securely. MongoDB clients are “public clients” in the sense of the OIDC specs (which do not have a shared secret with the Identity Provider), and must behave accordingly. + +Since these steps require the involvement of a human being, the application should be set up to gracefully handle timeouts and provide the user with a way to abort the connection attempt. + +# General requirements + +An application implementing workforce OIDC needs to generally comply with OpenID and OAuth 2.0 standards. + +In particular: + +* Any HTTP calls made to non-local servers MUST be made using HTTPS. +* IdP metadata discovery MUST be implemented as described in [RFC8414](https://datatracker.ietf.org/doc/html/rfc8414). + +Using a well-tested and standards-compliant third-party library for core OIDC logic for the respective ecosystem is highly recommended. If this is not possible, implementers need to pay special attention to the specifications referenced in this document. + +## Endpoint restrictions + +Currently, users who connect to a host other than localhost or an Atlas hostname need to explicitly opt-in into being able to do so by setting the `ALLOWED_HOSTS` flag (specified in the drivers auth spec). In the future, MongoDB is hoping to support Demonstrating Proof of Possession (DPoP, [RFC9449](https://datatracker.ietf.org/doc/html/rfc9449)) that will allow lifting this restriction. The goal here is to prevent users from connecting to malicious endpoints that will advertise attacker-controlled IdP metadata and and intercept tokens intended for other clusters (or even other OIDC endpoints in general). + +We would also like to generally adopt [RFC8707](https://datatracker.ietf.org/doc/html/rfc8707), but have not decided on a specific format for expressing the MongoDB endpoints as resources. + +## Token management + +After a successful authentication, applications SHOULD periodically attempt to use the OIDC token refresh mechanism in order to exchange the access token it uses for a fresh one. The refresh interval SHOULD be determined by the token expiry time indicated by the Identity Provider. If the refresh attempt fails, the application MAY ask or suggest the user to re-authenticate from scratch, even if the currently used access token has not expired yet. + +Under normal circumstances, the application provides an access token received from the Identity Provider to the driver. The application SHOULD provide a toggle to users that can be used to indicate that it should use the ID token, rather than the access token, in its place.[^2] + +## OIDC Scopes + +The initial request to the IdP involves specifying the `scope` parameter. This is a space-separated unordered list of strings which contains: + +* The scopes listed in the `requestScopes` field of the IdP response from the MongoDB endpoint, and +* The `openid` and `offline_access` scopes[^3]. If the IdP metadata document contains a `scopes_supported` field, and this field does not list one of these scopes, then the respective scope SHOULD NOT be added to the `scope` parameter. + +# Authorization Code Flow + +In this flow, the client application uses a local HTTP server to receive a response from the Identity Provider, as described in [RFC8252](https://datatracker.ietf.org/doc/html/rfc8252).[^4] The application follows these steps: + +1. Generate a code challenge for PKCE using cryptographically random data, as described in [RFC7636](https://datatracker.ietf.org/doc/html/rfc7636). +2. Spin up a local HTTP server. The default (incoming) redirect URL for MongoDB applications is `http://localhost:27097/redirect`, which MAY be configurable. If the application allows configuring the URL, the port MAY be specified as `0` to allow listening on an arbitrary port. The application listens on the host and port listed in the URL. The application MUST listen on all addresses that the hostname resolves to through `getaddrinfo()`, and MUST listen on the same port in all cases. If listening on any address fails, or `getaddrinfo()` did not return any addresses, it must abort this process and the application MAY fall back to Device Auth. + 1. To preserve privacy, pages served from this local HTTP server MUST NOT reference external resources directly. They MAY provide external links that require user interaction. + 2. The HTTP server SHOULD set default headers of `Content-Security-Policy: default-src 'self'` and `Referrer-Policy: no-referrer`, or similarly restrictive defaults. +3. Compose the URL for Auth Code Flow, using the code challenge generated earlier and the redirect URL from the previous step, with the port replaced with the actual port if it was specified as `0`. The application MUST add a `state` parameter containing cryptographically random data ([RFC6749](https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.1) specifies this as optional but recommended). +4. The application SHOULD, instead of directly presenting the URL from the previous step to the user, register that URL as an outgoing HTTP 307 redirect from the local HTTP server. The redirect base URL SHOULD contain a piece of cryptographically random data. The advantage of this approach are that: + 1. The application can ensure that the URL that is passed to the browser in the next step does not contain special characters (other than the typical `/` and `:` present in URLs) which would need to be escaped when opening a browser through a shell command. + 2. It allows tracking whether the URL has been accessed, i.e. get a definite confirmation of whether the user successfully opened it in a browser. +5. Open a browser pointing at that URL, or instruct the user to do so. The former approach is preferred. If opening a browser fails, the application MAY fall back to Device Auth. +6. Wait until one of the following events occurs: + 1. The local outgoing redirect URL is accessed (if any). + 2. Opening the browser fails. + 3. A timeout occurs or the connection attempt is aborted. +7. Wait until the incoming redirect URL is accessed in a valid way, i.e. using GET or POST with the correct `state` parameter and without an `error` parameter. If the incoming redirect URL is accessed with a mismatching `state` parameter or the `error` parameter is set, the application SHOULD display a helpful error page. If an `iss` parameter is present, it MUST be validated according to [RFC9207](https://datatracker.ietf.org/doc/html/rfc9207), i.e. compare equal to the `issuer` string in the issuer metadata document. Subsequent requests to the incoming redirect URL should be rejected. + 1. If error parameters such as `error`, `error_description` and/or `error_uri` are displayed to the user, they MUST be validated to match the `NQSCHAR` definition of [RFC6749](https://datatracker.ietf.org/doc/html/rfc6749) (and in the case of `error_uri`, a valid URI) before doing so, and they MUST be escaped as appropriate for the chosen display format. +8. The application MUST redirect from the incoming redirect URL to a different URL on the same local HTTP server as a HTTP 303 redirect, removing all query parameters and/or the request body. The target page SHOULD indicate successful authentication to the Identity Provider, and SHOULD clarify that the user is not authenticated with the MongoDB endpoint yet. It MAY be updated once the application successfully authenticates against the MongoDB endpoint to reflect that. +9. Stop listening on and close the local HTTP server. As browsers may keep lingering open connections, the application SHOULD ensure that these connections do not prevent the application from progressing to the next step (i.e. do not block closing the server). +10. Verify the parameters it received against the initial PKCE code challenge. +11. Perform a request to the OIDC token endpoint using the code received from the IdP on the incoming redirect URL. +12. Provide the token it received from the token endpoint to the MongoDB driver. + +The developer tools team owns example templates for the local HTTP server at [https://github.com/mongodb-js/devtools-shared/tree/main/packages/oidc-http-server-pages](https://github.com/mongodb-js/devtools-shared/tree/main/packages/oidc-http-server-pages), and publishes templates that can be accessed at e.g. [https://unpkg.com/@mongodb-js/oidc-http-server-pages/dist/templates.gz](https://unpkg.com/@mongodb-js/oidc-http-server-pages/dist/templates.gz). + +# Device Auth Grant + +This flow is optional, and MUST NOT be used unless either: + +* The application has been unable to open a browser locally (e.g. in headless environments), or unable to listen on a local HTTP endpoint, and the user has explicitly indicated that falling back to this flow is acceptable; or +* The user has explicitly requested this flow. + +It is significantly simpler than the Auth Code Flow, but generally considered the less secure one between the two, and more susceptible to e.g. phishing attacks. + +The application follows these steps: + +1. Reach out to the IdP device authorization endpoint. This should result in a URL and a “user code”. +2. Present the URL and the user code to the user, expecting the user to open that URL manually (possibly on a different device). +3. Repeatedly poll the token endpoint for an access token. +4. Provide the token it received from the token endpoint to the MongoDB driver. + +# Diagnostics + +It is recommended to log the following events for diagnostic purposes: + +* All outgoing HTTP calls, minus sensitive information (e.g. URLs, with search parameter values redacted) +* All inbound HTTP calls, minus sensitive information +* Starting to listen on the local HTTP server, including port and address(es), and whether that was successful or not +* Incoming redirect to the local HTTP server accessed and whether the redirect was accepted or rejected +* Closing of the local HTTP server +* Browser opening and whether it were successful or not +* Acquisition of new tokens from the Identity Provider, and in particular whether an ID token was present or not +* Token refresh attempts and whether they were successful or not + +# Appendix: Relevant standards (non-exhaustive) + +* [RFC6749](https://datatracker.ietf.org/doc/html/rfc6749): The OAuth 2.0 Authorization Framework +* [RFC6819](https://datatracker.ietf.org/doc/html/rfc6819): OAuth 2.0 Threat Model and Security Considerations +* [RFC7636](https://datatracker.ietf.org/doc/html/rfc7636): Proof Key for Code Exchange by OAuth Public Clients (PKCE) +* [RFC8252](https://datatracker.ietf.org/doc/html/rfc8252): OAuth 2.0 for Native Apps +* [RFC8414](https://datatracker.ietf.org/doc/html/rfc8414): OAuth 2.0 Authorization Server Metadata +* [RFC8628](https://datatracker.ietf.org/doc/html/rfc8628): OAuth 2.0 Device Authorization Grant +* [RFC8707](https://datatracker.ietf.org/doc/html/rfc8707): Resource Indicators for OAuth 2.0 +* [RFC9207](https://datatracker.ietf.org/doc/html/rfc9207): OAuth 2.0 Authorization Server Issuer Identification +* [RFC9449](https://datatracker.ietf.org/doc/html/rfc9449): OAuth 2.0 Demonstrating Proof of Possession (DPoP) +* [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html) +* [Draft](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics): OAuth 2.0 Security Best Current Practice +* [Risk of phishing Access Tokens from clients using OIDC Authentication](https://docs.google.com/document/d/1TdcBtRu4yNXQkI7ZdKWZlSIaWs29tIQblyS3805nK1A/edit?tab=t.0) + +# Appendix: Multiple MongoClients + +Some applications may require support for multiple concurrent MongoClients using the same OIDC tokens. In this case, a token set (access token, ID token and refresh token) may be re-used, if and only if: + +* The `username` parameter is equal +* The IdP metadata provided by the MongoDB endpoint is equal +* Both token sets contain an ID token and the respective `aud` and `sub` claims[^5] of the ID tokens are equal, OR neither token set contains an ID token + +If an application supports multiple MongoClients, it MUST ensure that only one token acquisition flow is in use at the same time, and coordinate token refresh intervals accordingly. + +The Developer Tools team maintains an implementation that integrates with multiple MongoClient instances at [https://github.com/mongodb-js/oidc-plugin](https://github.com/mongodb-js/oidc-plugin), which can be used as a reference implementation (and which can generally be used in other applications based on the Node.js driver, although as a standalone package it is not considered a supported product of MongoDB). + + +[^1]: Technically, this refers to an Authorization Server (AS). Inside MongoDB, the usage of AS and IdP has been considered more or less interchangeable. + +[^2]: At the time of writing, there are Identity Providers which do not support JWT access tokens, but which do provide JWT ID tokens that are usable for authentication. This requires opt-in on both the server configuration side and the client side. + +[^3]: The `offline_access` scope is what provides the ability to refresh tokens without performing a full re-authentication. Some particularly security-sensitive customers may choose this approach at the expense of a greatly diminished UX, where users need to frequently re-authenticate. + +[^4]: [RFC8252](https://datatracker.ietf.org/doc/html/rfc8252) lays out alternatives to this approach, such as registering a custom URI scheme handler or registering “Claims” on specific HTTPS URLs, but we’ve decided not to pursue these approaches in any existing applications, since some of our applications are CLI applications without an installation step where neither of these alternative approaches is feasible. + +[^5]: OIDC as a protocol allows for `aud` claims that contain multiple strings, instead of a single one. MongoDB endpoints are [restricted](https://jira.mongodb.org/browse/SERVER-86607) to single-value `aud` claims, although client applications do not need to be concerned with this restriction. \ No newline at end of file From 5a9549c204b37bcfe69b29660555f597197403dd Mon Sep 17 00:00:00 2001 From: Alex Bevilacqua Date: Wed, 13 Nov 2024 08:36:10 -0500 Subject: [PATCH 02/10] add Requirements for Client Applications implementing Workforce (Human) OIDC Auth For MongoDB --- docs/README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index 4291b7272b..a2efd5955e 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,3 +1,7 @@ # MongoDB Non-Drivers Specifications -Supporting material for various MongoDB Drivers Specifications lives here +Supporting material for various MongoDB Drivers Specifications lives here. + +## Authentication + +* [Requirements for Client Applications implementing Workforce (Human) OIDC Auth For MongoDB](Requirements for Client Applications implementing Workforce (Human) OIDC Auth For MongoDB.md) From 5217d3d957bca7598d540b40a214b2768e91a93a Mon Sep 17 00:00:00 2001 From: Alex Bevilacqua Date: Wed, 13 Nov 2024 08:37:11 -0500 Subject: [PATCH 03/10] add Requirements for Client Applications implementing Workforce (Human) OIDC Auth For MongoDB --- docs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index a2efd5955e..5c12a4ca20 100644 --- a/docs/README.md +++ b/docs/README.md @@ -4,4 +4,4 @@ Supporting material for various MongoDB Drivers Specifications lives here. ## Authentication -* [Requirements for Client Applications implementing Workforce (Human) OIDC Auth For MongoDB](Requirements for Client Applications implementing Workforce (Human) OIDC Auth For MongoDB.md) +* [Requirements for Client Applications implementing Workforce (Human) OIDC Auth For MongoDB](./Requirements%20for%20Client%20Applications%20implementing%20Workforce%20(Human)%20OIDC%20Auth%20For%20MongoDB.md) From 2324eb7604c2e6bd7bbb8716b233f9516e490b40 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Thu, 14 Nov 2024 15:37:09 +0100 Subject: [PATCH 04/10] small editorial fixes --- ...ongoDB.md => workforce-human-oidc-auth.md} | 134 +++++++++--------- 1 file changed, 70 insertions(+), 64 deletions(-) rename docs/{Requirements for Client Applications implementing Workforce (Human) OIDC Auth For MongoDB.md => workforce-human-oidc-auth.md} (82%) diff --git a/docs/Requirements for Client Applications implementing Workforce (Human) OIDC Auth For MongoDB.md b/docs/workforce-human-oidc-auth.md similarity index 82% rename from docs/Requirements for Client Applications implementing Workforce (Human) OIDC Auth For MongoDB.md rename to docs/workforce-human-oidc-auth.md index 146cd70d8e..511c51c724 100644 --- a/docs/Requirements for Client Applications implementing Workforce (Human) OIDC Auth For MongoDB.md +++ b/docs/workforce-human-oidc-auth.md @@ -8,7 +8,7 @@ MongoDB offers OpenID Connect (OIDC) authentication and authorization for databa ## Audience -This document is intended for authors and maintainers of MongoDB client applications that implement Workforce OIDC authentication, or those who wish to understand existing implementations of it. This document does NOT describe the server implementation of OIDC, nor the details of OIDC protocol interactions that are part of external standards and generally implemented through the use of a third-party library. +This document is intended for authors and maintainers of MongoDB client applications that implement Workforce OIDC authentication, or those who wish to understand existing implementations of it. This document does *not* describe the server implementation of OIDC, nor the details of OIDC protocol interactions that are part of external standards and generally implemented through the use of a third-party library. ## Meta @@ -18,43 +18,43 @@ The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SH Currently, all workforce OIDC clients in MongoDB support one or two mechanisms for acquiring OIDC tokens: -* Authorization Code Flow with PKCE (short: Auth Code, PKCE is pronounced “pixie”) -* Device Authorization Grant (short: Device Auth) +* Authorization Code Flow with PKCE (short: Auth Code, PKCE is pronounced “pixie”) +* Device Authorization Grant (short: Device Auth) -Auth Code Flow is generally the preferred mechanism. If an application decides to only support one of these flows, that should be the typical choice. If an application supports both flows, it MAY default to Auth Code Flow and fall back to Device Auth only if +Auth Code Flow is generally the preferred mechanism. If an application decides to only support one of these flows, that should be the typical choice. If an application supports both flows, it MAY default to Auth Code Flow and fall back to Device Auth only if -* The former is unavailable under specific circumstances, which are described in the Auth Code Flow section; and +* The former is unavailable under specific circumstances, which are described in the Auth Code Flow section; and * The user has explicitly indicated that Device Auth is enabled for this connection attempt. In both of these cases, the general chain of events is as follows: -1. The user passes a connection string to the client application and indicates (possibly through said connection string) that they desire to use `MONGODB-OIDC` as their authentication mechanism. -2. The application connects to the MongoDB endpoint and asks it for information about the Identity Provider (IdP)[^1] it is supposed to authenticate with. If there was a username in the connection string, the application sends that as well. -3. The MongoDB endpoint responds with information about the IdP, in the form of an `issuer` URL identifying the IdP and other metadata about it. -4. The application looks up the public metadata document for the IdP, which includes information about user-facing URL endpoints. -5. The application composes a URL based on those endpoints and presents it to the user in some form (the details depend on the exact flow chosen). -6. The user visits that URL, which can result in any number of steps to authenticate the user. -7. The application receives a token from the IdP (the details again depend on the exact flow chosen). +1. The user passes a connection string to the client application and indicates (possibly through said connection string) that they desire to use `MONGODB-OIDC` as their authentication mechanism. +2. The application connects to the MongoDB endpoint and asks it for information about the Identity Provider (IdP)[^1] it is supposed to authenticate with. If there was a username in the connection string, the application sends that as well. +3. The MongoDB endpoint responds with information about the IdP, in the form of an `issuer` URL identifying the IdP and other metadata about it. +4. The application looks up the public metadata document for the IdP, which includes information about user-facing URL endpoints. +5. The application composes a URL based on those endpoints and presents it to the user in some form (the details depend on the exact flow chosen). +6. The user visits that URL, which can result in any number of steps to authenticate the user. +7. The application receives a token from the IdP (the details again depend on the exact flow chosen). 8. The application presents this token to the MongoDB endpoint. -Since in these steps the client application performs actions depending on information supplied by external sources, this document specifies mechanisms that help ensure that these actions are carried out securely. MongoDB clients are “public clients” in the sense of the OIDC specs (which do not have a shared secret with the Identity Provider), and must behave accordingly. +Since in these steps the client application performs actions depending on information supplied by external sources, this document specifies mechanisms that help ensure that these actions are carried out securely. MongoDB clients are “public clients” in the sense of the OIDC specs (i.e. they do not possess a shared secret with the Identity Provider), and must behave accordingly. Since these steps require the involvement of a human being, the application should be set up to gracefully handle timeouts and provide the user with a way to abort the connection attempt. # General requirements -An application implementing workforce OIDC needs to generally comply with OpenID and OAuth 2.0 standards. +An application implementing workforce OIDC needs to generally comply with OpenID and OAuth 2.0 standards. In particular: -* Any HTTP calls made to non-local servers MUST be made using HTTPS. +* Any HTTP calls made to non-local servers MUST be made using HTTPS. * IdP metadata discovery MUST be implemented as described in [RFC8414](https://datatracker.ietf.org/doc/html/rfc8414). Using a well-tested and standards-compliant third-party library for core OIDC logic for the respective ecosystem is highly recommended. If this is not possible, implementers need to pay special attention to the specifications referenced in this document. ## Endpoint restrictions -Currently, users who connect to a host other than localhost or an Atlas hostname need to explicitly opt-in into being able to do so by setting the `ALLOWED_HOSTS` flag (specified in the drivers auth spec). In the future, MongoDB is hoping to support Demonstrating Proof of Possession (DPoP, [RFC9449](https://datatracker.ietf.org/doc/html/rfc9449)) that will allow lifting this restriction. The goal here is to prevent users from connecting to malicious endpoints that will advertise attacker-controlled IdP metadata and and intercept tokens intended for other clusters (or even other OIDC endpoints in general). +Currently, users who connect to a host other than localhost or an Atlas hostname need to explicitly opt-in into being able to do so by setting the `ALLOWED_HOSTS` flag (specified in the drivers auth spec). In the future, MongoDB is hoping to support Demonstrating Proof of Possession (DPoP, [RFC9449](https://datatracker.ietf.org/doc/html/rfc9449)) that will allow lifting this restriction. The goal here is to prevent users from connecting to untrusted endpoints that will advertise attacker-controlled IdP metadata and and intercept tokens intended for other clusters (or even other OIDC endpoints in general). We would also like to generally adopt [RFC8707](https://datatracker.ietf.org/doc/html/rfc8707), but have not decided on a specific format for expressing the MongoDB endpoints as resources. @@ -68,32 +68,34 @@ Under normal circumstances, the application provides an access token received fr The initial request to the IdP involves specifying the `scope` parameter. This is a space-separated unordered list of strings which contains: -* The scopes listed in the `requestScopes` field of the IdP response from the MongoDB endpoint, and +* The scopes listed in the `requestScopes` field of the IdP response from the MongoDB endpoint, and * The `openid` and `offline_access` scopes[^3]. If the IdP metadata document contains a `scopes_supported` field, and this field does not list one of these scopes, then the respective scope SHOULD NOT be added to the `scope` parameter. # Authorization Code Flow In this flow, the client application uses a local HTTP server to receive a response from the Identity Provider, as described in [RFC8252](https://datatracker.ietf.org/doc/html/rfc8252).[^4] The application follows these steps: -1. Generate a code challenge for PKCE using cryptographically random data, as described in [RFC7636](https://datatracker.ietf.org/doc/html/rfc7636). -2. Spin up a local HTTP server. The default (incoming) redirect URL for MongoDB applications is `http://localhost:27097/redirect`, which MAY be configurable. If the application allows configuring the URL, the port MAY be specified as `0` to allow listening on an arbitrary port. The application listens on the host and port listed in the URL. The application MUST listen on all addresses that the hostname resolves to through `getaddrinfo()`, and MUST listen on the same port in all cases. If listening on any address fails, or `getaddrinfo()` did not return any addresses, it must abort this process and the application MAY fall back to Device Auth. - 1. To preserve privacy, pages served from this local HTTP server MUST NOT reference external resources directly. They MAY provide external links that require user interaction. - 2. The HTTP server SHOULD set default headers of `Content-Security-Policy: default-src 'self'` and `Referrer-Policy: no-referrer`, or similarly restrictive defaults. -3. Compose the URL for Auth Code Flow, using the code challenge generated earlier and the redirect URL from the previous step, with the port replaced with the actual port if it was specified as `0`. The application MUST add a `state` parameter containing cryptographically random data ([RFC6749](https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.1) specifies this as optional but recommended). -4. The application SHOULD, instead of directly presenting the URL from the previous step to the user, register that URL as an outgoing HTTP 307 redirect from the local HTTP server. The redirect base URL SHOULD contain a piece of cryptographically random data. The advantage of this approach are that: - 1. The application can ensure that the URL that is passed to the browser in the next step does not contain special characters (other than the typical `/` and `:` present in URLs) which would need to be escaped when opening a browser through a shell command. - 2. It allows tracking whether the URL has been accessed, i.e. get a definite confirmation of whether the user successfully opened it in a browser. -5. Open a browser pointing at that URL, or instruct the user to do so. The former approach is preferred. If opening a browser fails, the application MAY fall back to Device Auth. -6. Wait until one of the following events occurs: - 1. The local outgoing redirect URL is accessed (if any). - 2. Opening the browser fails. - 3. A timeout occurs or the connection attempt is aborted. -7. Wait until the incoming redirect URL is accessed in a valid way, i.e. using GET or POST with the correct `state` parameter and without an `error` parameter. If the incoming redirect URL is accessed with a mismatching `state` parameter or the `error` parameter is set, the application SHOULD display a helpful error page. If an `iss` parameter is present, it MUST be validated according to [RFC9207](https://datatracker.ietf.org/doc/html/rfc9207), i.e. compare equal to the `issuer` string in the issuer metadata document. Subsequent requests to the incoming redirect URL should be rejected. - 1. If error parameters such as `error`, `error_description` and/or `error_uri` are displayed to the user, they MUST be validated to match the `NQSCHAR` definition of [RFC6749](https://datatracker.ietf.org/doc/html/rfc6749) (and in the case of `error_uri`, a valid URI) before doing so, and they MUST be escaped as appropriate for the chosen display format. -8. The application MUST redirect from the incoming redirect URL to a different URL on the same local HTTP server as a HTTP 303 redirect, removing all query parameters and/or the request body. The target page SHOULD indicate successful authentication to the Identity Provider, and SHOULD clarify that the user is not authenticated with the MongoDB endpoint yet. It MAY be updated once the application successfully authenticates against the MongoDB endpoint to reflect that. -9. Stop listening on and close the local HTTP server. As browsers may keep lingering open connections, the application SHOULD ensure that these connections do not prevent the application from progressing to the next step (i.e. do not block closing the server). -10. Verify the parameters it received against the initial PKCE code challenge. -11. Perform a request to the OIDC token endpoint using the code received from the IdP on the incoming redirect URL. +1. Generate a code challenge for PKCE using cryptographically random data, as described in [RFC7636](https://datatracker.ietf.org/doc/html/rfc7636). +2. Spin up a local HTTP server. The default (incoming) redirect URL for MongoDB applications is `http://localhost:27097/redirect`, which MAY be configurable. If the application allows configuring the URL, the port MAY be specified as `0` to allow listening on an arbitrary port. The application listens on the host and port listed in the URL. The application MUST listen on all addresses that the hostname resolves to through `getaddrinfo()`, and MUST listen on the same port in all cases. If listening on any address fails, or `getaddrinfo()` did not return any addresses, it must abort this process and the application MAY fall back to Device Auth. + 1. To preserve privacy, pages served from this local HTTP server MUST NOT reference external resources directly. They MAY provide external links that require user interaction. + 2. The HTTP server SHOULD set default headers of `Content-Security-Policy: default-src 'self'` and `Referrer-Policy: no-referrer`, or similarly restrictive defaults. +3. Compose the URL for Auth Code Flow, using the code challenge generated earlier and the redirect URL from the previous step, with the port replaced with the actual port if it was specified as `0`. + 1. The application MUST add a `state` parameter containing cryptographically random data ([RFC6749](https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.1) specifies this as optional but recommended). + 2. The application MAY allow the user to indicate that it should add a `nonce` parameter containing cryptographically random data to the authentication request, as defined in the OpenID connect specification, which is then later embedded in the ID token itself. +4. The application SHOULD, instead of directly presenting the URL from the previous step to the user, register that URL as an outgoing HTTP 307 redirect from the local HTTP server. The redirect base URL SHOULD contain a piece of cryptographically random data. The advantages of this approach are that: + 1. The application can ensure that the URL that is passed to the browser in the next step does not contain special characters (other than the typical `/` and `:` present in URLs) which would need to be escaped when opening a browser through a shell command. + 2. It allows tracking whether the URL has been accessed, i.e. get a definite confirmation of whether the user successfully opened it in a browser. +5. Open a browser pointing at that URL, or instruct the user to do so. The former approach is preferred. If opening a browser fails, the application MAY fall back to Device Auth. +6. Wait until one of the following events occurs: + 1. The local outgoing redirect URL is accessed (if any). + 2. Opening the browser fails. + 3. A timeout occurs or the connection attempt is aborted. +7. Wait until the incoming redirect URL is accessed in a valid way, i.e. using GET or POST with the correct `state` parameter and without an `error` parameter. If the incoming redirect URL is accessed with a mismatching `state` parameter or the `error` parameter is set, the application SHOULD display a helpful error page. If an `iss` parameter is present, it MUST be validated according to [RFC9207](https://datatracker.ietf.org/doc/html/rfc9207), i.e. compare equal to the `issuer` string in the issuer metadata document. Subsequent requests to the incoming redirect URL should be rejected. + 1. If error parameters such as `error`, `error_description` and/or `error_uri` are displayed to the user, they MUST be validated to match the `NQSCHAR` definition of [RFC6749](https://datatracker.ietf.org/doc/html/rfc6749) (and in the case of `error_uri`, a valid URI) before doing so, and they MUST be escaped as appropriate for the chosen display format. +8. The application MUST redirect from the incoming redirect URL to a different URL on the same local HTTP server as a HTTP 303 redirect, removing all query parameters and/or the request body. The target page SHOULD indicate successful authentication to the Identity Provider, and SHOULD clarify that the user is not authenticated with the MongoDB endpoint yet. It MAY be updated once the application successfully authenticates against the MongoDB endpoint to reflect that. +9. Stop listening on and close the local HTTP server. As browsers may keep lingering open connections, the application SHOULD ensure that these connections do not prevent the application from progressing to the next step (i.e. do not block closing the server). +10. Verify the parameters it received against the initial PKCE code challenge. +11. Perform a request to the OIDC token endpoint using the code received from the IdP on the incoming redirect URL. 12. Provide the token it received from the token endpoint to the MongoDB driver. The developer tools team owns example templates for the local HTTP server at [https://github.com/mongodb-js/devtools-shared/tree/main/packages/oidc-http-server-pages](https://github.com/mongodb-js/devtools-shared/tree/main/packages/oidc-http-server-pages), and publishes templates that can be accessed at e.g. [https://unpkg.com/@mongodb-js/oidc-http-server-pages/dist/templates.gz](https://unpkg.com/@mongodb-js/oidc-http-server-pages/dist/templates.gz). @@ -102,65 +104,69 @@ The developer tools team owns example templates for the local HTTP server at [ht This flow is optional, and MUST NOT be used unless either: -* The application has been unable to open a browser locally (e.g. in headless environments), or unable to listen on a local HTTP endpoint, and the user has explicitly indicated that falling back to this flow is acceptable; or +* The application has been unable to open a browser locally (e.g. in headless environments), or unable to listen on a local HTTP endpoint, and the user has explicitly indicated that falling back to this flow is acceptable; or * The user has explicitly requested this flow. It is significantly simpler than the Auth Code Flow, but generally considered the less secure one between the two, and more susceptible to e.g. phishing attacks. The application follows these steps: -1. Reach out to the IdP device authorization endpoint. This should result in a URL and a “user code”. -2. Present the URL and the user code to the user, expecting the user to open that URL manually (possibly on a different device). -3. Repeatedly poll the token endpoint for an access token. +1. Reach out to the IdP device authorization endpoint. This should result in a URL and a “user code”. +2. Present the URL and the user code to the user, expecting the user to open that URL manually (possibly on a different device). +3. Repeatedly poll the token endpoint for an access token. 4. Provide the token it received from the token endpoint to the MongoDB driver. # Diagnostics It is recommended to log the following events for diagnostic purposes: -* All outgoing HTTP calls, minus sensitive information (e.g. URLs, with search parameter values redacted) -* All inbound HTTP calls, minus sensitive information -* Starting to listen on the local HTTP server, including port and address(es), and whether that was successful or not -* Incoming redirect to the local HTTP server accessed and whether the redirect was accepted or rejected -* Closing of the local HTTP server -* Browser opening and whether it were successful or not -* Acquisition of new tokens from the Identity Provider, and in particular whether an ID token was present or not +* All outgoing HTTP calls, minus sensitive information (e.g. URLs, with search parameter values redacted) +* All inbound HTTP calls, minus sensitive information +* Starting to listen on the local HTTP server, including port and address(es), and whether that was successful or not +* Incoming redirect to the local HTTP server accessed and whether the redirect was accepted or rejected +* Closing of the local HTTP server +* Browser opening and whether it were successful or not +* Acquisition of new tokens from the Identity Provider, and in particular whether an ID token was present or not * Token refresh attempts and whether they were successful or not # Appendix: Relevant standards (non-exhaustive) -* [RFC6749](https://datatracker.ietf.org/doc/html/rfc6749): The OAuth 2.0 Authorization Framework -* [RFC6819](https://datatracker.ietf.org/doc/html/rfc6819): OAuth 2.0 Threat Model and Security Considerations -* [RFC7636](https://datatracker.ietf.org/doc/html/rfc7636): Proof Key for Code Exchange by OAuth Public Clients (PKCE) -* [RFC8252](https://datatracker.ietf.org/doc/html/rfc8252): OAuth 2.0 for Native Apps -* [RFC8414](https://datatracker.ietf.org/doc/html/rfc8414): OAuth 2.0 Authorization Server Metadata -* [RFC8628](https://datatracker.ietf.org/doc/html/rfc8628): OAuth 2.0 Device Authorization Grant -* [RFC8707](https://datatracker.ietf.org/doc/html/rfc8707): Resource Indicators for OAuth 2.0 -* [RFC9207](https://datatracker.ietf.org/doc/html/rfc9207): OAuth 2.0 Authorization Server Issuer Identification -* [RFC9449](https://datatracker.ietf.org/doc/html/rfc9449): OAuth 2.0 Demonstrating Proof of Possession (DPoP) -* [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html) -* [Draft](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics): OAuth 2.0 Security Best Current Practice +* [RFC6749](https://datatracker.ietf.org/doc/html/rfc6749): The OAuth 2.0 Authorization Framework +* [RFC6819](https://datatracker.ietf.org/doc/html/rfc6819): OAuth 2.0 Threat Model and Security Considerations +* [RFC7636](https://datatracker.ietf.org/doc/html/rfc7636): Proof Key for Code Exchange by OAuth Public Clients (PKCE) +* [RFC8252](https://datatracker.ietf.org/doc/html/rfc8252): OAuth 2.0 for Native Apps +* [RFC8414](https://datatracker.ietf.org/doc/html/rfc8414): OAuth 2.0 Authorization Server Metadata +* [RFC8628](https://datatracker.ietf.org/doc/html/rfc8628): OAuth 2.0 Device Authorization Grant +* [RFC8707](https://datatracker.ietf.org/doc/html/rfc8707): Resource Indicators for OAuth 2.0 +* [RFC9207](https://datatracker.ietf.org/doc/html/rfc9207): OAuth 2.0 Authorization Server Issuer Identification +* [RFC9449](https://datatracker.ietf.org/doc/html/rfc9449): OAuth 2.0 Demonstrating Proof of Possession (DPoP) +* [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html) +* [Draft](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics): OAuth 2.0 Security Best Current Practice * [Risk of phishing Access Tokens from clients using OIDC Authentication](https://docs.google.com/document/d/1TdcBtRu4yNXQkI7ZdKWZlSIaWs29tIQblyS3805nK1A/edit?tab=t.0) # Appendix: Multiple MongoClients Some applications may require support for multiple concurrent MongoClients using the same OIDC tokens. In this case, a token set (access token, ID token and refresh token) may be re-used, if and only if: -* The `username` parameter is equal -* The IdP metadata provided by the MongoDB endpoint is equal -* Both token sets contain an ID token and the respective `aud` and `sub` claims[^5] of the ID tokens are equal, OR neither token set contains an ID token +* The `username` parameter is equal +* The IdP metadata provided by the MongoDB endpoint is equal +* Both token sets contain an ID token and the respective `aud` and `sub` claims[^5] of the ID tokens are equal, OR neither token set contains an ID token If an application supports multiple MongoClients, it MUST ensure that only one token acquisition flow is in use at the same time, and coordinate token refresh intervals accordingly. -The Developer Tools team maintains an implementation that integrates with multiple MongoClient instances at [https://github.com/mongodb-js/oidc-plugin](https://github.com/mongodb-js/oidc-plugin), which can be used as a reference implementation (and which can generally be used in other applications based on the Node.js driver, although as a standalone package it is not considered a supported product of MongoDB). +The Developer Tools team maintains an implementation that integrates with multiple MongoClient instances at [https://github.com/mongodb-js/oidc-plugin](https://github.com/mongodb-js/oidc-plugin), which can be used as a reference implementation (and which can generally be used in other applications based on the Node.js driver, although as a standalone package it is not considered a supported product of MongoDB). +## Changelog + +- 2024-11-14: Initial version. [^1]: Technically, this refers to an Authorization Server (AS). Inside MongoDB, the usage of AS and IdP has been considered more or less interchangeable. [^2]: At the time of writing, there are Identity Providers which do not support JWT access tokens, but which do provide JWT ID tokens that are usable for authentication. This requires opt-in on both the server configuration side and the client side. -[^3]: The `offline_access` scope is what provides the ability to refresh tokens without performing a full re-authentication. Some particularly security-sensitive customers may choose this approach at the expense of a greatly diminished UX, where users need to frequently re-authenticate. +[^3]: The `offline_access` scope is what provides the ability to refresh tokens without performing a full re-authentication. Some particularly security-sensitive customers may choose this approach at the expense of a greatly diminished UX, where users need to frequently re-authenticate. [^4]: [RFC8252](https://datatracker.ietf.org/doc/html/rfc8252) lays out alternatives to this approach, such as registering a custom URI scheme handler or registering “Claims” on specific HTTPS URLs, but we’ve decided not to pursue these approaches in any existing applications, since some of our applications are CLI applications without an installation step where neither of these alternative approaches is feasible. -[^5]: OIDC as a protocol allows for `aud` claims that contain multiple strings, instead of a single one. MongoDB endpoints are [restricted](https://jira.mongodb.org/browse/SERVER-86607) to single-value `aud` claims, although client applications do not need to be concerned with this restriction. \ No newline at end of file +[^5]: OIDC as a protocol allows for `aud` claims that contain multiple strings, instead of a single one. MongoDB endpoints are [restricted](https://jira.mongodb.org/browse/SERVER-86607) to single-value `aud` claims, although client applications do not need to be concerned with this restriction. + From a97e264dd56497faa0475012bd930bf2866ec826 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Thu, 14 Nov 2024 16:37:34 +0100 Subject: [PATCH 05/10] fixup: add CODEOWNERS entry --- .github/CODEOWNERS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 8628b64fae..d7b22cfeff 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -46,5 +46,8 @@ # URI Options /source/uri-options/ @mongodb/dbx-spec-owners-uri-options +# Workforce OIDC +/docs/workforce-human-oidc-auth.md @mongodb/dbx-spec-owners-workforce-oidc + # Workflows and code ownership file /.github/ @mongodb/dbx-leadership From 4b67b690e9a4d8818caa6b27a9306a338af66e4b Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Mon, 18 Nov 2024 15:42:33 +0100 Subject: [PATCH 06/10] fixup: fix link --- docs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index 5c12a4ca20..9bf01c1734 100644 --- a/docs/README.md +++ b/docs/README.md @@ -4,4 +4,4 @@ Supporting material for various MongoDB Drivers Specifications lives here. ## Authentication -* [Requirements for Client Applications implementing Workforce (Human) OIDC Auth For MongoDB](./Requirements%20for%20Client%20Applications%20implementing%20Workforce%20(Human)%20OIDC%20Auth%20For%20MongoDB.md) +* [Requirements for Client Applications implementing Workforce (Human) OIDC Auth For MongoDB](./workforce-human-oidc-auth.md) From d0096bdcbc92d0c8d2c48a444cd5abb19e467db2 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Mon, 18 Nov 2024 20:19:27 +0100 Subject: [PATCH 07/10] fixup: lint --- docs/README.md | 2 +- docs/workforce-human-oidc-auth.md | 257 ++++++++++++++++++++---------- 2 files changed, 176 insertions(+), 83 deletions(-) diff --git a/docs/README.md b/docs/README.md index 9bf01c1734..7dabff0028 100644 --- a/docs/README.md +++ b/docs/README.md @@ -4,4 +4,4 @@ Supporting material for various MongoDB Drivers Specifications lives here. ## Authentication -* [Requirements for Client Applications implementing Workforce (Human) OIDC Auth For MongoDB](./workforce-human-oidc-auth.md) +- [Requirements for Client Applications implementing Workforce (Human) OIDC Auth For MongoDB](./workforce-human-oidc-auth.md) diff --git a/docs/workforce-human-oidc-auth.md b/docs/workforce-human-oidc-auth.md index 511c51c724..d2fddb1eb1 100644 --- a/docs/workforce-human-oidc-auth.md +++ b/docs/workforce-human-oidc-auth.md @@ -4,42 +4,62 @@ ## Abstract -MongoDB offers OpenID Connect (OIDC) authentication and authorization for database users. OIDC auth in clients generally falls into one of two categories; either Workflow OIDC targeting programmatic users, which is [fully specified here](https://github.com/mongodb/specifications/blob/master/source/auth/auth.md#mongodb-oidc) and does not involve user interaction, or Workforce OIDC targeting human users, which authenticate explicitly through means such as browsers. +MongoDB offers OpenID Connect (OIDC) authentication and authorization for database users. OIDC auth in clients generally +falls into one of two categories; either Workflow OIDC targeting programmatic users, which is +[fully specified here](https://github.com/mongodb/specifications/blob/master/source/auth/auth.md#mongodb-oidc) and does +not involve user interaction, or Workforce OIDC targeting human users, which authenticate explicitly through means such +as browsers. ## Audience -This document is intended for authors and maintainers of MongoDB client applications that implement Workforce OIDC authentication, or those who wish to understand existing implementations of it. This document does *not* describe the server implementation of OIDC, nor the details of OIDC protocol interactions that are part of external standards and generally implemented through the use of a third-party library. +This document is intended for authors and maintainers of MongoDB client applications that implement Workforce OIDC +authentication, or those who wish to understand existing implementations of it. This document does *not* describe the +server implementation of OIDC, nor the details of OIDC protocol interactions that are part of external standards and +generally implemented through the use of a third-party library. ## Meta -The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt). +The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and +"OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt). ## Token acquisition flows Currently, all workforce OIDC clients in MongoDB support one or two mechanisms for acquiring OIDC tokens: -* Authorization Code Flow with PKCE (short: Auth Code, PKCE is pronounced “pixie”) -* Device Authorization Grant (short: Device Auth) +- Authorization Code Flow with PKCE (short: Auth Code, PKCE is pronounced “pixie”) +- Device Authorization Grant (short: Device Auth) -Auth Code Flow is generally the preferred mechanism. If an application decides to only support one of these flows, that should be the typical choice. If an application supports both flows, it MAY default to Auth Code Flow and fall back to Device Auth only if +Auth Code Flow is generally the preferred mechanism. If an application decides to only support one of these flows, that +should be the typical choice. If an application supports both flows, it MAY default to Auth Code Flow and fall back to +Device Auth only if -* The former is unavailable under specific circumstances, which are described in the Auth Code Flow section; and -* The user has explicitly indicated that Device Auth is enabled for this connection attempt. +- The former is unavailable under specific circumstances, which are described in the Auth Code Flow section; and +- The user has explicitly indicated that Device Auth is enabled for this connection attempt. In both of these cases, the general chain of events is as follows: -1. The user passes a connection string to the client application and indicates (possibly through said connection string) that they desire to use `MONGODB-OIDC` as their authentication mechanism. -2. The application connects to the MongoDB endpoint and asks it for information about the Identity Provider (IdP)[^1] it is supposed to authenticate with. If there was a username in the connection string, the application sends that as well. -3. The MongoDB endpoint responds with information about the IdP, in the form of an `issuer` URL identifying the IdP and other metadata about it. -4. The application looks up the public metadata document for the IdP, which includes information about user-facing URL endpoints. -5. The application composes a URL based on those endpoints and presents it to the user in some form (the details depend on the exact flow chosen). +1. The user passes a connection string to the client application and indicates (possibly through said connection string) + that they desire to use `MONGODB-OIDC` as their authentication mechanism. +2. The application connects to the MongoDB endpoint and asks it for information about the Identity Provider (IdP)[^1] it + is supposed to authenticate with. If there was a username in the connection string, the application sends that as + well. +3. The MongoDB endpoint responds with information about the IdP, in the form of an `issuer` URL identifying the IdP and + other metadata about it. +4. The application looks up the public metadata document for the IdP, which includes information about user-facing URL + endpoints. +5. The application composes a URL based on those endpoints and presents it to the user in some form (the details depend + on the exact flow chosen). 6. The user visits that URL, which can result in any number of steps to authenticate the user. 7. The application receives a token from the IdP (the details again depend on the exact flow chosen). 8. The application presents this token to the MongoDB endpoint. -Since in these steps the client application performs actions depending on information supplied by external sources, this document specifies mechanisms that help ensure that these actions are carried out securely. MongoDB clients are “public clients” in the sense of the OIDC specs (i.e. they do not possess a shared secret with the Identity Provider), and must behave accordingly. +Since in these steps the client application performs actions depending on information supplied by external sources, this +document specifies mechanisms that help ensure that these actions are carried out securely. MongoDB clients are “public +clients” in the sense of the OIDC specs (i.e. they do not possess a shared secret with the Identity Provider), and must +behave accordingly. -Since these steps require the involvement of a human being, the application should be set up to gracefully handle timeouts and provide the user with a way to abort the connection attempt. +Since these steps require the involvement of a human being, the application should be set up to gracefully handle +timeouts and provide the user with a way to abort the connection attempt. # General requirements @@ -47,72 +67,129 @@ An application implementing workforce OIDC needs to generally comply with OpenID In particular: -* Any HTTP calls made to non-local servers MUST be made using HTTPS. -* IdP metadata discovery MUST be implemented as described in [RFC8414](https://datatracker.ietf.org/doc/html/rfc8414). +- Any HTTP calls made to non-local servers MUST be made using HTTPS. +- IdP metadata discovery MUST be implemented as described in [RFC8414](https://datatracker.ietf.org/doc/html/rfc8414). -Using a well-tested and standards-compliant third-party library for core OIDC logic for the respective ecosystem is highly recommended. If this is not possible, implementers need to pay special attention to the specifications referenced in this document. +Using a well-tested and standards-compliant third-party library for core OIDC logic for the respective ecosystem is +highly recommended. If this is not possible, implementers need to pay special attention to the specifications referenced +in this document. ## Endpoint restrictions -Currently, users who connect to a host other than localhost or an Atlas hostname need to explicitly opt-in into being able to do so by setting the `ALLOWED_HOSTS` flag (specified in the drivers auth spec). In the future, MongoDB is hoping to support Demonstrating Proof of Possession (DPoP, [RFC9449](https://datatracker.ietf.org/doc/html/rfc9449)) that will allow lifting this restriction. The goal here is to prevent users from connecting to untrusted endpoints that will advertise attacker-controlled IdP metadata and and intercept tokens intended for other clusters (or even other OIDC endpoints in general). +Currently, users who connect to a host other than localhost or an Atlas hostname need to explicitly opt-in into being +able to do so by setting the `ALLOWED_HOSTS` flag (specified in the drivers auth spec). In the future, MongoDB is hoping +to support Demonstrating Proof of Possession (DPoP, [RFC9449](https://datatracker.ietf.org/doc/html/rfc9449)) that will +allow lifting this restriction. The goal here is to prevent users from connecting to untrusted endpoints that will +advertise attacker-controlled IdP metadata and and intercept tokens intended for other clusters (or even other OIDC +endpoints in general). -We would also like to generally adopt [RFC8707](https://datatracker.ietf.org/doc/html/rfc8707), but have not decided on a specific format for expressing the MongoDB endpoints as resources. +We would also like to generally adopt [RFC8707](https://datatracker.ietf.org/doc/html/rfc8707), but have not decided on +a specific format for expressing the MongoDB endpoints as resources. ## Token management -After a successful authentication, applications SHOULD periodically attempt to use the OIDC token refresh mechanism in order to exchange the access token it uses for a fresh one. The refresh interval SHOULD be determined by the token expiry time indicated by the Identity Provider. If the refresh attempt fails, the application MAY ask or suggest the user to re-authenticate from scratch, even if the currently used access token has not expired yet. +After a successful authentication, applications SHOULD periodically attempt to use the OIDC token refresh mechanism in +order to exchange the access token it uses for a fresh one. The refresh interval SHOULD be determined by the token +expiry time indicated by the Identity Provider. If the refresh attempt fails, the application MAY ask or suggest the +user to re-authenticate from scratch, even if the currently used access token has not expired yet. -Under normal circumstances, the application provides an access token received from the Identity Provider to the driver. The application SHOULD provide a toggle to users that can be used to indicate that it should use the ID token, rather than the access token, in its place.[^2] +Under normal circumstances, the application provides an access token received from the Identity Provider to the driver. +The application SHOULD provide a toggle to users that can be used to indicate that it should use the ID token, rather +than the access token, in its place.[^2] ## OIDC Scopes -The initial request to the IdP involves specifying the `scope` parameter. This is a space-separated unordered list of strings which contains: +The initial request to the IdP involves specifying the `scope` parameter. This is a space-separated unordered list of +strings which contains: -* The scopes listed in the `requestScopes` field of the IdP response from the MongoDB endpoint, and -* The `openid` and `offline_access` scopes[^3]. If the IdP metadata document contains a `scopes_supported` field, and this field does not list one of these scopes, then the respective scope SHOULD NOT be added to the `scope` parameter. +- The scopes listed in the `requestScopes` field of the IdP response from the MongoDB endpoint, and +- The `openid` and `offline_access` scopes[^3]. If the IdP metadata document contains a `scopes_supported` field, and + this field does not list one of these scopes, then the respective scope SHOULD NOT be added to the `scope` + parameter. # Authorization Code Flow -In this flow, the client application uses a local HTTP server to receive a response from the Identity Provider, as described in [RFC8252](https://datatracker.ietf.org/doc/html/rfc8252).[^4] The application follows these steps: - -1. Generate a code challenge for PKCE using cryptographically random data, as described in [RFC7636](https://datatracker.ietf.org/doc/html/rfc7636). -2. Spin up a local HTTP server. The default (incoming) redirect URL for MongoDB applications is `http://localhost:27097/redirect`, which MAY be configurable. If the application allows configuring the URL, the port MAY be specified as `0` to allow listening on an arbitrary port. The application listens on the host and port listed in the URL. The application MUST listen on all addresses that the hostname resolves to through `getaddrinfo()`, and MUST listen on the same port in all cases. If listening on any address fails, or `getaddrinfo()` did not return any addresses, it must abort this process and the application MAY fall back to Device Auth. - 1. To preserve privacy, pages served from this local HTTP server MUST NOT reference external resources directly. They MAY provide external links that require user interaction. - 2. The HTTP server SHOULD set default headers of `Content-Security-Policy: default-src 'self'` and `Referrer-Policy: no-referrer`, or similarly restrictive defaults. -3. Compose the URL for Auth Code Flow, using the code challenge generated earlier and the redirect URL from the previous step, with the port replaced with the actual port if it was specified as `0`. - 1. The application MUST add a `state` parameter containing cryptographically random data ([RFC6749](https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.1) specifies this as optional but recommended). - 2. The application MAY allow the user to indicate that it should add a `nonce` parameter containing cryptographically random data to the authentication request, as defined in the OpenID connect specification, which is then later embedded in the ID token itself. -4. The application SHOULD, instead of directly presenting the URL from the previous step to the user, register that URL as an outgoing HTTP 307 redirect from the local HTTP server. The redirect base URL SHOULD contain a piece of cryptographically random data. The advantages of this approach are that: - 1. The application can ensure that the URL that is passed to the browser in the next step does not contain special characters (other than the typical `/` and `:` present in URLs) which would need to be escaped when opening a browser through a shell command. - 2. It allows tracking whether the URL has been accessed, i.e. get a definite confirmation of whether the user successfully opened it in a browser. -5. Open a browser pointing at that URL, or instruct the user to do so. The former approach is preferred. If opening a browser fails, the application MAY fall back to Device Auth. +In this flow, the client application uses a local HTTP server to receive a response from the Identity Provider, as +described in [RFC8252](https://datatracker.ietf.org/doc/html/rfc8252).[^4] The application follows these steps: + +1. Generate a code challenge for PKCE using cryptographically random data, as described in + [RFC7636](https://datatracker.ietf.org/doc/html/rfc7636). +2. Spin up a local HTTP server. The default (incoming) redirect URL for MongoDB applications is + `http://localhost:27097/redirect`, which MAY be configurable. If the application allows configuring the URL, the + port MAY be specified as `0` to allow listening on an arbitrary port. The application listens on the host and port + listed in the URL. The application MUST listen on all addresses that the hostname resolves to through + `getaddrinfo()`, and MUST listen on the same port in all cases. If listening on any address fails, or + `getaddrinfo()` did not return any addresses, it must abort this process and the application MAY fall back to + Device Auth. + 1. To preserve privacy, pages served from this local HTTP server MUST NOT reference external resources directly. + They MAY provide external links that require user interaction. + 2. The HTTP server SHOULD set default headers of `Content-Security-Policy: default-src 'self'` and + `Referrer-Policy: no-referrer`, or similarly restrictive defaults. +3. Compose the URL for Auth Code Flow, using the code challenge generated earlier and the redirect URL from the + previous step, with the port replaced with the actual port if it was specified as `0`. + 1. The application MUST add a `state` parameter containing cryptographically random data + ([RFC6749](https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.1) specifies this as optional but + recommended). + 2. The application MAY allow the user to indicate that it should add a `nonce` parameter containing + cryptographically random data to the authentication request, as defined in the OpenID connect specification, + which is then later embedded in the ID token itself. +4. The application SHOULD, instead of directly presenting the URL from the previous step to the user, register that URL + as an outgoing HTTP 307 redirect from the local HTTP server. The redirect base URL SHOULD contain a piece of + cryptographically random data. The advantages of this approach are that: + 1. The application can ensure that the URL that is passed to the browser in the next step does not contain special + characters (other than the typical `/` and `:` present in URLs) which would need to be escaped when opening a + browser through a shell command. + 2. It allows tracking whether the URL has been accessed, i.e. get a definite confirmation of whether the user + successfully opened it in a browser. +5. Open a browser pointing at that URL, or instruct the user to do so. The former approach is preferred. If opening a + browser fails, the application MAY fall back to Device Auth. 6. Wait until one of the following events occurs: - 1. The local outgoing redirect URL is accessed (if any). - 2. Opening the browser fails. - 3. A timeout occurs or the connection attempt is aborted. -7. Wait until the incoming redirect URL is accessed in a valid way, i.e. using GET or POST with the correct `state` parameter and without an `error` parameter. If the incoming redirect URL is accessed with a mismatching `state` parameter or the `error` parameter is set, the application SHOULD display a helpful error page. If an `iss` parameter is present, it MUST be validated according to [RFC9207](https://datatracker.ietf.org/doc/html/rfc9207), i.e. compare equal to the `issuer` string in the issuer metadata document. Subsequent requests to the incoming redirect URL should be rejected. - 1. If error parameters such as `error`, `error_description` and/or `error_uri` are displayed to the user, they MUST be validated to match the `NQSCHAR` definition of [RFC6749](https://datatracker.ietf.org/doc/html/rfc6749) (and in the case of `error_uri`, a valid URI) before doing so, and they MUST be escaped as appropriate for the chosen display format. -8. The application MUST redirect from the incoming redirect URL to a different URL on the same local HTTP server as a HTTP 303 redirect, removing all query parameters and/or the request body. The target page SHOULD indicate successful authentication to the Identity Provider, and SHOULD clarify that the user is not authenticated with the MongoDB endpoint yet. It MAY be updated once the application successfully authenticates against the MongoDB endpoint to reflect that. -9. Stop listening on and close the local HTTP server. As browsers may keep lingering open connections, the application SHOULD ensure that these connections do not prevent the application from progressing to the next step (i.e. do not block closing the server). + 1. The local outgoing redirect URL is accessed (if any). + 2. Opening the browser fails. + 3. A timeout occurs or the connection attempt is aborted. +7. Wait until the incoming redirect URL is accessed in a valid way, i.e. using GET or POST with the correct `state` + parameter and without an `error` parameter. If the incoming redirect URL is accessed with a mismatching `state` + parameter or the `error` parameter is set, the application SHOULD display a helpful error page. If an `iss` + parameter is present, it MUST be validated according to [RFC9207](https://datatracker.ietf.org/doc/html/rfc9207), + i.e. compare equal to the `issuer` string in the issuer metadata document. Subsequent requests to the incoming + redirect URL should be rejected. + 1. If error parameters such as `error`, `error_description` and/or `error_uri` are displayed to the user, they MUST + be validated to match the `NQSCHAR` definition of [RFC6749](https://datatracker.ietf.org/doc/html/rfc6749) (and + in the case of `error_uri`, a valid URI) before doing so, and they MUST be escaped as appropriate for the + chosen display format. +8. The application MUST redirect from the incoming redirect URL to a different URL on the same local HTTP server as a + HTTP 303 redirect, removing all query parameters and/or the request body. The target page SHOULD indicate + successful authentication to the Identity Provider, and SHOULD clarify that the user is not authenticated with the + MongoDB endpoint yet. It MAY be updated once the application successfully authenticates against the MongoDB + endpoint to reflect that. +9. Stop listening on and close the local HTTP server. As browsers may keep lingering open connections, the application + SHOULD ensure that these connections do not prevent the application from progressing to the next step (i.e. do not + block closing the server). 10. Verify the parameters it received against the initial PKCE code challenge. 11. Perform a request to the OIDC token endpoint using the code received from the IdP on the incoming redirect URL. 12. Provide the token it received from the token endpoint to the MongoDB driver. -The developer tools team owns example templates for the local HTTP server at [https://github.com/mongodb-js/devtools-shared/tree/main/packages/oidc-http-server-pages](https://github.com/mongodb-js/devtools-shared/tree/main/packages/oidc-http-server-pages), and publishes templates that can be accessed at e.g. [https://unpkg.com/@mongodb-js/oidc-http-server-pages/dist/templates.gz](https://unpkg.com/@mongodb-js/oidc-http-server-pages/dist/templates.gz). +The developer tools team owns example templates for the local HTTP server at +[https://github.com/mongodb-js/devtools-shared/tree/main/packages/oidc-http-server-pages](https://github.com/mongodb-js/devtools-shared/tree/main/packages/oidc-http-server-pages), +and publishes templates that can be accessed at e.g. +[https://unpkg.com/@mongodb-js/oidc-http-server-pages/dist/templates.gz](https://unpkg.com/@mongodb-js/oidc-http-server-pages/dist/templates.gz). # Device Auth Grant This flow is optional, and MUST NOT be used unless either: -* The application has been unable to open a browser locally (e.g. in headless environments), or unable to listen on a local HTTP endpoint, and the user has explicitly indicated that falling back to this flow is acceptable; or -* The user has explicitly requested this flow. +- The application has been unable to open a browser locally (e.g. in headless environments), or unable to listen on a + local HTTP endpoint, and the user has explicitly indicated that falling back to this flow is acceptable; or +- The user has explicitly requested this flow. -It is significantly simpler than the Auth Code Flow, but generally considered the less secure one between the two, and more susceptible to e.g. phishing attacks. +It is significantly simpler than the Auth Code Flow, but generally considered the less secure one between the two, and +more susceptible to e.g. phishing attacks. The application follows these steps: 1. Reach out to the IdP device authorization endpoint. This should result in a URL and a “user code”. -2. Present the URL and the user code to the user, expecting the user to open that URL manually (possibly on a different device). +2. Present the URL and the user code to the user, expecting the user to open that URL manually (possibly on a different + device). 3. Repeatedly poll the token endpoint for an access token. 4. Provide the token it received from the token endpoint to the MongoDB driver. @@ -120,53 +197,69 @@ The application follows these steps: It is recommended to log the following events for diagnostic purposes: -* All outgoing HTTP calls, minus sensitive information (e.g. URLs, with search parameter values redacted) -* All inbound HTTP calls, minus sensitive information -* Starting to listen on the local HTTP server, including port and address(es), and whether that was successful or not -* Incoming redirect to the local HTTP server accessed and whether the redirect was accepted or rejected -* Closing of the local HTTP server -* Browser opening and whether it were successful or not -* Acquisition of new tokens from the Identity Provider, and in particular whether an ID token was present or not -* Token refresh attempts and whether they were successful or not +- All outgoing HTTP calls, minus sensitive information (e.g. URLs, with search parameter values redacted) +- All inbound HTTP calls, minus sensitive information +- Starting to listen on the local HTTP server, including port and address(es), and whether that was successful or not +- Incoming redirect to the local HTTP server accessed and whether the redirect was accepted or rejected +- Closing of the local HTTP server +- Browser opening and whether it were successful or not +- Acquisition of new tokens from the Identity Provider, and in particular whether an ID token was present or not +- Token refresh attempts and whether they were successful or not # Appendix: Relevant standards (non-exhaustive) -* [RFC6749](https://datatracker.ietf.org/doc/html/rfc6749): The OAuth 2.0 Authorization Framework -* [RFC6819](https://datatracker.ietf.org/doc/html/rfc6819): OAuth 2.0 Threat Model and Security Considerations -* [RFC7636](https://datatracker.ietf.org/doc/html/rfc7636): Proof Key for Code Exchange by OAuth Public Clients (PKCE) -* [RFC8252](https://datatracker.ietf.org/doc/html/rfc8252): OAuth 2.0 for Native Apps -* [RFC8414](https://datatracker.ietf.org/doc/html/rfc8414): OAuth 2.0 Authorization Server Metadata -* [RFC8628](https://datatracker.ietf.org/doc/html/rfc8628): OAuth 2.0 Device Authorization Grant -* [RFC8707](https://datatracker.ietf.org/doc/html/rfc8707): Resource Indicators for OAuth 2.0 -* [RFC9207](https://datatracker.ietf.org/doc/html/rfc9207): OAuth 2.0 Authorization Server Issuer Identification -* [RFC9449](https://datatracker.ietf.org/doc/html/rfc9449): OAuth 2.0 Demonstrating Proof of Possession (DPoP) -* [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html) -* [Draft](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics): OAuth 2.0 Security Best Current Practice -* [Risk of phishing Access Tokens from clients using OIDC Authentication](https://docs.google.com/document/d/1TdcBtRu4yNXQkI7ZdKWZlSIaWs29tIQblyS3805nK1A/edit?tab=t.0) +- [RFC6749](https://datatracker.ietf.org/doc/html/rfc6749): The OAuth 2.0 Authorization Framework +- [RFC6819](https://datatracker.ietf.org/doc/html/rfc6819): OAuth 2.0 Threat Model and Security Considerations +- [RFC7636](https://datatracker.ietf.org/doc/html/rfc7636): Proof Key for Code Exchange by OAuth Public Clients (PKCE) +- [RFC8252](https://datatracker.ietf.org/doc/html/rfc8252): OAuth 2.0 for Native Apps +- [RFC8414](https://datatracker.ietf.org/doc/html/rfc8414): OAuth 2.0 Authorization Server Metadata +- [RFC8628](https://datatracker.ietf.org/doc/html/rfc8628): OAuth 2.0 Device Authorization Grant +- [RFC8707](https://datatracker.ietf.org/doc/html/rfc8707): Resource Indicators for OAuth 2.0 +- [RFC9207](https://datatracker.ietf.org/doc/html/rfc9207): OAuth 2.0 Authorization Server Issuer Identification +- [RFC9449](https://datatracker.ietf.org/doc/html/rfc9449): OAuth 2.0 Demonstrating Proof of Possession (DPoP) +- [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html) +- [Draft](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics): OAuth 2.0 Security Best Current + Practice +- [Risk of phishing Access Tokens from clients using OIDC Authentication](https://docs.google.com/document/d/1TdcBtRu4yNXQkI7ZdKWZlSIaWs29tIQblyS3805nK1A/edit?tab=t.0) # Appendix: Multiple MongoClients -Some applications may require support for multiple concurrent MongoClients using the same OIDC tokens. In this case, a token set (access token, ID token and refresh token) may be re-used, if and only if: +Some applications may require support for multiple concurrent MongoClients using the same OIDC tokens. In this case, a +token set (access token, ID token and refresh token) may be re-used, if and only if: -* The `username` parameter is equal -* The IdP metadata provided by the MongoDB endpoint is equal -* Both token sets contain an ID token and the respective `aud` and `sub` claims[^5] of the ID tokens are equal, OR neither token set contains an ID token +- The `username` parameter is equal +- The IdP metadata provided by the MongoDB endpoint is equal +- Both token sets contain an ID token and the respective `aud` and `sub` claims[^5] of the ID tokens are equal, OR + neither token set contains an ID token -If an application supports multiple MongoClients, it MUST ensure that only one token acquisition flow is in use at the same time, and coordinate token refresh intervals accordingly. +If an application supports multiple MongoClients, it MUST ensure that only one token acquisition flow is in use at the +same time, and coordinate token refresh intervals accordingly. -The Developer Tools team maintains an implementation that integrates with multiple MongoClient instances at [https://github.com/mongodb-js/oidc-plugin](https://github.com/mongodb-js/oidc-plugin), which can be used as a reference implementation (and which can generally be used in other applications based on the Node.js driver, although as a standalone package it is not considered a supported product of MongoDB). +The Developer Tools team maintains an implementation that integrates with multiple MongoClient instances at +[https://github.com/mongodb-js/oidc-plugin](https://github.com/mongodb-js/oidc-plugin), which can be used as a reference +implementation (and which can generally be used in other applications based on the Node.js driver, although as a +standalone package it is not considered a supported product of MongoDB). ## Changelog - 2024-11-14: Initial version. -[^1]: Technically, this refers to an Authorization Server (AS). Inside MongoDB, the usage of AS and IdP has been considered more or less interchangeable. +[^1]: Technically, this refers to an Authorization Server (AS). Inside MongoDB, the usage of AS and IdP has been + considered more or less interchangeable. -[^2]: At the time of writing, there are Identity Providers which do not support JWT access tokens, but which do provide JWT ID tokens that are usable for authentication. This requires opt-in on both the server configuration side and the client side. +[^2]: At the time of writing, there are Identity Providers which do not support JWT access tokens, but which do provide + JWT ID tokens that are usable for authentication. This requires opt-in on both the server configuration side and the + client side. -[^3]: The `offline_access` scope is what provides the ability to refresh tokens without performing a full re-authentication. Some particularly security-sensitive customers may choose this approach at the expense of a greatly diminished UX, where users need to frequently re-authenticate. +[^3]: The `offline_access` scope is what provides the ability to refresh tokens without performing a full + re-authentication. Some particularly security-sensitive customers may choose this approach at the expense of a + greatly diminished UX, where users need to frequently re-authenticate. -[^4]: [RFC8252](https://datatracker.ietf.org/doc/html/rfc8252) lays out alternatives to this approach, such as registering a custom URI scheme handler or registering “Claims” on specific HTTPS URLs, but we’ve decided not to pursue these approaches in any existing applications, since some of our applications are CLI applications without an installation step where neither of these alternative approaches is feasible. - -[^5]: OIDC as a protocol allows for `aud` claims that contain multiple strings, instead of a single one. MongoDB endpoints are [restricted](https://jira.mongodb.org/browse/SERVER-86607) to single-value `aud` claims, although client applications do not need to be concerned with this restriction. +[^4]: [RFC8252](https://datatracker.ietf.org/doc/html/rfc8252) lays out alternatives to this approach, such as registering + a custom URI scheme handler or registering “Claims” on specific HTTPS URLs, but we’ve decided not to pursue these + approaches in any existing applications, since some of our applications are CLI applications without an installation + step where neither of these alternative approaches is feasible. +[^5]: OIDC as a protocol allows for `aud` claims that contain multiple strings, instead of a single one. MongoDB endpoints + are [restricted](https://jira.mongodb.org/browse/SERVER-86607) to single-value `aud` claims, although client + applications do not need to be concerned with this restriction. From 28a047db3d212ad9b0ab4e94bafee8a22122d751 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 19 Nov 2024 16:23:53 +0100 Subject: [PATCH 08/10] fixup: adjust text around nonce parameter addition --- docs/workforce-human-oidc-auth.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/workforce-human-oidc-auth.md b/docs/workforce-human-oidc-auth.md index d2fddb1eb1..56e66e201a 100644 --- a/docs/workforce-human-oidc-auth.md +++ b/docs/workforce-human-oidc-auth.md @@ -130,9 +130,11 @@ described in [RFC8252](https://datatracker.ietf.org/doc/html/rfc8252).[^4] The a 1. The application MUST add a `state` parameter containing cryptographically random data ([RFC6749](https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.1) specifies this as optional but recommended). - 2. The application MAY allow the user to indicate that it should add a `nonce` parameter containing - cryptographically random data to the authentication request, as defined in the OpenID connect specification, - which is then later embedded in the ID token itself. + 2. The application SHOULD allow the user to indicate that it should add a `nonce` parameter containing + cryptographically random data to the authentication request, as defined in the OpenID Connect specification, + which is then later embedded in the ID token itself. This option SHOULD be on-by-default. (Some Identity + Providers may effectively require a `nonce` option, but since it is an OpenID Connect feature and not an OAuth + 2.0 feature, we allow users to disable this if their Identity Provider does not support it.) 4. The application SHOULD, instead of directly presenting the URL from the previous step to the user, register that URL as an outgoing HTTP 307 redirect from the local HTTP server. The redirect base URL SHOULD contain a piece of cryptographically random data. The advantages of this approach are that: From 85592f594600afda4d7593de741fe6d9be3611eb Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Wed, 27 Nov 2024 11:00:49 +0100 Subject: [PATCH 09/10] fixup: apply suggestions from code review Co-authored-by: Nikola Irinchev --- docs/workforce-human-oidc-auth.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/workforce-human-oidc-auth.md b/docs/workforce-human-oidc-auth.md index 56e66e201a..66f65cb808 100644 --- a/docs/workforce-human-oidc-auth.md +++ b/docs/workforce-human-oidc-auth.md @@ -5,7 +5,7 @@ ## Abstract MongoDB offers OpenID Connect (OIDC) authentication and authorization for database users. OIDC auth in clients generally -falls into one of two categories; either Workflow OIDC targeting programmatic users, which is +falls into one of two categories: either Workflow OIDC targeting programmatic users, which is [fully specified here](https://github.com/mongodb/specifications/blob/master/source/auth/auth.md#mongodb-oidc) and does not involve user interaction, or Workforce OIDC targeting human users, which authenticate explicitly through means such as browsers. @@ -80,7 +80,7 @@ Currently, users who connect to a host other than localhost or an Atlas hostname able to do so by setting the `ALLOWED_HOSTS` flag (specified in the drivers auth spec). In the future, MongoDB is hoping to support Demonstrating Proof of Possession (DPoP, [RFC9449](https://datatracker.ietf.org/doc/html/rfc9449)) that will allow lifting this restriction. The goal here is to prevent users from connecting to untrusted endpoints that will -advertise attacker-controlled IdP metadata and and intercept tokens intended for other clusters (or even other OIDC +advertise attacker-controlled IdP metadata and intercept tokens intended for other clusters (or even other OIDC endpoints in general). We would also like to generally adopt [RFC8707](https://datatracker.ietf.org/doc/html/rfc8707), but have not decided on From b66f9609e7e608953241aa43a1711865f1f6c1ab Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Thu, 5 Dec 2024 14:16:57 +0100 Subject: [PATCH 10/10] fixup: cr comments --- docs/workforce-human-oidc-auth.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/workforce-human-oidc-auth.md b/docs/workforce-human-oidc-auth.md index 66f65cb808..62923af6ca 100644 --- a/docs/workforce-human-oidc-auth.md +++ b/docs/workforce-human-oidc-auth.md @@ -74,18 +74,6 @@ Using a well-tested and standards-compliant third-party library for core OIDC lo highly recommended. If this is not possible, implementers need to pay special attention to the specifications referenced in this document. -## Endpoint restrictions - -Currently, users who connect to a host other than localhost or an Atlas hostname need to explicitly opt-in into being -able to do so by setting the `ALLOWED_HOSTS` flag (specified in the drivers auth spec). In the future, MongoDB is hoping -to support Demonstrating Proof of Possession (DPoP, [RFC9449](https://datatracker.ietf.org/doc/html/rfc9449)) that will -allow lifting this restriction. The goal here is to prevent users from connecting to untrusted endpoints that will -advertise attacker-controlled IdP metadata and intercept tokens intended for other clusters (or even other OIDC -endpoints in general). - -We would also like to generally adopt [RFC8707](https://datatracker.ietf.org/doc/html/rfc8707), but have not decided on -a specific format for expressing the MongoDB endpoints as resources. - ## Token management After a successful authentication, applications SHOULD periodically attempt to use the OIDC token refresh mechanism in @@ -114,7 +102,7 @@ described in [RFC8252](https://datatracker.ietf.org/doc/html/rfc8252).[^4] The a 1. Generate a code challenge for PKCE using cryptographically random data, as described in [RFC7636](https://datatracker.ietf.org/doc/html/rfc7636). -2. Spin up a local HTTP server. The default (incoming) redirect URL for MongoDB applications is +2. Launch a local HTTP server. The default (incoming) redirect URL for MongoDB applications is `http://localhost:27097/redirect`, which MAY be configurable. If the application allows configuring the URL, the port MAY be specified as `0` to allow listening on an arbitrary port. The application listens on the host and port listed in the URL. The application MUST listen on all addresses that the hostname resolves to through @@ -224,7 +212,7 @@ It is recommended to log the following events for diagnostic purposes: Practice - [Risk of phishing Access Tokens from clients using OIDC Authentication](https://docs.google.com/document/d/1TdcBtRu4yNXQkI7ZdKWZlSIaWs29tIQblyS3805nK1A/edit?tab=t.0) -# Appendix: Multiple MongoClients +# Appendix A: Multiple MongoClients Some applications may require support for multiple concurrent MongoClients using the same OIDC tokens. In this case, a token set (access token, ID token and refresh token) may be re-used, if and only if: @@ -242,6 +230,18 @@ The Developer Tools team maintains an implementation that integrates with multip implementation (and which can generally be used in other applications based on the Node.js driver, although as a standalone package it is not considered a supported product of MongoDB). +# Appendix B: Future intentions for endpoint restrictions + +Currently, users who connect to a host other than localhost or an Atlas hostname need to specify this host in the +`ALLOWED_HOSTS` auth mechanism property. In the future, MongoDB is hoping to support Demonstrating Proof of Possession +(DPoP, [RFC9449](https://datatracker.ietf.org/doc/html/rfc9449)) which will allow lifting this restriction. The goal +here of either of these mechanisms is to prevent users from connecting to untrusted endpoints that could advertise +attacker-controlled IdP metadata and intercept tokens intended for other clusters (or even non-MongoDB OIDC +applications). + +We would also like to adopt [RFC8707](https://datatracker.ietf.org/doc/html/rfc8707), but have not decided on a specific +format for expressing MongoDB clusters as resource URLs. + ## Changelog - 2024-11-14: Initial version.