Skip to content

Commit 3e587b9

Browse files
Document OIDC feature flags (#1443)
1 parent cf1cfd4 commit 3e587b9

File tree

3 files changed

+64
-36
lines changed

3 files changed

+64
-36
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ features = ["sync"]
5555
| `in-use-encryption` | Enable support for client-side field level encryption and queryable encryption. Note that re-exports from the `mongocrypt` crate may change in backwards-incompatible ways while that crate is below version 1.0. |
5656
| `tracing-unstable` | Enable support for emitting [`tracing`](https://docs.rs/tracing/latest/tracing/) events. This API is unstable and may be subject to breaking changes in minor releases. |
5757
| `compat-3-0-0` | Required for future compatibility if default features are disabled. |
58+
| `azure-oidc` | Enable support for Azure OIDC environment authentication. |
59+
| `gcp-oidc` | Enable support for GCP OIDC environment authentication. |
5860

5961
## Web Framework Examples
6062

src/client/auth.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
pub(crate) mod aws;
66
#[cfg(feature = "gssapi-auth")]
77
mod gssapi;
8-
/// Contains the functionality for [`OIDC`](https://openid.net/developers/how-connect-works/) authorization and authentication.
98
pub mod oidc;
109
mod plain;
1110
mod sasl;

src/client/auth/oidc.rs

Lines changed: 62 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -534,36 +534,61 @@ pub(crate) async fn reauthenticate_stream(
534534
authenticate_stream(conn, credential, server_api, None).await
535535
}
536536

537-
async fn setup_automatic_providers(credential: &Credential, callback: &mut Option<CallbackInner>) {
538-
// If there is already a function, there is no need to set up an automatic provider
539-
// this could happen in the case of a reauthentication, or if the user has already set up
540-
// a function. A situation where the user has set up a function and an automatic provider
541-
// would already have caused an InvalidArgument error in `validate_credential`.
542-
if callback.is_some() {
543-
return;
544-
}
545-
if let Some(ref p) = credential.mechanism_properties {
546-
let environment = p.get_str(ENVIRONMENT_PROP_STR).unwrap_or("");
547-
#[cfg(any(feature = "azure-oidc", feature = "gcp-oidc"))]
548-
let resource = p.get_str(TOKEN_RESOURCE_PROP_STR).unwrap_or("");
549-
let function = match environment {
550-
#[cfg(feature = "azure-oidc")]
551-
AZURE_ENVIRONMENT_VALUE_STR => {
552-
let client_id = credential.username.as_deref();
553-
Some(Callback::azure_callback(client_id, resource))
554-
}
555-
#[cfg(feature = "gcp-oidc")]
556-
GCP_ENVIRONMENT_VALUE_STR => Some(Callback::gcp_callback(resource)),
557-
K8S_ENVIRONMENT_VALUE_STR => Some(Callback::k8s_callback()),
558-
_ => None,
559-
};
560-
if let Some(function) = function {
561-
*callback = Some(CallbackInner {
562-
function,
563-
cache: Cache::new(),
564-
})
537+
fn get_automatic_provider_callback(credential: &Credential) -> Result<CallbackInner> {
538+
let Some(ref mechanism_properties) = credential.mechanism_properties else {
539+
return Err(auth_error(
540+
"no callback or mechanism properties provided for OIDC authentication",
541+
));
542+
};
543+
544+
let environment = mechanism_properties.get_str(ENVIRONMENT_PROP_STR).ok();
545+
#[cfg(any(feature = "azure-oidc", feature = "gcp-oidc"))]
546+
let token_resource = mechanism_properties
547+
.get_str(TOKEN_RESOURCE_PROP_STR)
548+
.map_err(|_| {
549+
auth_error(format!(
550+
"the {TOKEN_RESOURCE_PROP_STR} authentication mechanism property must be set"
551+
))
552+
});
553+
554+
let function = match environment {
555+
#[cfg(feature = "azure-oidc")]
556+
Some(AZURE_ENVIRONMENT_VALUE_STR) => {
557+
let client_id = credential.username.as_deref();
558+
Callback::azure_callback(client_id, token_resource?)
565559
}
566-
}
560+
#[cfg(not(feature = "azure-oidc"))]
561+
Some(AZURE_ENVIRONMENT_VALUE_STR) => {
562+
return Err(auth_error(
563+
"the `azure-oidc` feature flag must be enabled for Azure OIDC authentication",
564+
));
565+
}
566+
#[cfg(feature = "gcp-oidc")]
567+
Some(GCP_ENVIRONMENT_VALUE_STR) => Callback::gcp_callback(token_resource?),
568+
#[cfg(not(feature = "gcp-oidc"))]
569+
Some(GCP_ENVIRONMENT_VALUE_STR) => {
570+
return Err(auth_error(
571+
"the `gcp-oidc` feature flag must be enabled for GCP OIDC authentication",
572+
));
573+
}
574+
Some(K8S_ENVIRONMENT_VALUE_STR) => Callback::k8s_callback(),
575+
Some(other) => {
576+
return Err(auth_error(format!(
577+
"unsupported value for authentication mechanism property {ENVIRONMENT_PROP_STR}: \
578+
{other}"
579+
)));
580+
}
581+
None => {
582+
return Err(auth_error(
583+
"no callback or environment configured for OIDC authentication",
584+
));
585+
}
586+
};
587+
588+
Ok(CallbackInner {
589+
function,
590+
cache: Cache::new(),
591+
})
567592
}
568593

569594
pub(crate) async fn authenticate_stream(
@@ -575,16 +600,18 @@ pub(crate) async fn authenticate_stream(
575600
// We need to hold the lock for the entire function so that multiple functions
576601
// are not called during an authentication race, and so that token_gen_id on the Connection
577602
// always matches that in the Credential Cache.
578-
let mut guard = credential.oidc_callback.inner.lock().await;
603+
let mut callback_guard = credential.oidc_callback.inner.lock().await;
579604

580-
setup_automatic_providers(credential, &mut guard).await;
581605
let CallbackInner {
582606
cache,
583607
function: Function { inner, kind },
584-
} = &mut guard
585-
.as_mut()
586-
.ok_or_else(|| auth_error("no functions supplied"))?;
587-
608+
} = match callback_guard.as_mut() {
609+
Some(callback) => callback,
610+
None => {
611+
let callback = get_automatic_provider_callback(credential)?;
612+
callback_guard.insert(callback)
613+
}
614+
};
588615
cache.propagate_token_gen_id(conn).await;
589616

590617
if server_first.into().is_some() {

0 commit comments

Comments
 (0)