diff --git a/enterprise/backend/test/metabase_enterprise/sso/integrations/saml_test.clj b/enterprise/backend/test/metabase_enterprise/sso/integrations/saml_test.clj
index 9c4b289eb6cd44d49df6870cae172e708c2c3fd6..37f61147dab9f86ee8826faa6ccb9756575e384d 100644
--- a/enterprise/backend/test/metabase_enterprise/sso/integrations/saml_test.clj
+++ b/enterprise/backend/test/metabase_enterprise/sso/integrations/saml_test.clj
@@ -5,7 +5,6 @@
             [metabase-enterprise.sso.integrations.sso-settings :as sso-settings]
             [metabase.config :as config]
             [metabase.http-client :as client]
-            [metabase.integrations.ldap :as ldap]
             [metabase.models.permissions-group :refer [PermissionsGroup]]
             [metabase.models.permissions-group-membership :refer [PermissionsGroupMembership]]
             [metabase.models.user :refer [User]]
@@ -27,7 +26,7 @@
 (use-fixtures :once (fixtures/initialize :test-users))
 
 (defn- disable-other-sso-types [thunk]
-  (mt/with-temporary-setting-values [ldap/ldap-enabled false
+  (mt/with-temporary-setting-values [ldap-enabled false
                                      jwt-enabled  false]
     (thunk)))
 
diff --git a/frontend/test/metabase/scenarios/admin/settings/sso/ldap.cy.spec.js b/frontend/test/metabase/scenarios/admin/settings/sso/ldap.cy.spec.js
index b72abc3d682b8af728fd831d86212834aadc8e05..e98253a5a3ca7356d9a08c557c16cc8737b7fa34 100644
--- a/frontend/test/metabase/scenarios/admin/settings/sso/ldap.cy.spec.js
+++ b/frontend/test/metabase/scenarios/admin/settings/sso/ldap.cy.spec.js
@@ -47,9 +47,8 @@ describe("scenarios > admin > settings > SSO > LDAP", () => {
       .type("Smith");
     cy.button("Save changes").click();
     cy.wait("@ldapUpdate").then(interception => {
-      expect(interception.response.statusCode).to.eq(200);
+      expect(interception.response.statusCode).to.eq(500);
     });
-    cy.button("Changes saved!");
   });
 
   it("should not reset previously populated fields when validation fails for just one of them (metabase#16226)", () => {
diff --git a/src/metabase/api/ldap.clj b/src/metabase/api/ldap.clj
index 7264c09562fa8b5dc5e61727cec608ed0b136d59..7964c3d15dc9a9a059b9a3a4fbc257724a682fa3 100644
--- a/src/metabase/api/ldap.clj
+++ b/src/metabase/api/ldap.clj
@@ -6,23 +6,10 @@
             [metabase.api.common :as api]
             [metabase.api.common.validation :as validation]
             [metabase.integrations.ldap :as ldap]
-            [metabase.models.setting :as setting]
-            [metabase.util.schema :as su]))
-
-(def ^:private mb-settings->ldap-details
-  {:ldap-enabled             :enabled
-   :ldap-host                :host
-   :ldap-port                :port
-   :ldap-bind-dn             :bind-dn
-   :ldap-password            :password
-   :ldap-security            :security
-   :ldap-user-base           :user-base
-   :ldap-user-filter         :user-filter
-   :ldap-attribute-email     :attribute-email
-   :ldap-attribute-firstname :attribute-firstname
-   :ldap-attribute-lastname  :attribute-lastname
-   :ldap-group-sync          :group-sync
-   :ldap-group-base          :group-base})
+            [metabase.models.setting :as setting :refer [defsetting]]
+            [metabase.util.i18n :refer [deferred-tru tru]]
+            [metabase.util.schema :as su]
+            [toucan.db :as db]))
 
 (defn- humanize-error-messages
   "Convert raw error message responses from our LDAP tests into our normal api error response structure."
@@ -86,6 +73,21 @@
         #"(?s).*"
         {:message message}))))
 
+(defsetting ldap-enabled
+  (deferred-tru "Is LDAP currently enabled?")
+  :type       :boolean
+  :visibility :public
+  :setter     (fn [new-value]
+                (let [new-value (boolean new-value)]
+                  (when new-value
+                    ;; Test the LDAP settings before enabling
+                    (let [result (ldap/test-current-ldap-details)]
+                      (when-not (= :SUCCESS (:status result))
+                        (throw (ex-info (tru "Unable to connect to LDAP server with current settings")
+                                        (humanize-error-messages result))))))
+                  (setting/set-value-of-type! :boolean :ldap-enabled new-value)))
+  :default    false)
+
 (defn- update-password-if-needed
   "Do not update password if `new-password` is an obfuscated value of the current password."
   [new-password]
@@ -100,22 +102,18 @@
   {settings su/Map}
   (validation/check-has-application-permission :setting)
   (let [ldap-settings (-> settings
-                          (select-keys (keys mb-settings->ldap-details))
+                          (select-keys (keys ldap/mb-settings->ldap-details))
                           (assoc :ldap-port (when-let [^String ldap-port (not-empty (str (:ldap-port settings)))]
                                               (Long/parseLong ldap-port)))
                           (update :ldap-password update-password-if-needed))
-        ldap-details  (set/rename-keys ldap-settings mb-settings->ldap-details)
-        results       (if-not (:ldap-enabled settings)
-                        ;; when disabled just respond with a success message
-                        {:status :SUCCESS}
-                        ;; otherwise validate settings
-                        (ldap/test-ldap-connection ldap-details))]
+        ldap-details  (set/rename-keys ldap-settings ldap/mb-settings->ldap-details)
+        results       (ldap/test-ldap-connection ldap-details)]
     (if (= :SUCCESS (:status results))
-      ;; test succeeded, save our settings
-      (setting/set-many! ldap-settings)
+      (db/transaction
+       (setting/set-many! ldap-settings)
+       (setting/set-value-of-type! :boolean :ldap-enabled (boolean (:ldap-enabled settings))))
       ;; test failed, return result message
       {:status 500
        :body   (humanize-error-messages results)})))
 
-
 (api/define-routes)
diff --git a/src/metabase/api/session.clj b/src/metabase/api/session.clj
index 7b44980e48a343fc682180cb4b08f2c3f4afe853..37847f30b8f4f5e9e04f9efd4dcc3c4ba6957295 100644
--- a/src/metabase/api/session.clj
+++ b/src/metabase/api/session.clj
@@ -5,6 +5,7 @@
             [java-time :as t]
             [metabase.analytics.snowplow :as snowplow]
             [metabase.api.common :as api]
+            [metabase.api.ldap :as api.ldap]
             [metabase.config :as config]
             [metabase.email.messages :as messages]
             [metabase.events :as events]
@@ -92,7 +93,7 @@
   "If LDAP is enabled and a matching user exists return a new Session for them, or `nil` if they couldn't be
   authenticated."
   [username password device-info :- request.u/DeviceInfo]
-  (when (ldap/ldap-configured?)
+  (when (api.ldap/ldap-enabled)
     (try
       (when-let [user-info (ldap/find-user username)]
         (when-not (ldap/verify-password user-info password)
diff --git a/src/metabase/api/user.clj b/src/metabase/api/user.clj
index 9c7733a9ef407ec68ba9a02e455ad933a52edb59..56847536ebf16ca7ec8b640a58f9bfe0b9e87372 100644
--- a/src/metabase/api/user.clj
+++ b/src/metabase/api/user.clj
@@ -7,9 +7,9 @@
             [metabase.analytics.snowplow :as snowplow]
             [metabase.api.common :as api]
             [metabase.api.common.validation :as validation]
+            [metabase.api.ldap :as api.ldap]
             [metabase.email.messages :as messages]
             [metabase.integrations.google :as google]
-            [metabase.integrations.ldap :as ldap]
             [metabase.models.collection :as collection :refer [Collection]]
             [metabase.models.login-history :refer [LoginHistory]]
             [metabase.models.permissions-group :as perms-group]
@@ -352,7 +352,7 @@
                                  ;; if google-auth-client-id is set it means Google Auth is enabled
                                  (google/google-auth-client-id)))
     :ldap_auth     (boolean (and (:ldap_auth existing-user)
-                                 (ldap/ldap-configured?))))
+                                 (api.ldap/ldap-enabled))))
   ;; now return the existing user whether they were originally active or not
   (fetch-user :id (u/the-id existing-user)))
 
diff --git a/src/metabase/integrations/ldap.clj b/src/metabase/integrations/ldap.clj
index 98be17f8b4ec728b71e88784f52ae2a20fd01c0d..b7f138e4d71b42cbed624bc183a739aace57cbe8 100644
--- a/src/metabase/integrations/ldap.clj
+++ b/src/metabase/integrations/ldap.clj
@@ -17,11 +17,6 @@
 ;; Otherwise, this would only happen the first time `find-user` or `fetch-or-create-user!` is called.
 (u/ignore-exceptions (classloader/require ['metabase-enterprise.enhancements.integrations.ldap]))
 
-(defsetting ldap-enabled
-  (deferred-tru "Enable LDAP authentication.")
-  :type    :boolean
-  :default false)
-
 (defsetting ldap-host
   (deferred-tru "Server hostname."))
 
@@ -96,14 +91,28 @@
                    (setting/set-value-of-type! :json :ldap-group-mappings new-value)))))
 
 (defsetting ldap-configured?
-  "Check if LDAP is enabled and that the mandatory settings are configured."
+  (deferred-tru "Have the mandatory LDAP settings (host and user search base) been validated and saved?")
   :type       :boolean
   :visibility :public
   :setter     :none
-  :getter     (fn [] (boolean (and (ldap-enabled)
-                                   (ldap-host)
+  :getter     (fn [] (boolean (and (ldap-host)
                                    (ldap-user-base)))))
 
+(def mb-settings->ldap-details
+  "Mappings from Metabase setting names to keys to use for LDAP connections"
+  {:ldap-host                :host
+   :ldap-port                :port
+   :ldap-bind-dn             :bind-dn
+   :ldap-password            :password
+   :ldap-security            :security
+   :ldap-user-base           :user-base
+   :ldap-user-filter         :user-filter
+   :ldap-attribute-email     :attribute-email
+   :ldap-attribute-firstname :attribute-firstname
+   :ldap-attribute-lastname  :attribute-lastname
+   :ldap-group-sync          :group-sync
+   :ldap-group-base          :group-base})
+
 (defn- details->ldap-options [{:keys [host port bind-dn password security]}]
   (let [security (keyword security)
         port     (if (string? port)
@@ -180,6 +189,13 @@
     (catch Exception e
       {:status :ERROR, :message (.getMessage e)})))
 
+(defn test-current-ldap-details
+  "Tests the connection to an LDAP server using the currently set settings."
+  []
+  (let [settings (into {} (for [[k v] mb-settings->ldap-details]
+                             [v (setting/get k)]))]
+    (test-ldap-connection settings)))
+
 (defn verify-password
   "Verifies if the supplied password is valid for the `user-info` (from `find-user`) or DN."
   ([user-info password]
diff --git a/src/metabase/models/user.clj b/src/metabase/models/user.clj
index 0e03c59e35b1115d710e8d132e80aedbdcfb820b..a14aa6669cc5ffa5d61f0d3376685026a5e8af13 100644
--- a/src/metabase/models/user.clj
+++ b/src/metabase/models/user.clj
@@ -244,7 +244,7 @@
 
 (defn- send-welcome-email! [new-user invitor sent-from-setup?]
   (let [reset-token               (set-password-reset-token! (u/the-id new-user))
-        should-link-to-login-page (and (public-settings/sso-configured?)
+        should-link-to-login-page (and (public-settings/sso-enabled?)
                                        (not (public-settings/enable-password-login)))
         join-url                  (if should-link-to-login-page
                                     (str (public-settings/site-url) "/auth/login")
diff --git a/src/metabase/public_settings.clj b/src/metabase/public_settings.clj
index b2cec212dfa90b548821cbae1fdb3214230c41b6..e6a2f187387dd4d7d96deb1da75c82fa723414eb 100644
--- a/src/metabase/public_settings.clj
+++ b/src/metabase/public_settings.clj
@@ -22,9 +22,9 @@
 (defn- google-auth-configured? []
   (boolean (setting/get :google-auth-client-id)))
 
-(defn- ldap-configured? []
-  (classloader/require 'metabase.integrations.ldap)
-  ((resolve 'metabase.integrations.ldap/ldap-configured?)))
+(defn- ldap-enabled? []
+  (classloader/require 'metabase.api.ldap)
+  ((resolve 'metabase.api.ldap/ldap-enabled)))
 
 (defn- ee-sso-configured? []
   (u/ignore-exceptions
@@ -32,11 +32,11 @@
   (when-let [varr (resolve 'metabase-enterprise.sso.integrations.sso-settings/other-sso-configured?)]
     (varr)))
 
-(defn sso-configured?
-  "Any SSO provider is configured"
+(defn sso-enabled?
+  "Any SSO provider is configured and enabled"
   []
   (or (google-auth-configured?)
-      (ldap-configured?)
+      (ldap-enabled?)
       (ee-sso-configured?)))
 
 (defsetting check-for-updates
@@ -364,7 +364,7 @@
                 ;; otherwise this always returns true.
                 (let [v (setting/get-value-of-type :boolean :enable-password-login)]
                   (if (and (some? v)
-                           (sso-configured?))
+                           (sso-enabled?))
                     v
                     true))))
 
diff --git a/test/metabase/api/ldap_test.clj b/test/metabase/api/ldap_test.clj
index cb8501104c17ea9f4b29eb95d16bbf94675ad7b4..da424cac0da04732aabe115c2d0a52485d00ec1d 100644
--- a/test/metabase/api/ldap_test.clj
+++ b/test/metabase/api/ldap_test.clj
@@ -8,10 +8,11 @@
             [metabase.test.integrations.ldap :as ldap.test]))
 
 (defn ldap-test-details
-  []
-  (-> (ldap.test/get-ldap-details)
-      (set/rename-keys (set/map-invert @#'api.ldap/mb-settings->ldap-details))
-      (assoc :ldap-enabled true)))
+  ([] (ldap-test-details true))
+  ([enabled?]
+   (-> (ldap.test/get-ldap-details)
+       (set/rename-keys (set/map-invert @#'ldap/mb-settings->ldap-details))
+       (assoc :ldap-enabled enabled?))))
 
 (deftest ldap-settings-test
   (testing "PUT /api/ldap/settings"
@@ -23,19 +24,24 @@
         (mt/user-http-request :crowberto :put 500 "ldap/settings"
                               (assoc (ldap-test-details) :ldap-password "wrong-password")))
 
-      (testing "Invalid LDAP settings can be saved if LDAP is disabled"
-        (mt/user-http-request :crowberto :put 200 "ldap/settings"
-                              (assoc (ldap-test-details) :ldap-password "wrong-password" :ldap-enabled false)))
-
       (testing "Valid LDAP settings can still be saved if port is a integer (#18936)"
         (mt/user-http-request :crowberto :put 200 "ldap/settings"
                               (assoc (ldap-test-details)
                                      :ldap-port (Integer. (ldap.test/get-ldap-port)))))
 
-      (testing "LDAP port is saved as default value if passed as an empty string (#18936)"
-        (mt/user-http-request :crowberto :put 200 "ldap/settings"
-                              (assoc (ldap-test-details) :ldap-port "" :ldap-enabled false))
-        (is (= 389 (ldap/ldap-port))))
+      (testing "Passing ldap-enabled=false will disable LDAP"
+        (mt/user-http-request :crowberto :put 200 "ldap/settings" (ldap-test-details false))
+        (is (not (api.ldap/ldap-enabled))))
+
+      (testing "Passing ldap-enabled=false still validates the LDAP settings"
+        (mt/user-http-request :crowberto :put 500 "ldap/settings"
+                              (assoc (ldap-test-details false) :ldap-password "wrong-password")))
+
+      (with-redefs [ldap/test-ldap-connection (constantly {:status :SUCCESS})]
+        (testing "LDAP port is saved as default value if passed as an empty string (#18936)"
+          (mt/user-http-request :crowberto :put 200 "ldap/settings"
+                                (assoc (ldap-test-details) :ldap-port ""))
+          (is (= 389 (ldap/ldap-port)))))
 
       (testing "Could update with obfuscated password"
         (mt/user-http-request :crowberto :put 200 "ldap/settings"
@@ -45,3 +51,18 @@
         (is (= "You don't have permissions to do that."
                (mt/user-http-request :rasta :put 403 "ldap/settings"
                                      (assoc (ldap-test-details) :ldap-port "" :ldap-enabled false))))))))
+
+(deftest ldap-enabled-test
+  (ldap.test/with-ldap-server
+    (testing "`ldap-enabled` setting validates currently saved LDAP settings"
+      (mt/with-temporary-setting-values [ldap-enabled false]
+        (with-redefs [ldap/test-current-ldap-details (constantly {:status :ERROR :message "test error"})]
+          (is (thrown-with-msg? clojure.lang.ExceptionInfo
+                                #"Unable to connect to LDAP server"
+                                (api.ldap/ldap-enabled! true))))
+        (with-redefs [ldap/test-current-ldap-details (constantly {:status :SUCCESS})]
+          (api.ldap/ldap-enabled! true)
+          (is (api.ldap/ldap-enabled))
+
+          (api.ldap/ldap-enabled! false)
+          (is (not (api.ldap/ldap-enabled))))))))
diff --git a/test/metabase/test/integrations/ldap.clj b/test/metabase/test/integrations/ldap.clj
index 0c3f863895f7578765a0303f388c5db50ea115d3..bb56815c84027425d888b94cdab240419f53e498 100644
--- a/test/metabase/test/integrations/ldap.clj
+++ b/test/metabase/test/integrations/ldap.clj
@@ -54,15 +54,15 @@
   [f options]
   (binding [*ldap-server* (start-ldap-server! options)]
     (try
-      (tu/with-temporary-setting-values [ldap-enabled    true
-                                         ldap-host       "localhost"
+      (tu/with-temporary-setting-values [ldap-host       "localhost"
                                          ldap-port       (get-ldap-port)
                                          ldap-bind-dn    "cn=Directory Manager"
                                          ldap-password   "password"
                                          ldap-user-base  "dc=metabase,dc=com"
                                          ldap-group-sync true
                                          ldap-group-base "dc=metabase,dc=com"]
-        (f))
+         (tu/with-temporary-raw-setting-values [ldap-enabled "true"]
+          (f)))
       (finally (.shutDown *ldap-server* true)))))
 
 (defmacro with-ldap-server