diff --git a/libpurple/connection.h b/libpurple/connection.h
--- a/libpurple/connection.h
+++ b/libpurple/connection.h
@@ -298,6 +298,23 @@
 const char *purple_connection_get_password(PurpleConnection *gc);
 
 /**
+ * purple_connection_set_password:
+ * @connection: The instance.
+ * @password: (nullable): The new password.
+ *
+ * Sets the password for @connection to @password.
+ *
+ * This will not change your password on the remote service. It just updates
+ * the password that the protocol should use when connecting.
+ *
+ * This is generally used by protocol plugins that support multiple
+ * authentication methods and need to prompt the user for a password.
+ *
+ * Since: 3.0.0
+ */
+void purple_connection_set_password(PurpleConnection *connection, const char *password);
+
+/**
  * purple_connection_get_active_chats:
  * @gc: The connection.
  *
# HG changeset patch
# Node ID 2d984405b70d
# Parent  413cde086275
diff --git a/libpurple/connection.c b/libpurple/connection.c
--- a/libpurple/connection.c
+++ b/libpurple/connection.c
@@ -342,6 +342,22 @@
 	return priv->password;
 }
 
+void
+purple_connection_set_password(PurpleConnection *connection,
+                               const char *password)
+{
+	PurpleConnectionPrivate *priv = NULL;
+
+	g_return_if_fail(PURPLE_IS_CONNECTION(connection));
+
+	priv = purple_connection_get_instance_private(connection);
+
+	purple_str_wipe(priv->password);
+	priv->password = g_strdup(password);
+
+	g_object_notify_by_pspec(G_OBJECT(connection), properties[PROP_PASSWORD]);
+}
+
 GSList *
 purple_connection_get_active_chats(PurpleConnection *connection) {
 	PurpleConnectionPrivate *priv = NULL;
@@ -673,8 +689,8 @@
 			priv->account = g_value_get_object(value);
 			break;
 		case PROP_PASSWORD:
-			g_free(priv->password);
-			priv->password = g_value_dup_string(value);
+			purple_connection_set_password(connection,
+			                               g_value_get_string(value));
 			break;
 		case PROP_DISPLAY_NAME:
 			purple_connection_set_display_name(connection,
@@ -867,7 +883,7 @@
 	properties[PROP_PASSWORD] = g_param_spec_string(
 		"password", "Password",
 		"The password used for connection.", NULL,
-		G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+		G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
 
 	properties[PROP_DISPLAY_NAME] = g_param_spec_string(
 		"display-name", "Display name",
diff --git a/libpurple/protocols/jabber/auth.c b/libpurple/protocols/jabber/auth.c
--- a/libpurple/protocols/jabber/auth.c
+++ b/libpurple/protocols/jabber/auth.c
@@ -108,7 +108,10 @@
 		                                               NULL, NULL, NULL);
 	}
 
-	/* Restart our connection */
+	/* Store the new password in our connection. */
+	purple_connection_set_password(gc, entry);
+
+	/* Restart our connection. */
 	jabber_auth_start_old(js);
 }
 
@@ -122,6 +125,44 @@
 	purple_account_set_enabled(purple_connection_get_account(gc), FALSE);
 }
 
+static void
+auth_old_read_pass_cb(GObject *source, GAsyncResult *result, gpointer data) {
+	JabberStream *js = data;
+	PurpleCredentialManager *manager = PURPLE_CREDENTIAL_MANAGER(source);
+	GError *error = NULL;
+	char *password = NULL;
+
+	password = purple_credential_manager_read_password_finish(manager, result,
+	                                                          &error);
+	if(password == NULL || error != NULL) {
+		PurpleAccount *account = NULL;
+		const char *message = "unknown error";
+
+		if(error != NULL) {
+			message = error->message;
+		}
+
+		purple_debug_warning("jabber", "failed to read password from the "
+		                     "credential manager : %s", message);
+
+		g_clear_error(&error);
+
+		account = purple_connection_get_account(js->gc);
+		purple_account_request_password(account, G_CALLBACK(auth_old_pass_cb),
+		                                G_CALLBACK(auth_no_pass_cb),
+		                                js->gc);
+
+		return;
+	}
+
+	/* Save the password in the connection. */
+	purple_connection_set_password(js->gc, password);
+	purple_str_wipe(password);
+
+	/* Restart the authentication process. */
+	jabber_auth_start_old(js);
+}
+
 void
 jabber_auth_start(JabberStream *js, PurpleXmlNode *packet)
 {
@@ -369,7 +410,13 @@
 	 */
 
 	if (!purple_connection_get_password(js->gc)) {
-		purple_account_request_password(account, G_CALLBACK(auth_old_pass_cb), G_CALLBACK(auth_no_pass_cb), js->gc);
+		PurpleCredentialManager *manager = NULL;
+
+		manager = purple_credential_manager_get_default();
+
+		purple_credential_manager_read_password_async(manager, account, NULL,
+		                                              auth_old_read_pass_cb,
+		                                              js);
 		return;
 	}
 	iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:auth");
diff --git a/libpurple/protocols/jabber/auth_cyrus.c b/libpurple/protocols/jabber/auth_cyrus.c
--- a/libpurple/protocols/jabber/auth_cyrus.c
+++ b/libpurple/protocols/jabber/auth_cyrus.c
@@ -182,6 +182,45 @@
 	purple_account_set_enabled(account, FALSE);
 }
 
+static void
+auth_pass_read_cb(GObject *source, GAsyncResult *result, gpointer data) {
+	JabberStream *js = data;
+	PurpleCredentialManager *manager = PURPLE_CREDENTIAL_MANAGER(source);
+	GError *error = NULL;
+	char *password = NULL;
+
+	password = purple_credential_manager_read_password_finish(manager, result,
+	                                                          &error);
+	if(password == NULL || error != NULL) {
+		PurpleAccount *account = NULL;
+		const char *message = "unknown error";
+
+		if(error != NULL) {
+			message = error->message;
+		}
+
+		purple_debug_warning("jabber", "failed to read password from the "
+		                     "credential manager : %s", message);
+
+		g_clear_error(&error);
+
+		account = purple_connection_get_account(js->gc);
+		purple_account_request_password(account, G_CALLBACK(auth_pass_cb),
+		                                G_CALLBACK(auth_no_pass_cb),
+		                                js->gc);
+
+		return;
+	}
+
+	js->sasl_password = password;
+
+	/* Rebuild our callbacks as we now have a password to offer */
+	jabber_sasl_build_callbacks(js);
+
+	/* Restart our negotiation */
+	start_cyrus_wrapper(js);
+}
+
 static gboolean remove_current_mech(JabberStream *js) {
 	char *pos;
 	if ((pos = strstr(js->sasl_mechs->str, js->current_mech))) {
@@ -254,7 +293,14 @@
 				 */
 
 				if (!js->sasl_password) {
-					purple_account_request_password(account, G_CALLBACK(auth_pass_cb), G_CALLBACK(auth_no_pass_cb), js->gc);
+					PurpleCredentialManager *manager = NULL;
+
+					manager = purple_credential_manager_get_default();
+					purple_credential_manager_read_password_async(manager,
+					                                              account,
+					                                              NULL,
+					                                              auth_pass_read_cb,
+					                                              js);
 					return JABBER_SASL_STATE_CONTINUE;
 
 				/* If we've got a password, but aren't sending
