diff --git a/libebackend/e-authentication-mediator.c b/libebackend/e-authentication-mediator.c
index 4a7e36f..af80a54 100644
--- a/libebackend/e-authentication-mediator.c
+++ b/libebackend/e-authentication-mediator.c
@@ -1264,3 +1264,28 @@ e_authentication_mediator_dismiss (EAuthenticationMediator *mediator)
 	e_dbus_authenticator_emit_dismissed (mediator->priv->interface);
 }
 
+/**
+ * e_authentication_mediator_server_error:
+ * @mediator: an #EAuthenticationMediator
+ *
+ * Signals to the authentication client that the authentication session has
+ * terminated with a server-side error.
+ *
+ * Since: 3.12
+ **/
+void
+e_authentication_mediator_server_error (EAuthenticationMediator *mediator,
+					const GError *error)
+{
+	gchar *name;
+
+	g_return_if_fail (E_IS_AUTHENTICATION_MEDIATOR (mediator));
+	g_return_if_fail (error != NULL);
+
+	name = g_dbus_error_encode_gerror (error);
+	g_return_if_fail (name != NULL);
+
+	e_dbus_authenticator_emit_server_error (mediator->priv->interface, name, error->message);
+
+	g_free (name);
+}
diff --git a/libebackend/e-authentication-mediator.h b/libebackend/e-authentication-mediator.h
index f4c5e9c..f0fe8e3 100644
--- a/libebackend/e-authentication-mediator.h
+++ b/libebackend/e-authentication-mediator.h
@@ -97,6 +97,9 @@ gboolean	e_authentication_mediator_wait_for_client_finish
 					 GError **error);
 void		e_authentication_mediator_dismiss
 					(EAuthenticationMediator *mediator);
+void		e_authentication_mediator_server_error
+					(EAuthenticationMediator *mediator,
+					 const GError *error);
 
 G_END_DECLS
 
diff --git a/libebackend/e-source-registry-server.c b/libebackend/e-source-registry-server.c
index 6d39142..2e28fd0 100644
--- a/libebackend/e-source-registry-server.c
+++ b/libebackend/e-source-registry-server.c
@@ -492,8 +492,19 @@ source_registry_server_auth_session_cb (GObject *source_object,
 		session, result, &error);
 
 	if (error != NULL) {
+		ESourceAuthenticator *authenticator;
+
 		g_warn_if_fail (auth_result == E_AUTHENTICATION_SESSION_ERROR);
 		g_simple_async_result_take_error (request->simple, error);
+
+		/* If the authenticator is an EAuthenticationMediator,
+		 * have it emit a "server-error" signal to the client. */
+		authenticator =
+			e_authentication_session_get_authenticator (session);
+		if (E_IS_AUTHENTICATION_MEDIATOR (authenticator))
+			e_authentication_mediator_server_error (
+				E_AUTHENTICATION_MEDIATOR (authenticator),
+				error);
 	}
 
 	/* Authentication dismissals require additional handling. */
diff --git a/libedataserver/e-source-registry.c b/libedataserver/e-source-registry.c
index 6589eb7..5ba6005 100644
--- a/libedataserver/e-source-registry.c
+++ b/libedataserver/e-source-registry.c
@@ -1884,6 +1884,26 @@ source_registry_authenticate_dismissed_cb (EDBusAuthenticator *dbus_auth,
 }
 
 /* Helper for e_source_registry_authenticate_sync() */
+static void
+source_registry_authenticate_server_error_cb (EDBusAuthenticator *dbus_auth,
+					      const gchar *name,
+					      const gchar *message,
+					      AuthContext *auth_context)
+{
+	/* Be careful not to overwrite an existing error */
+	if (auth_context->auth_result != E_SOURCE_AUTHENTICATION_ERROR) {
+		GError *error;
+
+		error = g_dbus_error_new_for_dbus_error (name, message);
+		g_propagate_error (auth_context->error, error);
+
+		auth_context->auth_result = E_SOURCE_AUTHENTICATION_ERROR;
+	}
+
+	g_main_loop_quit (auth_context->main_loop);
+}
+
+/* Helper for e_source_registry_authenticate_sync() */
 static gboolean
 source_registry_call_authenticate_for_source (ESourceRegistry *registry,
                                               ESourceAuthenticator *auth,
@@ -2071,6 +2091,11 @@ e_source_registry_authenticate_sync (ESourceRegistry *registry,
 		G_CALLBACK (source_registry_authenticate_dismissed_cb),
 		auth_context);
 
+	g_signal_connect (
+		dbus_auth, "server-error",
+		G_CALLBACK (source_registry_authenticate_server_error_cb),
+		auth_context);
+
 	encryption_key = gcr_secret_exchange_begin (
 		auth_context->secret_exchange);
 
diff --git a/modules/gnome-online-accounts/e-goa-password-based.c b/modules/gnome-online-accounts/e-goa-password-based.c
index 759d258..827a615 100644
--- a/modules/gnome-online-accounts/e-goa-password-based.c
+++ b/modules/gnome-online-accounts/e-goa-password-based.c
@@ -116,6 +116,8 @@ e_goa_password_based_execute_sync (EAuthenticationSession *session,
 	goa_client = goa_client_new_sync (cancellable, error);
 	if (goa_client == NULL) {
 		session_result = E_AUTHENTICATION_SESSION_ERROR;
+		if (error && *error)
+			g_dbus_error_strip_remote_error (*error);
 		goto exit;
 	}
 
@@ -158,6 +160,8 @@ e_goa_password_based_execute_sync (EAuthenticationSession *session,
 		goa_account, NULL, cancellable, error);
 	if (!success) {
 		session_result = E_AUTHENTICATION_SESSION_ERROR;
+		if (error && *error)
+			g_dbus_error_strip_remote_error (*error);
 		goto exit;
 	}
 
@@ -185,6 +189,8 @@ e_goa_password_based_execute_sync (EAuthenticationSession *session,
 
 	if (password == NULL) {
 		session_result = E_AUTHENTICATION_SESSION_ERROR;
+		if (error && *error)
+			g_dbus_error_strip_remote_error (*error);
 		goto exit;
 	}
 
diff --git a/private/org.gnome.evolution.dataserver.Authenticator.xml b/private/org.gnome.evolution.dataserver.Authenticator.xml
index 4a17fb4..22d9a34 100644
--- a/private/org.gnome.evolution.dataserver.Authenticator.xml
+++ b/private/org.gnome.evolution.dataserver.Authenticator.xml
@@ -91,5 +91,20 @@
   -->
   <signal name="Dismissed"/>
 
+  <!--
+      ServerError:
+      @name: a #GError name encoded with g_dbus_error_encode_gerror().
+      @message: a #GError::message
+
+      Emitted when there was a server-side error. A g_dbus_error_new_for_dbus_error()
+      can be used to reconstruct original #GError from @name and @message.
+
+      This signal ends the authentication session.
+  -->
+  <signal name="ServerError">
+    <arg name="name" type="s"/>
+    <arg name="message" type="s"/>
+  </signal>
+
 </interface>
 
