diff --git a/configure.ac b/configure.ac
index b98443d..026b0c1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -95,6 +95,7 @@ PKG_CHECK_MODULES(CALENDAR,
                   gtk+-3.0 >= $GTK_MIN_VERSION
                   libecal-1.2 >= $ECAL_REQUIRED
                   libedataserver-1.2 >= $EDATASERVER_REQUIRED
+                  libedataserverui-1.2 >= $EDATASERVERUI_REQUIRED
                   libical >= $LIBICAL_REQUIRED)
 
 APPSTREAM_XML
diff --git a/src/gcal-manager.c b/src/gcal-manager.c
index cae59b2..fc8dde6 100644
--- a/src/gcal-manager.c
+++ b/src/gcal-manager.c
@@ -17,6 +17,8 @@
  * with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <libedataserverui/libedataserverui.h>
+
 #include "gcal-manager.h"
 #include "gcal-utils.h"
 
@@ -45,6 +47,7 @@ typedef struct
   GHashTable      *clients;
 
   ESourceRegistry *source_registry;
+  ECredentialsPrompter *credentials_prompter;
 
   ECalDataModel   *e_data_model;
   ECalDataModel   *search_data_model;
@@ -500,6 +503,83 @@ remove_source (GcalManager  *manager,
 }
 
 static void
+gcal_show_source_error (const gchar *where,
+			const gchar *what,
+			ESource *source,
+			const GError *error)
+{
+  if (!error || g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+    return;
+
+  /* TODO Show the error in UI, somehow */
+  g_warning ("%s: %s '%s': %s", where, what, e_source_get_display_name (source), error->message);
+}
+
+static void
+gcal_source_invoke_authenticate_cb (GObject *source_object,
+				    GAsyncResult *result,
+				    gpointer user_data)
+{
+  ESource *source = E_SOURCE (source_object);
+  GError *error = NULL;
+
+  if (!e_source_invoke_authenticate_finish (source, result, &error) &&
+      !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+    gcal_show_source_error (G_STRFUNC, "Failed to invoke authenticate", source, error);
+  }
+
+  g_clear_error (&error);
+}
+
+static void
+gcal_source_trust_prompt_done_cb (GObject *source_object,
+				  GAsyncResult *result,
+				  gpointer user_data)
+{
+  ETrustPromptResponse response = E_TRUST_PROMPT_RESPONSE_UNKNOWN;
+  ESource *source = E_SOURCE (source_object);
+  GError *error = NULL;
+
+  if (!e_trust_prompt_run_for_source_finish (source, result, &response, &error)) {
+    gcal_show_source_error (G_STRFUNC, "Failed to prompt for trust for", source, error);
+  } else if (response == E_TRUST_PROMPT_RESPONSE_ACCEPT || response == E_TRUST_PROMPT_RESPONSE_ACCEPT_TEMPORARILY) {
+    /* Use NULL credentials to reuse those from the last time. */
+    e_source_invoke_authenticate (source, NULL, NULL /* cancellable */, gcal_source_invoke_authenticate_cb, NULL);
+  }
+
+  g_clear_error (&error);
+}
+
+static void
+gcal_source_credentials_required_cb (ESourceRegistry *registry,
+				     ESource *source,
+				     ESourceCredentialsReason reason,
+				     const gchar *certificate_pem,
+				     GTlsCertificateFlags certificate_errors,
+				     const GError *op_error,
+				     GcalManager *manager)
+{
+  GcalManagerPrivate *priv;
+  ECredentialsPrompter *credentials_prompter;
+
+  g_return_if_fail (GCAL_IS_MANAGER (manager));
+
+  priv = gcal_manager_get_instance_private (manager);
+  credentials_prompter = priv->credentials_prompter;
+
+  if (e_credentials_prompter_get_auto_prompt_disabled_for (credentials_prompter, source))
+    return;
+
+  if (reason == E_SOURCE_CREDENTIALS_REASON_SSL_FAILED) {
+    e_trust_prompt_run_for_source (e_credentials_prompter_get_dialog_parent (credentials_prompter),
+	source, certificate_pem, certificate_errors, op_error ? op_error->message : NULL,
+	TRUE /* allow_source_save */, NULL /* cancellable */, gcal_source_trust_prompt_done_cb, NULL);
+  } else if (reason == E_SOURCE_CREDENTIALS_REASON_ERROR && op_error) {
+    gcal_show_source_error (G_STRFUNC, "Failed to authenticate", source, op_error);
+  }
+}
+
+static void
 gcal_manager_class_init (GcalManagerClass *klass)
 {
   G_OBJECT_CLASS (klass)->constructed = gcal_manager_constructed;
@@ -543,6 +623,7 @@ gcal_manager_constructed (GObject *object)
 {
   GcalManagerPrivate *priv;
 
+  ESourceCredentialsProvider *credentials_provider;
   GList *sources, *l;
   GError *error = NULL;
 
@@ -581,6 +662,45 @@ gcal_manager_constructed (GObject *object)
   e_cal_data_model_set_timezone (priv->e_data_model, priv->system_timezone);
   e_cal_data_model_set_expand_recurrences (priv->search_data_model, TRUE);
   e_cal_data_model_set_timezone (priv->search_data_model, priv->system_timezone);
+
+  priv->credentials_prompter = e_credentials_prompter_new (priv->source_registry);
+
+  /* First disable credentials prompt for all but calendar sources... */
+  sources = e_source_registry_list_sources (priv->source_registry, NULL);
+
+  for (l = sources; l != NULL; l = g_list_next (l)) {
+    ESource *source = E_SOURCE (l->data);
+
+    /* Mark for skip also currently disabled sources */
+    if (!e_source_has_extension (source, E_SOURCE_EXTENSION_CALENDAR))
+      e_credentials_prompter_set_auto_prompt_disabled_for (priv->credentials_prompter, source, TRUE);
+  }
+
+  g_list_free_full (sources, g_object_unref);
+
+  credentials_provider = e_credentials_prompter_get_provider (priv->credentials_prompter);
+
+  /* ...then enable credentials prompt for credential source of the calendar sources,
+     which can be a collection source.  */
+  sources = e_source_registry_list_sources (priv->source_registry, E_SOURCE_EXTENSION_CALENDAR);
+
+  for (l = sources; l != NULL; l = g_list_next (l)) {
+    ESource *source = E_SOURCE (l->data), *cred_source;
+
+    cred_source = e_source_credentials_provider_ref_credentials_source (credentials_provider, source);
+    if (cred_source && !e_source_equal (source, cred_source))
+      e_credentials_prompter_set_auto_prompt_disabled_for (priv->credentials_prompter, cred_source, FALSE);
+    g_clear_object (&cred_source);
+  }
+
+  g_list_free_full (sources, g_object_unref);
+
+  /* The eds_credentials_prompter responses to REQUIRED and REJECTED reasons,
+     the SSL_FAILED should be handled elsewhere. */
+  g_signal_connect (priv->source_registry, "credentials-required",
+     G_CALLBACK (gcal_source_credentials_required_cb), object);
+
+  e_credentials_prompter_process_awaiting_credentials (priv->credentials_prompter);
 }
 
 static void
@@ -600,6 +720,11 @@ gcal_manager_finalize (GObject *object)
     g_object_unref (priv->search_data_model);
 
   g_hash_table_destroy (priv->clients);
+
+  if (priv->source_registry)
+    g_signal_handlers_disconnect_by_func (priv->source_registry, gcal_source_credentials_required_cb, object);
+
+  g_clear_object (&priv->credentials_prompter);
 }
 
 static void
