libhimmelblau 0.8.5

Samba Library for Azure Entra ID Authentication
Documentation
diff --git a/src/auth.rs b/src/auth.rs
index 583961c..d51cb7a 100644
--- a/src/auth.rs
+++ b/src/auth.rs
@@ -5679,38 +5778,51 @@ impl BrokerClientApplication {
         let text;
         (text, resp) = self.app.await_working(resp).await?;
         if resp.status().is_redirection() {
-            let document = Html::parse_document(&text);
-            let selector = Selector::parse("a[href]").map_err(|_| {
-                MsalError::InvalidParse("Failed parsing auth code response".to_string())
-            })?;
-            if let Some(element) = document.select(&selector).next() {
-                if let Some(href_encoded) = element.value().attr("href") {
-                    let href = percent_decode_str(href_encoded)
-                        .decode_utf8()
-                        .map_err(|e| {
-                            MsalError::URLFormatFailed(format!("Failed decoding url: {:?}", e))
-                        })?;
-                    if let Ok(url) = Url::parse(&href) {
-                        return url
-                            .query_pairs()
-                            .find_map(|(key, value)| {
+            // Parse HTML in its own scope so Html is dropped before any await.
+            // Html uses non-atomic reference counting and is not Send.
+            let auth_code_result: Option<String> = {
+                let document = Html::parse_document(&text);
+                let selector = Selector::parse("a[href]").map_err(|_| {
+                    MsalError::InvalidParse("Failed parsing auth code response".to_string())
+                })?;
+                if let Some(element) = document.select(&selector).next() {
+                    if let Some(href_encoded) = element.value().attr("href") {
+                        let href = percent_decode_str(href_encoded)
+                            .decode_utf8()
+                            .map_err(|e| {
+                                MsalError::URLFormatFailed(format!("Failed decoding url: {:?}", e))
+                            })?;
+                        if let Ok(url) = Url::parse(&href) {
+                            url.query_pairs().find_map(|(key, value)| {
                                 if key == "code" {
                                     Some(value.into_owned())
                                 } else {
                                     None
                                 }
                             })
-                            .ok_or(MsalError::GeneralFailure(
-                                "Authorization code not found".to_string(),
-                            ));
+                        } else {
+                            None
+                        }
+                    } else {
+                        None
                     }
+                } else {
+                    None
                 }
+            }; // Html document dropped here
+
+            if let Some(code) = auth_code_result {
+                return Ok(code);
             }
 
             // MS may have returned an AuthConfig here with an error attached.
             // Return the error from that AuthConfig if possible. If a required
-            // password change is indicated, raise an error.
-            match self.app.parse_auth_config(&text, false, false) {
+            // password change is indicated, raise an error. If ConvergedTFA is
+            // returned, MFA is required for this user.
+            // Note: parse_auth_config uses Html internally but is synchronous,
+            // so the Html is dropped before we return the AuthConfig.
+            let auth_config_result = self.app.parse_auth_config(&text, false, false);
+            match auth_config_result {
                 #[cfg(feature = "changepassword")]
                 Err(MsalError::ChangePassword) => return Err(MsalError::ChangePassword),
                 Err(MsalError::AADSTSError(e)) => return Err(MsalError::AADSTSError(e)),
@@ -5742,8 +5854,12 @@ impl BrokerClientApplication {
 
             // MS may have returned an AuthConfig here with an error attached.
             // Return the error from that AuthConfig if possible. If a required
-            // password change is indicated, raise an error.
-            match self.app.parse_auth_config(&text, false, false) {
+            // password change is indicated, raise an error. If ConvergedTFA is
+            // returned, MFA is required for this user.
+            // Note: parse_auth_config uses Html internally but is synchronous,
+            // so the Html is dropped before we return the AuthConfig.
+            let auth_config_result = self.app.parse_auth_config(&text, false, false);
+            match auth_config_result {
                 #[cfg(feature = "changepassword")]
                 Err(MsalError::ChangePassword) => return Err(MsalError::ChangePassword),
                 Err(MsalError::AADSTSError(e)) => return Err(MsalError::AADSTSError(e)),