[gnome-online-accounts/wip/kerberos: 5/5] stuff that needs to be squashed



commit 2d6edc4140c4e7fa753b338657faaa49e298b86f
Author: Ray Strode <rstrode redhat com>
Date:   Wed Aug 15 19:48:26 2012 -0400

    stuff that needs to be squashed

 data/dbus-interfaces.xml                     |    7 +
 src/Makefile.am                              |    2 +-
 src/goabackend/Makefile.am                   |   19 +-
 src/goabackend/goakerberosprovider.c         | 1226 ++++++++++++++++++++------
 src/goabackend/org.gnome.Identity.xml        |   73 --
 src/goaidentity/Makefile.am                  |    2 +
 src/goaidentity/goaalarm.c                   |   25 +-
 src/goaidentity/goaidentity.c                |    6 -
 src/goaidentity/goaidentity.h                |    3 +-
 src/goaidentity/goaidentityservice.c         | 1002 ++++++++++++---------
 src/goaidentity/goaidentityutils.c           |    4 +-
 src/goaidentity/goaidentityutils.h           |    4 +-
 src/goaidentity/goakerberosidentity.c        |  190 ++---
 src/goaidentity/goakerberosidentitymanager.c |   11 +-
 src/goaidentity/org.gnome.Identity.xml       |   17 +
 15 files changed, 1643 insertions(+), 948 deletions(-)
---
diff --git a/data/dbus-interfaces.xml b/data/dbus-interfaces.xml
index 07aac04..c58aed0 100644
--- a/data/dbus-interfaces.xml
+++ b/data/dbus-interfaces.xml
@@ -486,6 +486,13 @@
       ticketing capabilities.
   -->
   <interface name="org.gnome.OnlineAccounts.Ticketing">
+    <!--
+      GetTicket:
+
+      Use this method to obtain an ticket that can be used to
+      access resources for the account.
+    -->
+    <method name="GetTicket"/>
   </interface>
 
 </node>
diff --git a/src/Makefile.am b/src/Makefile.am
index 21cf4e5..63a20e5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,6 +1,6 @@
 
 NULL =
 
-SUBDIRS = goa goabackend goaidentity daemon examples
+SUBDIRS = goa goaidentity goabackend daemon examples
 
 -include $(top_srcdir)/git.mk
diff --git a/src/goabackend/Makefile.am b/src/goabackend/Makefile.am
index b9d607f..ad608bd 100644
--- a/src/goabackend/Makefile.am
+++ b/src/goabackend/Makefile.am
@@ -6,6 +6,7 @@ EXTRA_DIST =
 INCLUDES = 							\
 	-I$(top_builddir)/src -I$(top_srcdir)/src		\
 	-I$(top_builddir)/src -I$(top_srcdir)/src		\
+	-I$(top_srcdir)/src/goaidentity				\
 	-DPACKAGE_LIBEXEC_DIR=\""$(libexecdir)"\" 		\
 	-DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\" 		\
 	-DPACKAGE_DATA_DIR=\""$(datadir)"\" 			\
@@ -35,19 +36,6 @@ enum_built_sources =							\
 
 EXTRA_DIST += goabackendenumtypes.h.template goabackendenumtypes.c.template
 
-dbus_built_sources = org.gnome.Identity.c org.gnome.Identity.h
-
-$(dbus_built_sources) : Makefile.am org.gnome.Identity.xml
-	gdbus-codegen                                       \
-		--interface-prefix org.gnome.Identity.      \
-		--c-namespace GoaIdentity                   \
-		--c-generate-object-manager                 \
-		--generate-c-code org.gnome.Identity        \
-		org.gnome.Identity.xml                      \
-		$(NULL)
-
-EXTRA_DIST += $(dbus_built_sources)
-
 # ----------------------------------------------------------------------------------------------------
 
 lib_LTLIBRARIES = libgoa-backend-1.0.la
@@ -71,7 +59,6 @@ libgoa_backend_1_0_la_HEADERS =						\
 	goayahooprovider.h						\
 	goatwitterprovider.h						\
 	goawindowsliveprovider.h					\
-	org.gnome.Identity.h						\
 	$(NULL)
 
 libgoa_backend_1_0_la_SOURCES =						\
@@ -95,7 +82,7 @@ libgoa_backend_1_0_la_SOURCES =						\
 	goautils.h			goautils.c			\
 	goawebview.h			goawebview.c			\
 	nautilus-floating-bar.h		nautilus-floating-bar.c		\
-	org.gnome.Identity.c		 org.gnome.Identity.h		\
+	$(top_srcdir)/src/goaidentity/org.gnome.Identity.c		\
 	$(NULL)
 
 libgoa_backend_1_0_la_CPPFLAGS =				\
@@ -107,6 +94,7 @@ libgoa_backend_1_0_la_CFLAGS =					\
 	-DGOA_API_IS_SUBJECT_TO_CHANGE				\
 	$(WEBKIT_GTK_CFLAGS)					\
 	$(JSON_GLIB_CFLAGS)					\
+	$(GCR_CFLAGS) 						\
 	$(GLIB_CFLAGS) 						\
 	$(GTK_CFLAGS) 						\
 	$(REST_CFLAGS)						\
@@ -119,6 +107,7 @@ libgoa_backend_1_0_la_LIBADD = 					\
 	$(top_builddir)/src/goa/libgoa-1.0.la			\
 	$(WEBKIT_GTK_LIBS)					\
 	$(JSON_GLIB_LIBS)					\
+	$(GCR_LIBS) 						\
 	$(GLIB_LIBS) 						\
 	$(GTK_LIBS) 						\
 	$(REST_LIBS)						\
diff --git a/src/goabackend/goakerberosprovider.c b/src/goabackend/goakerberosprovider.c
index 1b8b75b..edf3088 100644
--- a/src/goabackend/goakerberosprovider.c
+++ b/src/goabackend/goakerberosprovider.c
@@ -29,6 +29,9 @@
 #include "goakerberosprovider.h"
 #include "goaeditablelabel.h"
 #include "goautils.h"
+#include "goaidentity.h"
+
+#include <gcr/gcr.h>
 
 #include "org.gnome.Identity.h"
 
@@ -42,7 +45,8 @@ struct _GoaKerberosProvider
 {
   /*< private >*/
   GoaProvider parent_instance;
-  GoaIdentityManager *identity_manager;
+  GoaIdentityServiceManager *identity_manager;
+  GDBusObjectManager *object_manager;
 };
 
 typedef struct _GoaKerberosProviderClass GoaKerberosProviderClass;
@@ -78,6 +82,620 @@ get_provider_name (GoaProvider *provider, GoaObject *object)
   return g_strdup(_("Enterprise Identity"));
 }
 
+typedef struct
+{
+  GtkDialog *dialog;
+  GMainLoop *loop;
+
+  GtkWidget *cluebar;
+  GtkWidget *cluebar_label;
+  GtkWidget *spinner;
+
+  GtkWidget *realm;
+
+  GtkWidget *expander;
+  GtkWidget *username;
+  GtkWidget *server;
+
+  gchar *account_object_path;
+
+  GError *error;
+} SignInRequest;
+
+static void
+on_identity_signed_in (GoaIdentityServiceManager *manager,
+                       GAsyncResult              *result,
+                       GSimpleAsyncResult        *operation_result)
+{
+  gboolean  signed_in;
+  GError   *error;
+  char     *identity_object_path;
+
+  error = NULL;
+  signed_in = goa_identity_service_manager_call_sign_in_finish (manager,
+                                                                &identity_object_path,
+                                                                result,
+                                                                &error);
+
+  if (!signed_in)
+    {
+      /* FIXME: should do proper error matching here */
+      if (strstr (error->message, "ancel") != NULL)
+        {
+          g_clear_error (&error);
+          g_set_error_literal (&error,
+                               GOA_ERROR,
+                               GOA_ERROR_DIALOG_DISMISSED,
+                               "");
+        }
+      else
+        g_dbus_error_strip_remote_error (error);
+      g_simple_async_result_take_error (operation_result, error);
+      g_simple_async_result_complete_in_idle (operation_result);
+      g_object_unref (operation_result);
+      return;
+    }
+
+  g_simple_async_result_set_op_res_gpointer (operation_result,
+                                             g_strdup (identity_object_path),
+                                             (GDestroyNotify)
+                                             g_free);
+  g_simple_async_result_complete_in_idle (operation_result);
+  g_object_unref (operation_result);
+}
+
+static void
+on_identity_manager_ensured (GoaKerberosProvider *self,
+                             GAsyncResult        *result,
+                             GSimpleAsyncResult  *operation_result)
+{
+  GoaIdentityServiceManager *manager;
+  GError             *error;
+
+  error = NULL;
+  manager = goa_identity_service_manager_proxy_new_for_bus_finish (result, &error);
+  if (manager == NULL)
+    {
+      g_dbus_error_strip_remote_error (error);
+      g_simple_async_result_take_error (operation_result, error);
+      g_simple_async_result_complete_in_idle (operation_result);
+      g_object_unref (operation_result);
+      return;
+    }
+
+  g_simple_async_result_set_op_res_gpointer (operation_result,
+                                             g_object_ref (manager),
+                                             (GDestroyNotify)
+                                             g_object_unref);
+  g_simple_async_result_complete_in_idle (operation_result);
+  g_object_unref (operation_result);
+}
+
+static void
+ensure_identity_manager (GoaKerberosProvider *self,
+                         GCancellable        *cancellable,
+                         GAsyncReadyCallback  callback,
+                         gpointer             user_data)
+{
+  GSimpleAsyncResult *operation_result;
+
+  operation_result = g_simple_async_result_new (G_OBJECT (self),
+                                                callback,
+                                                user_data,
+                                                ensure_identity_manager);
+  g_simple_async_result_set_check_cancellable (operation_result, cancellable);
+
+  g_object_set_data (G_OBJECT (operation_result),
+                     "cancellable",
+                     cancellable);
+
+  if (self->identity_manager != NULL)
+    {
+      g_simple_async_result_set_op_res_gpointer (operation_result,
+                                                 g_object_ref (self->identity_manager),
+                                                 (GDestroyNotify)
+                                                 g_object_unref);
+      g_simple_async_result_complete_in_idle (operation_result);
+      g_object_unref (operation_result);
+      return;
+    }
+
+  goa_identity_service_manager_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+                                                  G_DBUS_PROXY_FLAGS_NONE,
+                                                  "org.gnome.Identity",
+                                                  "/org/gnome/Identity/Manager",
+                                                  cancellable,
+                                                  (GAsyncReadyCallback)
+                                                  on_identity_manager_ensured,
+                                                  operation_result);
+}
+
+static void
+on_object_manager_ensured (GoaKerberosProvider *self,
+                           GAsyncResult        *result,
+                           GSimpleAsyncResult  *operation_result)
+{
+  GDBusObjectManager *manager;
+  GError *error;
+
+  error = NULL;
+  manager = goa_identity_service_object_manager_client_new_for_bus_finish (result, &error);
+  if (manager == NULL)
+    {
+      g_dbus_error_strip_remote_error (error);
+      g_simple_async_result_take_error (operation_result, error);
+      g_simple_async_result_complete_in_idle (operation_result);
+      g_object_unref (operation_result);
+      return;
+    }
+
+  g_simple_async_result_set_op_res_gpointer (operation_result,
+                                             g_object_ref (manager),
+                                             (GDestroyNotify)
+                                             g_object_unref);
+  g_simple_async_result_complete_in_idle (operation_result);
+  g_object_unref (operation_result);
+}
+
+static void
+ensure_object_manager (GoaKerberosProvider *self,
+                       GCancellable        *cancellable,
+                       GAsyncReadyCallback  callback,
+                       gpointer             user_data)
+{
+  GSimpleAsyncResult *operation_result;
+
+  operation_result = g_simple_async_result_new (G_OBJECT (self),
+                                                callback,
+                                                user_data,
+                                                ensure_object_manager);
+  g_simple_async_result_set_check_cancellable (operation_result, cancellable);
+
+  g_object_set_data (G_OBJECT (operation_result),
+                     "cancellable",
+                     cancellable);
+
+  if (self->object_manager != NULL)
+    {
+      g_simple_async_result_set_op_res_gpointer (operation_result,
+                                                 g_object_ref (self->object_manager),
+                                                 (GDestroyNotify)
+                                                 g_object_unref);
+      g_simple_async_result_complete_in_idle (operation_result);
+      g_object_unref (operation_result);
+      return;
+    }
+  goa_identity_service_object_manager_client_new_for_bus (G_BUS_TYPE_SESSION,
+                                                          G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
+                                                          "org.gnome.Identity",
+                                                          "/org/gnome/Identity",
+                                                          cancellable,
+                                                          (GAsyncReadyCallback)
+                                                          on_object_manager_ensured,
+                                                          operation_result);
+}
+
+static void
+on_secret_keys_exchanged_for_sign_in (GoaKerberosProvider *self,
+                                      GAsyncResult        *result,
+                                      GSimpleAsyncResult  *operation_result)
+{
+  const char       *identifier;
+  const char       *password;
+  GCancellable     *cancellable;
+  GError           *error;
+  GVariantBuilder   details;
+
+  error = NULL;
+
+  if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result),
+                                             &error))
+    {
+      g_simple_async_result_take_error (operation_result, error);
+      g_simple_async_result_complete_in_idle (operation_result);
+      g_object_unref (operation_result);
+      return;
+    }
+
+  cancellable = g_object_get_data (G_OBJECT (operation_result), "cancellable");
+  password = g_object_get_data (G_OBJECT (operation_result), "password");
+  identifier = g_simple_async_result_get_source_tag (operation_result);
+
+  g_variant_builder_init (&details, G_VARIANT_TYPE ("a{ss}"));
+
+  if (password != NULL)
+    {
+      GcrSecretExchange *secret_exchange;
+      char *secret;
+
+      secret_exchange = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
+
+      secret = gcr_secret_exchange_send (secret_exchange, password, -1);
+      g_variant_builder_add (&details, "{ss}", "initial-password", secret);
+      g_free (secret);
+    }
+
+  goa_identity_service_manager_call_sign_in (self->identity_manager,
+                                             identifier,
+                                             g_variant_builder_end (&details),
+                                             cancellable,
+                                             (GAsyncReadyCallback)
+                                             on_identity_signed_in,
+                                             operation_result);
+}
+
+static void
+on_secret_keys_exchanged (GoaIdentityServiceManager *manager,
+                          GAsyncResult              *result,
+                          GSimpleAsyncResult        *operation_result)
+{
+  GcrSecretExchange *secret_exchange;
+  char              *return_key;
+  GError            *error;
+
+  secret_exchange = g_simple_async_result_get_source_tag (operation_result);
+
+  error = NULL;
+  if (!goa_identity_service_manager_call_exchange_secret_keys_finish (manager,
+                                                                      &return_key,
+                                                                      result,
+                                                                      &error))
+    {
+      g_object_unref (secret_exchange);
+
+      g_simple_async_result_take_error (operation_result, error);
+      g_simple_async_result_complete_in_idle (operation_result);
+      g_object_unref (operation_result);
+      return;
+    }
+
+  if (!gcr_secret_exchange_receive (secret_exchange, return_key))
+    {
+      g_object_unref (secret_exchange);
+
+      g_simple_async_result_set_error (operation_result,
+                                       GCR_ERROR,
+                                       GCR_ERROR_UNRECOGNIZED,
+                                       _("Identity service returned invalid key"));
+      g_simple_async_result_complete_in_idle (operation_result);
+      g_object_unref (operation_result);
+      return;
+    }
+
+  g_simple_async_result_set_op_res_gpointer (operation_result,
+                                             secret_exchange,
+                                             (GDestroyNotify)
+                                             g_object_unref);
+  g_simple_async_result_complete_in_idle (operation_result);
+  g_object_unref (operation_result);
+}
+
+static void
+exchange_secret_keys (GoaKerberosProvider  *self,
+                      const char           *password,
+                      GCancellable         *cancellable,
+                      GAsyncReadyCallback   callback,
+                      gpointer              user_data)
+{
+
+  GSimpleAsyncResult *operation_result;
+  GcrSecretExchange  *secret_exchange;
+  char               *secret_key;
+
+  secret_exchange = gcr_secret_exchange_new (NULL);
+
+  operation_result = g_simple_async_result_new (G_OBJECT (self),
+                                                callback,
+                                                user_data,
+                                                secret_exchange);
+
+  if (password == NULL)
+    {
+      g_simple_async_result_complete_in_idle (operation_result);
+      g_simple_async_result_set_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (operation_result),
+                                                 NULL,
+                                                 NULL);
+      return;
+    }
+
+  secret_key = gcr_secret_exchange_begin (secret_exchange);
+
+  goa_identity_service_manager_call_exchange_secret_keys (self->identity_manager,
+                                                          secret_key,
+                                                          cancellable,
+                                                          (GAsyncReadyCallback)
+                                                          on_secret_keys_exchanged,
+                                                          operation_result);
+  g_free (secret_key);
+}
+
+static void
+on_identity_manager_ensured_for_sign_in (GoaKerberosProvider *self,
+                                         GAsyncResult        *result,
+                                         GSimpleAsyncResult  *operation_result)
+{
+  GoaIdentityServiceManager *manager;
+  const char                *password;
+  GCancellable              *cancellable;
+  GError                    *error;
+
+  error = NULL;
+
+  if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result),
+                                             &error))
+    {
+      g_simple_async_result_take_error (operation_result, error);
+      g_simple_async_result_complete_in_idle (operation_result);
+      g_object_unref (operation_result);
+      return;
+    }
+
+  manager = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
+
+  if (self->identity_manager == NULL)
+    self->identity_manager = g_object_ref (manager);
+
+  cancellable = g_object_get_data (G_OBJECT (operation_result), "cancellable");
+  password = g_object_get_data (G_OBJECT (operation_result), "password");
+
+  exchange_secret_keys (self,
+                        password,
+                        cancellable,
+                        (GAsyncReadyCallback)
+                        on_secret_keys_exchanged_for_sign_in,
+                        operation_result);
+}
+
+static void
+sign_in_identity (GoaKerberosProvider  *self,
+                  const char           *identifier,
+                  const char           *password,
+                  GCancellable         *cancellable,
+                  GAsyncReadyCallback   callback,
+                  gpointer              user_data)
+{
+  GSimpleAsyncResult *operation_result;
+
+  operation_result = g_simple_async_result_new (G_OBJECT (self),
+                                                callback,
+                                                user_data,
+                                                (gpointer)
+                                                identifier);
+
+  g_simple_async_result_set_check_cancellable (operation_result, cancellable);
+
+  g_object_set_data (G_OBJECT (operation_result),
+                     "cancellable",
+                     cancellable);
+  g_object_set_data (G_OBJECT (operation_result),
+                     "password",
+                     (gpointer)
+                     password);
+
+  ensure_identity_manager (self,
+                           cancellable,
+                           (GAsyncReadyCallback)
+                           on_identity_manager_ensured_for_sign_in,
+                           operation_result);
+}
+
+static void
+on_object_manager_ensured_for_look_up (GoaKerberosProvider *self,
+                                       GAsyncResult        *result,
+                                       GSimpleAsyncResult  *operation_result)
+{
+  GDBusObjectManager *manager;
+  const char         *identifier;
+  GList              *objects, *node;
+  GError             *error;
+
+  error = NULL;
+
+  if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result),
+                                             &error))
+    {
+      g_simple_async_result_take_error (operation_result, error);
+      g_simple_async_result_complete_in_idle (operation_result);
+      g_object_unref (operation_result);
+      return;
+    }
+
+  manager = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
+
+  if (self->object_manager == NULL)
+    self->object_manager = g_object_ref (manager);
+
+  identifier = g_simple_async_result_get_source_tag (operation_result);
+
+  g_simple_async_result_set_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (operation_result),
+                                             NULL,
+                                             NULL);
+  objects = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (self->object_manager));
+
+  for (node = objects; node != NULL; node = node->next)
+    {
+      GoaIdentityServiceIdentity *candidate_identity;
+      const char                 *candidate_identifier;
+      GDBusObject                *object;
+
+      object = node->data;
+
+      candidate_identity = GOA_IDENTITY_SERVICE_IDENTITY (g_dbus_object_get_interface (object, "org.gnome.Identity"));
+
+      if (candidate_identity == NULL)
+        continue;
+
+      candidate_identifier = goa_identity_service_identity_get_identifier (candidate_identity);
+
+      if (g_strcmp0 (candidate_identifier, identifier) == 0)
+        {
+          g_simple_async_result_set_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (operation_result),
+                                                     candidate_identity,
+                                                     (GDestroyNotify)
+                                                     g_object_unref);
+          break;
+        }
+
+      g_object_unref (candidate_identity);
+    }
+
+  g_list_free_full (objects, (GDestroyNotify) g_object_unref);
+  g_simple_async_result_complete_in_idle (G_SIMPLE_ASYNC_RESULT (operation_result));
+  g_object_unref (operation_result);
+}
+
+static void
+look_up_identity (GoaKerberosProvider  *self,
+                  const char           *identifier,
+                  GCancellable         *cancellable,
+                  GAsyncReadyCallback   callback,
+                  gpointer              user_data)
+{
+  GSimpleAsyncResult *operation_result;
+
+  operation_result = g_simple_async_result_new (G_OBJECT (self),
+                                                callback,
+                                                user_data,
+                                                (gpointer)
+                                                identifier);
+
+  g_simple_async_result_set_check_cancellable (operation_result, cancellable);
+
+  g_object_set_data (G_OBJECT (operation_result),
+                     "cancellable",
+                     cancellable);
+  ensure_object_manager (self,
+                         cancellable,
+                         (GAsyncReadyCallback)
+                         on_object_manager_ensured_for_look_up,
+                         operation_result);
+}
+
+static void
+on_account_signed_in (GoaProvider   *provider,
+                      GAsyncResult  *result,
+                      SignInRequest *request)
+{
+  if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result),
+                                             &request->error))
+    {
+      g_main_loop_quit (request->loop);
+      return;
+    }
+
+  g_main_loop_quit (request->loop);
+}
+
+static gboolean
+get_ticket_sync (GoaKerberosProvider *self,
+                 GoaObject           *object,
+                 gboolean             is_interactive,
+                 GCancellable        *cancellable,
+                 GError             **error)
+{
+  GVariant            *credentials;
+  GError              *lookup_error;
+  GoaAccount          *account;
+  const char          *identifier;
+  const char          *password;
+  SignInRequest        request;
+  gboolean             ret;
+
+  ret = FALSE;
+
+  account = goa_object_peek_account (object);
+  identifier = goa_account_get_identity (account);
+  password = NULL;
+
+  lookup_error = NULL;
+  credentials = goa_utils_lookup_credentials_sync (GOA_PROVIDER (self),
+                                                   object,
+                                                   cancellable,
+                                                   &lookup_error);
+  if (!is_interactive)
+    {
+      if (credentials == NULL)
+        {
+          if (lookup_error != NULL)
+              g_propagate_error (error, lookup_error);
+          else
+              g_set_error (error,
+                           GOA_ERROR,
+                           GOA_ERROR_NOT_AUTHORIZED,
+                           _("Could not find saved credentials for principal `%s' in keyring"), identifier);
+          goto out;
+        }
+
+      if (!g_variant_lookup (credentials, "password", "&s", &password))
+        {
+          g_set_error (error,
+                       GOA_ERROR,
+                       GOA_ERROR_NOT_AUTHORIZED,
+                       _("Did not find password for principal `%s' in credentials"),
+                       identifier);
+          goto out;
+        }
+    }
+
+  memset (&request, 0, sizeof (SignInRequest));
+  request.loop = g_main_loop_new (NULL, FALSE);
+  request.error = NULL;
+
+  sign_in_identity (self,
+                    identifier,
+                    password,
+                    NULL,
+                    (GAsyncReadyCallback)
+                    on_account_signed_in,
+                    &request);
+
+  g_main_loop_run (request.loop);
+  g_main_loop_unref (request.loop);
+
+  if (request.error != NULL)
+    {
+      g_propagate_error (error, request.error);
+      goto out;
+    }
+
+  ret = TRUE;
+out:
+  if (credentials != NULL)
+    g_variant_unref (credentials);
+
+  return ret;
+}
+
+static gboolean
+on_handle_get_ticket (GoaTicketing          *interface,
+                      GDBusMethodInvocation *invocation)
+{
+  GoaObject *object;
+  GoaAccount *account;
+  GoaProvider *provider;
+  GError *error;
+  gboolean got_ticket;
+
+  object = GOA_OBJECT (g_dbus_interface_get_object (G_DBUS_INTERFACE (interface)));
+  account = goa_object_peek_account (object);
+
+  provider = goa_provider_get_for_provider_type (goa_account_get_provider_type (account));
+  error = NULL;
+  got_ticket = get_ticket_sync (GOA_KERBEROS_PROVIDER (provider),
+                                object,
+                                TRUE /* Allow interaction */,
+                                NULL,
+                                &error);
+
+  if (!got_ticket)
+    g_dbus_method_invocation_take_error (invocation, error);
+  else
+    goa_ticketing_complete_get_ticket (interface, invocation);
+
+  g_object_unref (provider);
+  return TRUE;
+}
+
 static gboolean
 build_object (GoaProvider         *provider,
               GoaObjectSkeleton   *object,
@@ -111,13 +729,19 @@ build_object (GoaProvider         *provider,
       if (ticketing == NULL)
         {
           ticketing = goa_ticketing_skeleton_new ();
+
+          g_signal_connect (ticketing,
+                            "handle-get-ticket",
+                            G_CALLBACK (on_handle_get_ticket),
+                            NULL);
+
           goa_object_skeleton_set_ticketing (object, ticketing);
+
         }
     }
-  else
+  else if (ticketing != NULL)
     {
-      if (ticketing != NULL)
-        goa_object_skeleton_set_ticketing (object, NULL);
+      goa_object_skeleton_set_ticketing (object, NULL);
     }
 
   if (just_added)
@@ -168,28 +792,10 @@ add_entry (GtkWidget     *grid1,
     *out_entry = entry;
 }
 
-typedef struct
-{
-  GtkDialog *dialog;
-  GMainLoop *loop;
-
-  GtkWidget *cluebar;
-  GtkWidget *cluebar_label;
-  GtkWidget *spinner;
-
-  GtkWidget *realm;
-
-  GtkWidget *expander;
-  GtkWidget *username;
-  GtkWidget *server;
-
-  gchar *account_object_path;
-
-  GError *error;
-} SignInRequest;
-
 static void
-create_account_details_ui (GtkBox *vbox, gboolean new_account, SignInRequest *request)
+create_account_details_ui (GtkBox        *vbox,
+                           gboolean       new_account,
+                           SignInRequest *request)
 {
   GtkWidget *header_grid;
   GtkWidget *grid1;
@@ -263,238 +869,209 @@ add_account_cb (GoaManager *manager, GAsyncResult *res, gpointer user_request)
                                        &request->account_object_path,
                                        res,
                                        &request->error);
+  if (request->error != NULL)
+    g_dbus_error_strip_remote_error (request->error);
   g_main_loop_quit (request->loop);
 }
 
-static void
-on_identity_signed_in (GoaIdentityManager *manager,
-                       GAsyncResult       *result,
-                       GSimpleAsyncResult *operation_result)
+static gboolean
+refresh_account (GoaProvider    *provider,
+                 GoaClient      *client,
+                 GoaObject      *object,
+                 GtkWindow      *parent,
+                 GError        **error)
 {
-  gboolean  signed_in;
-  GError   *error;
-  char     *identity_object_path;
-
-  error = NULL;
-  signed_in = goa_identity_manager_call_sign_in_finish (manager,
-                                                        &identity_object_path,
-                                                        result,
-                                                        &error);
+  GoaKerberosProvider *self = GOA_KERBEROS_PROVIDER (provider);
+  gboolean             got_ticket;
 
-  if (!signed_in)
-    {
-      g_simple_async_result_take_error (operation_result, error);
-      g_simple_async_result_complete_in_idle (operation_result);
-      return;
-    }
+  g_return_val_if_fail (GOA_IS_KERBEROS_PROVIDER (provider), FALSE);
+  g_return_val_if_fail (GOA_IS_CLIENT (client), FALSE);
+  g_return_val_if_fail (GOA_IS_OBJECT (object), FALSE);
+  g_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
-  g_simple_async_result_set_op_res_gpointer (operation_result,
-                                             g_strdup (identity_object_path),
-                                             (GDestroyNotify)
-                                             g_free);
-  g_simple_async_result_complete_in_idle (operation_result);
+  got_ticket = get_ticket_sync (self,
+                                object,
+                                TRUE /* Allow interaction */,
+                                NULL,
+                                error);
+  return got_ticket;
 }
 
 static void
-on_identity_manager_ensured (GoaKerberosProvider *self,
-                             GAsyncResult        *result,
-                             GSimpleAsyncResult  *operation_result)
+on_initial_sign_in_done (GoaKerberosProvider *self,
+                         GAsyncResult        *result,
+                         GSimpleAsyncResult  *operation_result)
 {
-  GoaIdentityManager *manager;
-  GError             *error;
+  GError    *error;
+  gboolean   remember_password;
+  GoaObject *object;
+
+  object = g_simple_async_result_get_source_tag (operation_result);
+
+  remember_password = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (operation_result),
+                                                          "remember-password"));
 
   error = NULL;
-  manager = goa_identity_manager_proxy_new_for_bus_finish (result, &error);
-  if (manager == NULL)
+  if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), &error))
     {
       g_simple_async_result_take_error (operation_result, error);
-      g_simple_async_result_complete_in_idle (operation_result);
-      return;
+    }
+  else if (remember_password)
+    {
+      GVariantBuilder  builder;
+      const char      *object_path;
+
+      object_path = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
+
+      if (object_path != NULL && object != NULL)
+        {
+          GcrSecretExchange *secret_exchange;
+          const char        *password;
+
+          secret_exchange = g_object_get_data (G_OBJECT (operation_result), "secret-exchange");
+          password = gcr_secret_exchange_get_secret (secret_exchange, NULL);
+
+          /* FIXME: we go to great lengths to keep the password in non-pageable memory,
+           * and then just duplicate it into a gvariant here
+           */
+          g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
+          g_variant_builder_add (&builder,
+                                 "{sv}",
+                                 "password",
+                                 g_variant_new_string (password));
+
+          error = NULL;
+          goa_utils_store_credentials_for_object_sync (GOA_PROVIDER (self),
+                                                       object,
+                                                       g_variant_builder_end (&builder),
+                                                       NULL,
+                                                       NULL);
+        }
     }
 
-  g_simple_async_result_set_op_res_gpointer (operation_result,
-                                             g_object_ref (manager),
-                                             (GDestroyNotify)
-                                             g_object_unref);
   g_simple_async_result_complete_in_idle (operation_result);
+  g_object_unref (operation_result);
 }
 
 static void
-ensure_identity_manager (GoaKerberosProvider *self,
-                         GCancellable        *cancellable,
-                         GAsyncReadyCallback  callback,
-                         gpointer             user_data)
+on_system_prompt_answered_for_initial_sign_in (GcrPrompt          *prompt,
+                                               GAsyncResult       *result,
+                                               GSimpleAsyncResult *operation_result)
 {
-  GSimpleAsyncResult *operation_result;
+  GoaKerberosProvider *self;
+  GCancellable        *cancellable;
+  GError              *error;
+  const char          *principal;
+  const char          *password;
+  GcrSecretExchange   *secret_exchange;
 
-  operation_result = g_simple_async_result_new (G_OBJECT (self),
-                                                callback,
-                                                user_data,
-                                                ensure_identity_manager);
-  g_simple_async_result_set_check_cancellable (operation_result, cancellable);
+  self = GOA_KERBEROS_PROVIDER (g_async_result_get_source_object (G_ASYNC_RESULT (operation_result)));
+  principal = g_object_get_data (G_OBJECT (operation_result), "principal");
+  cancellable = g_object_get_data (G_OBJECT (operation_result), "cancellable");
 
-  g_object_set_data (G_OBJECT (operation_result),
-                     "cancellable",
-                     cancellable);
+  error = NULL;
+  password = gcr_prompt_password_finish (prompt, result, &error);
 
-  if (self->identity_manager != NULL)
+  if (password == NULL)
     {
-      g_simple_async_result_set_op_res_gpointer (operation_result,
-                                                 g_object_ref (self->identity_manager),
-                                                 (GDestroyNotify)
-                                                 g_object_unref);
+      if (error != NULL)
+        g_simple_async_result_take_error (operation_result, error);
+      else
+        g_cancellable_cancel (cancellable);
+
       g_simple_async_result_complete_in_idle (operation_result);
+      g_object_unref (operation_result);
       return;
     }
 
-  goa_identity_manager_proxy_new_for_bus (G_BUS_TYPE_SESSION,
-                                          G_DBUS_PROXY_FLAGS_NONE,
-                                          "org.gnome.Identity",
-                                          "/org/gnome/Identity/Manager",
-                                          cancellable,
-                                          (GAsyncReadyCallback)
-                                          on_identity_manager_ensured,
-                                          operation_result);
+  secret_exchange = gcr_system_prompt_get_secret_exchange (GCR_SYSTEM_PROMPT (prompt));
+  g_object_set_data_full (G_OBJECT (operation_result),
+                          "secret-exchange",
+                          g_object_ref (secret_exchange),
+                          (GDestroyNotify)
+                          g_object_unref);
+
+  g_object_set_data (G_OBJECT (operation_result),
+                     "remember-password",
+                     GINT_TO_POINTER (gcr_prompt_get_choice_chosen (prompt)));
+
+  gcr_system_prompt_close (GCR_SYSTEM_PROMPT (prompt), NULL, NULL);
+
+  sign_in_identity (self,
+                    principal,
+                    password,
+                    cancellable,
+                    (GAsyncReadyCallback)
+                    on_initial_sign_in_done,
+                    operation_result);
 }
 
 static void
-on_identity_manager_ensured_for_sign_in (GoaKerberosProvider *self,
-                                         GAsyncResult        *result,
-                                         GSimpleAsyncResult  *operation_result)
+on_system_prompt_open_for_initial_sign_in (GcrSystemPrompt     *system_prompt,
+                                           GAsyncResult        *result,
+                                           GSimpleAsyncResult  *operation_result)
 {
-  GoaIdentityManager *manager;
-  const char         *identity;
-  const char         *password;
-  GCancellable       *cancellable;
-  GError             *error;
-  GVariantBuilder     details;
+  GCancellable *cancellable;
+  GcrPrompt *prompt;
+  GError *error;
 
+  cancellable = g_object_get_data (G_OBJECT (operation_result), "cancellable");
   error = NULL;
+  prompt = gcr_system_prompt_open_finish (result, &error);
 
-  if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result),
-                                             &error))
+  if (prompt == NULL)
     {
       g_simple_async_result_take_error (operation_result, error);
+
       g_simple_async_result_complete_in_idle (operation_result);
+      g_object_unref (operation_result);
+
       return;
     }
 
-  manager = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
-
-  if (self->identity_manager == NULL) {
-        self->identity_manager = g_object_ref (manager);
-  }
-
-  cancellable = g_object_get_data (G_OBJECT (operation_result), "cancellable");
-  password = g_object_get_data (G_OBJECT (operation_result), "password");
-  identity = g_simple_async_result_get_source_tag (operation_result);
-
-  g_variant_builder_init (&details, G_VARIANT_TYPE ("a{ss}"));
-
-  if (password != NULL)
-    g_variant_builder_add (&details, "{ss}", "initial-password", password);
+  gcr_prompt_set_description (prompt, _("Please enter your password below."));
+  gcr_prompt_set_choice_label (prompt, _("Remember this password"));
 
-  goa_identity_manager_call_sign_in (self->identity_manager,
-                                     identity,
-                                     g_variant_builder_end (&details),
-                                     cancellable,
-                                     (GAsyncReadyCallback)
-                                     on_identity_signed_in,
-                                     operation_result);
+  gcr_prompt_password_async (prompt,
+                             cancellable,
+                             (GAsyncReadyCallback)
+                             on_system_prompt_answered_for_initial_sign_in,
+                             operation_result);
 }
 
 static void
-sign_in_identity (GoaKerberosProvider  *self,
-                  const char           *identity,
-                  const char           *password,
-                  GCancellable         *cancellable,
-                  GAsyncReadyCallback   callback,
-                  gpointer              user_data)
+perform_initial_sign_in (GoaKerberosProvider *self,
+                         GoaObject           *object,
+                         const char          *principal,
+                         SignInRequest       *request)
 {
+
   GSimpleAsyncResult *operation_result;
+  GCancellable       *cancellable;
 
-  operation_result = g_simple_async_result_new (G_OBJECT (self),
-                                                callback,
-                                                user_data,
-                                                (gpointer)
-                                                identity);
+  cancellable = g_cancellable_new ();
 
+  operation_result = g_simple_async_result_new (G_OBJECT (self),
+                                                (GAsyncReadyCallback)
+                                                on_account_signed_in ,
+                                                request,
+                                                object);
   g_simple_async_result_set_check_cancellable (operation_result, cancellable);
 
   g_object_set_data (G_OBJECT (operation_result),
                      "cancellable",
                      cancellable);
   g_object_set_data (G_OBJECT (operation_result),
-                     "password",
+                     "principal",
                      (gpointer)
-                     password);
-
-  ensure_identity_manager (self,
-                           cancellable,
-                           (GAsyncReadyCallback)
-                           on_identity_manager_ensured_for_sign_in,
-                           operation_result);
-}
-
-static void
-on_account_signed_in (GoaProvider   *provider,
-                      GAsyncResult  *result,
-                      SignInRequest *request)
-{
-  if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result),
-                                             &request->error))
-    {
-      g_main_loop_quit (request->loop);
-      return;
-    }
-
-  g_main_loop_quit (request->loop);
-}
-
-static gboolean
-refresh_account (GoaProvider    *provider,
-                 GoaClient      *client,
-                 GoaObject      *object,
-                 GtkWindow      *parent,
-                 GError        **error)
-{
-  GoaKerberosProvider *self = GOA_KERBEROS_PROVIDER (provider);
-  SignInRequest        request;
-  GoaAccount          *account;
-  const char          *identity;
-
-  g_return_val_if_fail (GOA_IS_KERBEROS_PROVIDER (provider), FALSE);
-  g_return_val_if_fail (GOA_IS_CLIENT (client), FALSE);
-  g_return_val_if_fail (GOA_IS_OBJECT (object), FALSE);
-  g_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), FALSE);
-  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-  account = goa_object_peek_account (object);
-  identity = goa_account_get_identity (account);
-
-  memset (&request, 0, sizeof (SignInRequest));
-  request.loop = g_main_loop_new (NULL, FALSE);
-  request.error = NULL;
-
-  error = NULL;
-  sign_in_identity (self,
-                    identity,
-                    NULL,
-                    NULL,
-                    (GAsyncReadyCallback)
-                    on_account_signed_in,
-                    &request);
-
-  g_main_loop_run (request.loop);
-  g_main_loop_unref (request.loop);
-
-  if (request.error != NULL)
-    {
-      g_propagate_error (error, request.error);
-      return FALSE;
-    }
+                     principal);
 
-  return TRUE;
+  gcr_system_prompt_open_async (-1,
+                                cancellable,
+                                (GAsyncReadyCallback)
+                                on_system_prompt_open_for_initial_sign_in,
+                                operation_result);
 }
 
 static GoaObject *
@@ -550,9 +1127,7 @@ start_over:
    * given identity
    */
   provider_type = goa_provider_get_provider_type (provider);
-  /* FIXME: consider adding a new credentials interface for
-   * kerberos
-   */
+
   if (!goa_utils_check_duplicate (client,
                                   principal,
                                   provider_type,
@@ -566,6 +1141,7 @@ start_over:
 
   g_variant_builder_init (&details, G_VARIANT_TYPE ("a{ss}"));
   g_variant_builder_add (&details, "{ss}", "Realm", realm);
+  g_variant_builder_add (&details, "{ss}", "TicketingEnabled", "true");
 
   g_free (principal_for_display);
   principal_for_display = g_strdup_printf ("%s %s", username, realm);
@@ -592,13 +1168,7 @@ start_over:
 
   /* After the account is created, try to sign it in
    */
-  sign_in_identity (self,
-                    principal,
-                    NULL,
-                    NULL,
-                    (GAsyncReadyCallback)
-                    on_account_signed_in,
-                    &request);
+  perform_initial_sign_in (self, object, principal, &request);
 
   g_main_loop_run (request.loop);
 
@@ -608,19 +1178,23 @@ start_over:
       gchar *markup;
 
       g_dbus_error_strip_remote_error (request.error);
-      markup = g_strdup_printf ("<b>%s:</b> %s",
-                                _("Error connecting to enterperise identity server"),
-                                request.error->message);
-      g_clear_error (&request.error);
-
-      gtk_label_set_markup (GTK_LABEL (request.cluebar_label), markup);
-      g_free (markup);
 
-      button = gtk_dialog_get_widget_for_response (request.dialog, GTK_RESPONSE_OK);
-      gtk_button_set_label (GTK_BUTTON (button), _("_Try Again"));
-      gtk_expander_set_expanded (GTK_EXPANDER (request.expander), TRUE);
-      gtk_widget_set_no_show_all (request.cluebar, FALSE);
-      gtk_widget_show_all (request.cluebar);
+      if (strstr (request.error->message, "ancel") == NULL)
+        {
+          markup = g_strdup_printf ("<b>%s:</b> %s",
+                                    _("Error connecting to enterperise identity server"),
+                                    request.error->message);
+          g_clear_error (&request.error);
+
+          gtk_label_set_markup (GTK_LABEL (request.cluebar_label), markup);
+          g_free (markup);
+
+          button = gtk_dialog_get_widget_for_response (request.dialog, GTK_RESPONSE_OK);
+          gtk_button_set_label (GTK_BUTTON (button), _("_Try Again"));
+          gtk_expander_set_expanded (GTK_EXPANDER (request.expander), TRUE);
+          gtk_widget_set_no_show_all (request.cluebar, FALSE);
+          gtk_widget_show_all (request.cluebar);
+        }
 
       /* If it couldn't be signed in, then delete it and start over
        */
@@ -668,6 +1242,111 @@ show_account (GoaProvider         *provider,
                                                    _("Network Resources"));
 }
 
+static void
+on_identity_looked_up (GoaKerberosProvider *provider,
+                       GAsyncResult        *result,
+                       GSimpleAsyncResult  *operation_result)
+{
+
+  GoaIdentityServiceIdentity *identity;
+  GError                     *error;
+
+  error = NULL;
+  if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), &error))
+    {
+      g_simple_async_result_take_error (operation_result, error);
+      g_simple_async_result_complete_in_idle (operation_result);
+      g_object_unref (operation_result);
+      return;
+    }
+
+  identity = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
+  if (identity != NULL)
+    g_simple_async_result_set_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (operation_result),
+                                               g_object_ref (identity),
+                                               (GDestroyNotify)
+                                               g_object_unref);
+  else
+    g_simple_async_result_set_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (operation_result),
+                                               NULL,
+                                               NULL);
+
+  g_simple_async_result_complete_in_idle (operation_result);
+  g_object_unref (operation_result);
+}
+
+static void
+on_identity_looked_up_to_ensure_credentials (GoaKerberosProvider *self,
+                                             GAsyncResult        *result,
+                                             GSimpleAsyncResult  *operation_result)
+{
+
+  GoaIdentityServiceIdentity *identity;
+  GError                     *error;
+  GoaObject                  *object;
+  GoaAccount                 *account;
+  const char                 *identifier;
+  GCancellable               *cancellable;
+
+  error = NULL;
+  if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), &error))
+    {
+      g_simple_async_result_take_error (operation_result, error);
+      g_simple_async_result_complete_in_idle (operation_result);
+      g_object_unref (operation_result);
+      return;
+    }
+
+  identity = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
+
+  if (identity != NULL && goa_identity_service_identity_get_is_signed_in (identity))
+    {
+      g_simple_async_result_set_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (operation_result),
+                                                 g_object_ref (identity),
+                                                 (GDestroyNotify)
+                                                 g_object_unref);
+      g_simple_async_result_complete_in_idle (operation_result);
+      g_object_unref (operation_result);
+      return;
+    }
+
+  object = GOA_OBJECT (g_async_result_get_source_object (G_ASYNC_RESULT (operation_result)));
+  cancellable = g_object_get_data (G_OBJECT (operation_result), "cancellable");
+
+  if (!get_ticket_sync (self,
+                        object,
+                        FALSE /* Don't allow interaction */,
+                        cancellable,
+                        &error))
+    {
+      g_simple_async_result_take_error (operation_result, error);
+      g_simple_async_result_complete_in_idle (operation_result);
+      g_object_unref (operation_result);
+      return;
+    }
+
+  account = goa_object_peek_account (object);
+  identifier = goa_account_get_identity (account);
+
+  look_up_identity (self,
+                    identifier,
+                    cancellable,
+                    (GAsyncReadyCallback)
+                    on_identity_looked_up,
+                    operation_result);
+
+  g_simple_async_result_complete_in_idle (operation_result);
+  g_object_unref (operation_result);
+}
+
+static void
+on_credentials_ensured (GoaObject    *object,
+                        GAsyncResult *result,
+                        GMainLoop    *loop)
+{
+  g_main_loop_quit (loop);
+}
+
 static gboolean
 ensure_credentials_sync (GoaProvider         *provider,
                          GoaObject           *object,
@@ -675,73 +1354,66 @@ ensure_credentials_sync (GoaProvider         *provider,
                          GCancellable        *cancellable,
                          GError             **error)
 {
-  GoaKerberosProvider *self = GOA_KERBEROS_PROVIDER (provider);
-  GVariant            *credentials;
-  GoaAccount          *account;
-  const char          *identity;
-  const char          *password;
-  SignInRequest        request;
-  gboolean             ret;
-
-  ret = FALSE;
+  GoaIdentityServiceIdentity *identity;
+  GoaAccount                 *account;
+  const char                 *identifier;
+  GSimpleAsyncResult         *operation_result;
+  GMainLoop                  *loop;
+  gint64                      timestamp;
+  GDateTime                  *now, *expiration_time;
+  GTimeSpan                   time_span;
 
   account = goa_object_peek_account (object);
-  identity = goa_account_get_identity (account);
+  identifier = goa_account_get_identity (account);
+
+  loop = g_main_loop_new (NULL, FALSE);
+  operation_result = g_simple_async_result_new (G_OBJECT (object),
+                                                (GAsyncReadyCallback)
+                                                on_credentials_ensured,
+                                                loop,
+                                                ensure_credentials_sync);
+  g_simple_async_result_set_check_cancellable (operation_result, cancellable);
 
-  credentials = goa_utils_lookup_credentials_sync (provider,
-                                                   object,
-                                                   cancellable,
-                                                   error);
-  if (credentials == NULL)
-    {
-      if (error != NULL && *error == NULL)
-        g_set_error (error,
-                     GOA_ERROR,
-                     GOA_ERROR_NOT_AUTHORIZED,
-                     _("Could not find saved credentials for principal `%s' in keyring"), identity);
-      goto out;
-    }
+  g_object_set_data (G_OBJECT (operation_result),
+                     "cancellable",
+                     cancellable);
+
+  g_object_ref (operation_result);
+  look_up_identity (GOA_KERBEROS_PROVIDER (provider),
+                    identifier,
+                    cancellable,
+                    (GAsyncReadyCallback)
+                    on_identity_looked_up_to_ensure_credentials,
+                    operation_result);
+
+  g_main_loop_run (loop);
+  g_main_loop_unref (loop);
 
-  if (!g_variant_lookup (credentials, "password", "&s", &password))
+  if (g_simple_async_result_propagate_error (operation_result, error))
     {
-      g_set_error (error,
-                   GOA_ERROR,
-                   GOA_ERROR_NOT_AUTHORIZED,
-                   _("Did not find password for principal `%s' in credentials"),
-                   identity);
-      goto out;
+      g_object_unref (operation_result);
+      return FALSE;
     }
 
-  memset (&request, 0, sizeof (SignInRequest));
-  request.loop = g_main_loop_new (NULL, FALSE);
-  request.error = NULL;
+  identity = g_simple_async_result_get_op_res_gpointer (operation_result);
 
-  error = NULL;
-  sign_in_identity (self,
-                    identity,
-                    password,
+  now = g_date_time_new_now_local ();
+  timestamp = goa_identity_service_identity_get_expiration_timestamp (identity);
+  expiration_time = g_date_time_new_from_unix_local (timestamp);
+  time_span = g_date_time_difference (expiration_time, now);
 
-                    NULL,
-                    (GAsyncReadyCallback)
-                    on_account_signed_in,
-                    &request);
+  time_span /= G_TIME_SPAN_SECOND;
 
-  g_main_loop_run (request.loop);
-  g_main_loop_unref (request.loop);
+  if (time_span < 0 || time_span > G_MAXINT)
+    time_span = 0;
 
-  if (request.error != NULL)
-    {
-      g_propagate_error (error, request.error);
-      goto out;
-    }
+  *out_expires_in = (int) time_span;
 
-  *out_expires_in = -1;
-  ret = TRUE;
-out:
-  if (credentials != NULL)
-    g_variant_unref (credentials);
+  g_date_time_unref (now);
+  g_date_time_unref (expiration_time);
+  g_object_unref (operation_result);
 
-  return ret;
+  return TRUE;
 }
 
 static void
@@ -750,11 +1422,11 @@ goa_kerberos_provider_init (GoaKerberosProvider *provider)
 }
 
 static void
-goa_kerberos_provider_class_init (GoaKerberosProviderClass *klass)
+goa_kerberos_provider_class_init (GoaKerberosProviderClass *kerberos_class)
 {
   GoaProviderClass *provider_class;
 
-  provider_class = GOA_PROVIDER_CLASS (klass);
+  provider_class = GOA_PROVIDER_CLASS (kerberos_class);
   provider_class->get_provider_type          = get_provider_type;
   provider_class->get_provider_name          = get_provider_name;
   provider_class->build_object               = build_object;
diff --git a/src/goaidentity/Makefile.am b/src/goaidentity/Makefile.am
index 8fa4ad3..46f1c92 100644
--- a/src/goaidentity/Makefile.am
+++ b/src/goaidentity/Makefile.am
@@ -56,6 +56,8 @@ $(identity_dbus_built_sources) : Makefile.am org.gnome.Identity.xml
 		--c-generate-object-manager			\
 		--generate-c-code org.gnome.Identity		\
 		org.gnome.Identity.xml				\
+		--annotate "org.gnome.Identity"			\
+		           "org.gtk.GDBus.C.Name" Identity	\
 		$(NULL)
 BUILT_SOURCES += $(identity_dbus_built_sources)
 EXTRA_DIST += org.gnome.Identity.xml
diff --git a/src/goaidentity/goaalarm.c b/src/goaidentity/goaalarm.c
index 545a5ec..e28dd86 100644
--- a/src/goaidentity/goaalarm.c
+++ b/src/goaidentity/goaalarm.c
@@ -392,6 +392,7 @@ schedule_wakeups_with_timerfd (GoaAlarm *self)
   struct itimerspec timer_spec;
   int fd;
   int result;
+  GSource *source;
   static gboolean seen_before = FALSE;
 
   if (!seen_before)
@@ -424,15 +425,16 @@ schedule_wakeups_with_timerfd (GoaAlarm *self)
   self->priv->type = GOA_ALARM_TYPE_TIMER;
   self->priv->timer.stream = g_unix_input_stream_new (fd, TRUE);
 
-  self->priv->timer.source =
+  source =
     g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM
                                            (self->priv->timer.stream),
                                            self->priv->cancellable);
+  self->priv->timer.source = source;
   g_source_set_callback (self->priv->timer.source,
                          (GSourceFunc) on_timer_source_ready, self,
                          (GDestroyNotify) clear_timer_source_pointer);
   g_source_attach (self->priv->timer.source, self->priv->context);
-  g_source_unref (self->priv->timer.source);
+  g_source_unref (source);
 
   return TRUE;
 
@@ -474,8 +476,9 @@ static void
 schedule_wakeups_with_timeout_source (GoaAlarm *self)
 {
   GDateTime *now;
-  GTimeSpan time_span;
-  guint interval;
+  GSource   *source;
+  GTimeSpan  time_span;
+  guint      interval;
 
   self->priv->type = GOA_ALARM_TYPE_TIMEOUT;
 
@@ -492,14 +495,16 @@ schedule_wakeups_with_timeout_source (GoaAlarm *self)
    */
   interval = MIN (interval, MAX_TIMEOUT_INTERVAL);
 
-  self->priv->timeout.source = g_timeout_source_new (interval);
+  source = g_timeout_source_new (interval);
+
+  self->priv->timeout.source = source;
   g_source_set_callback (self->priv->timeout.source,
                          (GSourceFunc)
                          on_timeout_source_ready,
                          self, (GDestroyNotify) clear_timeout_source_pointer);
 
   g_source_attach (self->priv->timeout.source, self->priv->context);
-  g_source_unref (self->priv->timeout.source);
+  g_source_unref (source);
 }
 
 static void
@@ -531,15 +536,19 @@ clear_immediate_wakeup_source_pointer (GoaAlarm *self)
 static void
 schedule_immediate_wakeup (GoaAlarm *self)
 {
-  self->priv->immediate_wakeup_source = g_idle_source_new ();
+  GSource *source;
 
+  source = g_idle_source_new ();
+
+  self->priv->immediate_wakeup_source = source;
   g_source_set_callback (self->priv->immediate_wakeup_source,
                          (GSourceFunc)
                          on_immediate_wakeup_source_ready,
                          self,
                          (GDestroyNotify) clear_immediate_wakeup_source_pointer);
+
   g_source_attach (self->priv->immediate_wakeup_source, self->priv->context);
-  g_source_unref (self->priv->immediate_wakeup_source);
+  g_source_unref (source);
 }
 
 void
diff --git a/src/goaidentity/goaidentity.c b/src/goaidentity/goaidentity.c
index 03894e9..cf2f146 100644
--- a/src/goaidentity/goaidentity.c
+++ b/src/goaidentity/goaidentity.c
@@ -64,12 +64,6 @@ goa_identity_error_quark (void)
   return error_quark;
 }
 
-char **
-goa_identity_get_identifier_components (GoaIdentity *self)
-{
-  return GOA_IDENTITY_GET_IFACE (self)->get_identifier_components (self);
-}
-
 const char *
 goa_identity_get_identifier (GoaIdentity *self)
 {
diff --git a/src/goaidentity/goaidentity.h b/src/goaidentity/goaidentity.h
index 14fed36..acb4af1 100644
--- a/src/goaidentity/goaidentity.h
+++ b/src/goaidentity/goaidentity.h
@@ -41,7 +41,6 @@ struct _GoaIdentityInterface
   GTypeInterface base_interface;
 
   const char * (* get_identifier)            (GoaIdentity *identity);
-  char **      (* get_identifier_components) (GoaIdentity *identity);
   gboolean     (* is_signed_in)              (GoaIdentity *identity);
 };
 
@@ -57,6 +56,7 @@ typedef enum
   GOA_IDENTITY_ERROR_SAVING_CREDENTIALS,
   GOA_IDENTITY_ERROR_REMOVING_CREDENTIALS,
   GOA_IDENTITY_ERROR_PARSING_IDENTIFIER,
+  GOA_IDENTITY_ERROR_USER_CANCELLED,
 } GoaIdentityError;
 
 typedef enum
@@ -71,7 +71,6 @@ GType  goa_identity_get_type    (void);
 GQuark goa_identity_error_quark (void);
 
 const char  *goa_identity_get_identifier            (GoaIdentity *identity);
-char       **goa_identity_get_identifier_components (GoaIdentity *identity);
 gboolean     goa_identity_is_signed_in              (GoaIdentity *identity);
 
 
diff --git a/src/goaidentity/goaidentityservice.c b/src/goaidentity/goaidentityservice.c
index 0c66f24..f9034da 100644
--- a/src/goaidentity/goaidentityservice.c
+++ b/src/goaidentity/goaidentityservice.c
@@ -28,10 +28,10 @@
 #include <glib-object.h>
 #include <gio/gio.h>
 
-#include <libnotify/notify.h>
 #include <gcr/gcr.h>
 
 #include "goakerberosprovider.h"
+#include "goaidentityenumtypes.h"
 #include "goaidentityutils.h"
 
 #include "goakerberosidentitymanager.h"
@@ -46,16 +46,21 @@ struct _GoaIdentityServicePrivate
 
   GoaClient                *client;
   GoaManager               *accounts_manager;
+
+  GHashTable               *watched_connections;
+  GHashTable               *key_holders;
 };
 
 static void identity_service_manager_interface_init (GoaIdentityServiceManagerIface *interface);
-static void ask_to_sign_in (GoaIdentityService            *self,
-                            GoaIdentity                   *identity,
-                            gconstpointer                  initial_password,
-                            GoaIdentitySignInFlags         flags,
-                            GCancellable                  *cancellable,
-                            GAsyncReadyCallback            callback,
-                            gpointer                       user_data);
+
+static void
+sign_in (GoaIdentityService            *self,
+         const char                    *identifier,
+         gconstpointer                  initial_password,
+         GoaIdentitySignInFlags         flags,
+         GCancellable                  *cancellable,
+         GAsyncReadyCallback            callback,
+         gpointer                       user_data);
 
 G_DEFINE_TYPE_WITH_CODE (GoaIdentityService,
                          goa_identity_service,
@@ -67,29 +72,17 @@ static char *
 get_object_path_for_identity (GoaIdentityService *self,
                               GoaIdentity        *identity)
 {
-  char **components;
-  GString *object_path;
-  int i;
-
-  components = goa_identity_get_identifier_components (identity);
-  object_path = g_string_new ("/org/gnome/Identity/Manager");
-
-  for (i = 0; components[i] != NULL; i++)
-    {
-      char *escaped_component;
-
-      g_string_append_c (object_path, '/');
-      escaped_component = goa_identity_utils_escape_object_path_component (components[i],
-                                                                           (gsize)
-                                                                           strlen (components[i]));
-
-      g_string_append (object_path, escaped_component);
+  const char *identifier;
+  char       *escaped_identifier;
+  char       *object_path;
 
-      g_free (escaped_component);
-    }
-  g_strfreev (components);
+  identifier = goa_identity_get_identifier (identity);
+  escaped_identifier = goa_identity_utils_escape_object_path (identifier,
+                                                              strlen (identifier));
+  object_path = g_strdup_printf ("/org/gnome/Identity/Identities/%s", escaped_identifier);
 
-  return g_string_free (object_path, FALSE);
+  g_free (escaped_identifier);
+  return object_path;
 }
 
 static char *
@@ -101,20 +94,27 @@ export_identity (GoaIdentityService *self,
   GDBusInterfaceSkeleton *interface;
 
   object_path = get_object_path_for_identity (self, identity);
+
   object = G_DBUS_OBJECT_SKELETON (goa_identity_service_object_skeleton_new (object_path));
-  interface = G_DBUS_INTERFACE_SKELETON (goa_identity_service_org_gnome_identity_skeleton_new ());
+  interface = G_DBUS_INTERFACE_SKELETON (goa_identity_service_identity_skeleton_new ());
 
   g_object_bind_property (G_OBJECT (identity),
                           "identifier",
                           G_OBJECT (interface),
                           "identifier",
-                          G_BINDING_DEFAULT);
+                          G_BINDING_SYNC_CREATE);
 
   g_object_bind_property (G_OBJECT (identity),
                           "expiration-timestamp",
                           G_OBJECT (interface),
                           "expiration-timestamp",
-                          G_BINDING_DEFAULT);
+                          G_BINDING_SYNC_CREATE);
+
+  g_object_bind_property (G_OBJECT (identity),
+                          "is-signed-in",
+                          G_OBJECT (interface),
+                          "is-signed-in",
+                          G_BINDING_SYNC_CREATE);
 
   g_dbus_object_skeleton_add_interface (object, interface);
   g_object_unref (interface);
@@ -132,6 +132,7 @@ unexport_identity (GoaIdentityService *self,
   char *object_path;
 
   object_path = get_object_path_for_identity (self, identity);
+
   g_dbus_object_manager_server_unexport (self->priv->identity_object_manager_server,
                                          object_path);
   g_free (object_path);
@@ -164,45 +165,120 @@ on_sign_in_done (GoaIdentityService *self,
     }
 
   g_simple_async_result_complete_in_idle (operation_result);
+  g_object_unref (operation_result);
+}
+
+static GoaObject *
+find_object_with_principal (GoaIdentityService *self,
+                            const char         *principal,
+                            gboolean            must_be_enabled)
+{
+  GList      *objects;
+  GList      *node;
+  GoaObject  *found_object;
+
+  objects = goa_client_get_accounts (self->priv->client);
 
+  found_object = NULL;
+  for (node = objects; node != NULL; node = node->next)
+    {
+      GoaObject *object = GOA_OBJECT (node->data);
+      GoaAccount *account;
+      const char *provider_type;
+      const char *account_identity;
+
+      account = goa_object_peek_account (object);
+
+      if (account == NULL)
+        continue;
+
+      provider_type = goa_account_get_provider_type (account);
+
+      if (g_strcmp0 (provider_type, "kerberos") != 0)
+        continue;
+
+      if (must_be_enabled)
+        {
+          GoaTicketing *ticketing;
+
+          ticketing = goa_object_peek_ticketing (object);
+
+          if (ticketing == NULL)
+              continue;
+        }
+
+      account_identity = goa_account_get_identity (account);
+
+      if (g_strcmp0 (account_identity, principal) == 0)
+        {
+          found_object = g_object_ref (object);
+          break;
+        }
+    }
+  g_list_free_full (objects, (GDestroyNotify) g_object_unref);
+
+  return found_object;
 }
 
 static void
-on_got_identity_for_sign_in (GoaIdentityManager *manager,
-                             GAsyncResult       *result,
-                             GSimpleAsyncResult *operation_result)
+on_credentials_ensured (GoaAccount         *account,
+                        GAsyncResult       *result,
+                        GoaIdentityService *self)
 {
-  GoaIdentityService *self;
-  GError             *error;
-  GoaIdentity        *identity;
-  char               *password;
-  GoaIdentitySignInFlags flags;
+  GError     *error;
+  const char *account_identity;
+  int         expires_in;
 
-  error = NULL;
-  identity = goa_identity_manager_get_identity_finish (manager, result, &error);
+  account_identity = goa_account_get_identity (account);
 
-  if (error != NULL)
+  error = NULL;
+  if (!goa_account_call_ensure_credentials_finish (account,
+                                                   &expires_in,
+                                                   result,
+                                                   &error))
     {
-      goa_debug ("GoaIdentityService: Identity could not be signed in: %s",
+      goa_debug ("GoaIdentityService: could not ensure credentials for account %s: %s",
+                 account_identity,
                  error->message);
+      g_error_free (error);
       return;
     }
 
-  self = GOA_IDENTITY_SERVICE (g_async_result_get_source_object (G_ASYNC_RESULT (operation_result)));
+  goa_debug ("GoaIdentityService: credentials for account %s ensured for %d seconds",
+             account_identity,
+             expires_in);
+}
+
+static gboolean
+should_ignore_object (GoaIdentityService *self,
+                      GoaObject          *object)
+{
+  GoaAccount *account;
+
+  account = goa_object_peek_account (object);
+
+  if (goa_account_get_ticketing_disabled (account))
+    return TRUE;
 
-  password = g_object_get_data (G_OBJECT (result),
-                                "initial-password");
-  flags = (GoaIdentitySignInFlags) GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (result),
-                                                                        "sign-in-flags"));
-
-  ask_to_sign_in (self,
-                  identity,
-                  password,
-                  flags,
-                  NULL,
-                  (GAsyncReadyCallback)
-                  on_sign_in_done,
-                  operation_result);
+  return FALSE;
+}
+
+static void
+ensure_account_credentials (GoaIdentityService *self,
+                            GoaObject          *object)
+{
+
+  GoaAccount *account;
+
+  if (should_ignore_object (self, object))
+    return;
+
+  account = goa_object_peek_account (object);
+  goa_account_call_ensure_credentials (account,
+                                       NULL,
+                                       (GAsyncReadyCallback)
+                                       on_credentials_ensured,
+                                       self);
 }
 
 static void
@@ -211,6 +287,10 @@ on_sign_in_handled (GoaIdentityService    *self,
                     GDBusMethodInvocation *invocation)
 {
   GError *error = NULL;
+  GoaObject *object;
+  char *principal;
+
+  principal = g_simple_async_result_get_source_tag (G_SIMPLE_ASYNC_RESULT (result));
 
   if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), &error))
     {
@@ -225,6 +305,14 @@ on_sign_in_handled (GoaIdentityService    *self,
                                                      invocation,
                                                      object_path);
     }
+
+  object = find_object_with_principal (self, principal, TRUE);
+  g_free (principal);
+
+  if (object == NULL)
+    return;
+
+  ensure_account_credentials (self, object);
 }
 
 static void
@@ -241,13 +329,16 @@ read_sign_in_details (GoaIdentityServiceManager  *manager,
   g_variant_iter_init (&iter, details);
   while (g_variant_iter_loop (&iter, "{ss}", &key, &value))
     {
-      if (g_strcmp0 (key, "initial-secret") == 0)
+      if (g_strcmp0 (key, "initial-password") == 0)
         *secret_key = g_strdup (value);
-      else if (g_strcmp0 (key, "disallow-renewal") == 0)
+      else if (g_strcmp0 (key, "disallow-renewal") == 0
+               && g_strcmp0 (value, "true") == 0)
         *flags |= GOA_IDENTITY_SIGN_IN_FLAGS_DISALLOW_RENEWAL;
-      else if (g_strcmp0 (key, "disallow-forwarding") == 0)
+      else if (g_strcmp0 (key, "disallow-forwarding") == 0
+               && g_strcmp0 (value, "true") == 0)
         *flags |= GOA_IDENTITY_SIGN_IN_FLAGS_DISALLOW_FORWARDING;
-      else if (g_strcmp0 (key, "disallow-proxying") == 0)
+      else if (g_strcmp0 (key, "disallow-proxying") == 0
+               && g_strcmp0 (value, "true") == 0)
         *flags |= GOA_IDENTITY_SIGN_IN_FLAGS_DISALLOW_PROXYING;
     }
 }
@@ -259,51 +350,55 @@ goa_identity_service_handle_sign_in (GoaIdentityServiceManager *manager,
                                      GVariant                  *details)
 {
   GoaIdentityService     *self = GOA_IDENTITY_SERVICE (manager);
-  GSimpleAsyncResult     *result;
+  GSimpleAsyncResult     *operation_result;
   GoaIdentitySignInFlags  flags;
   char                   *secret_key;
+  gconstpointer           initial_password;
+  GCancellable           *cancellable;
 
   secret_key = NULL;
-
-  result = g_simple_async_result_new (G_OBJECT (self),
-                                      (GAsyncReadyCallback)
-                                      on_sign_in_handled,
-                                      g_object_ref (invocation),
-                                      goa_identity_service_handle_sign_in);
+  initial_password = NULL;
 
   read_sign_in_details (manager, details, &flags, &secret_key);
 
-  g_object_set_data (G_OBJECT (result),
-                     "sign-in-flags",
-                     GUINT_TO_POINTER ((guint) flags));
-
   if (secret_key != NULL)
     {
-      GcrSecretExchange  *secret_exchange;
-      gconstpointer       initial_password;
+      GcrSecretExchange *secret_exchange;
 
-      secret_exchange = gcr_secret_exchange_new (NULL);
+      secret_exchange = g_hash_table_lookup (self->priv->key_holders,
+                                             g_dbus_method_invocation_get_sender (invocation));
 
-      g_object_weak_ref (G_OBJECT (result),
-                         (GWeakNotify)
-                         g_object_unref,
-                         secret_exchange);
+      if (secret_exchange == NULL)
+        {
+          g_free (secret_key);
+          g_dbus_method_invocation_return_error (invocation,
+                                                 GOA_IDENTITY_MANAGER_ERROR,
+                                                 GOA_IDENTITY_MANAGER_ERROR_ACCESSING_CREDENTIALS,
+                                                 _("initial secret passed before secret key exchange"));
+          return TRUE;
+        }
 
       gcr_secret_exchange_receive (secret_exchange, secret_key);
       initial_password = gcr_secret_exchange_get_secret (secret_exchange, NULL);
-
-      g_object_set_data (G_OBJECT (result),
-                         "initial-password",
-                         (gpointer)
-                         initial_password);
     }
 
-  goa_identity_manager_get_identity (self->priv->identity_manager,
-                                     identifier,
-                                     NULL,
-                                     (GAsyncReadyCallback)
-                                     on_got_identity_for_sign_in,
-                                     result);
+  operation_result = g_simple_async_result_new (G_OBJECT (self),
+                                                (GAsyncReadyCallback)
+                                                on_sign_in_handled,
+                                                g_object_ref (invocation),
+                                                g_strdup (identifier));
+
+  cancellable = g_cancellable_new ();
+  sign_in (self,
+           identifier,
+           initial_password,
+           flags,
+           cancellable,
+           (GAsyncReadyCallback)
+           on_sign_in_done,
+           operation_result);
+  g_object_unref (cancellable);
+
   return TRUE;
 }
 
@@ -393,10 +488,138 @@ goa_identity_service_handle_sign_out (GoaIdentityServiceManager *manager,
 }
 
 static void
+on_secret_keys_exchanged (GoaIdentityService *self,
+                          GAsyncResult       *result)
+{
+  GDBusMethodInvocation *invocation;
+  GError                *error;
+
+  invocation = g_simple_async_result_get_source_tag (G_SIMPLE_ASYNC_RESULT (result));
+
+  error = NULL;
+  if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), &error))
+    {
+      g_dbus_method_invocation_take_error (invocation, error);
+    }
+  else
+    {
+      const char *output_key;
+
+      output_key = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
+      goa_identity_service_manager_complete_exchange_secret_keys (GOA_IDENTITY_SERVICE_MANAGER (self),
+                                                                  invocation,
+                                                                  output_key);
+    }
+}
+
+static void
+on_caller_watched (GDBusConnection    *connection,
+                   const char         *name,
+                   const char         *name_owner,
+                   GSimpleAsyncResult *operation_result)
+{
+  GoaIdentityService    *self;
+  GcrSecretExchange     *secret_exchange;
+  const char            *input_key;
+  char                  *output_key;
+
+  self = GOA_IDENTITY_SERVICE (g_async_result_get_source_object (G_ASYNC_RESULT (operation_result)));
+  input_key = g_object_get_data (G_OBJECT (operation_result), "input-key");
+
+  secret_exchange = gcr_secret_exchange_new (NULL);
+
+  if (!gcr_secret_exchange_receive (secret_exchange,
+                                    input_key))
+    {
+      g_simple_async_result_set_error (operation_result,
+                                       GCR_ERROR,
+                                       GCR_ERROR_UNRECOGNIZED,
+                                       _("Initial secret key is invalid"));
+      g_simple_async_result_complete_in_idle (operation_result);
+      g_object_unref (operation_result);
+      return;
+    }
+
+  g_hash_table_insert (self->priv->key_holders,
+                       g_strdup (name_owner),
+                       secret_exchange);
+
+  output_key = gcr_secret_exchange_send (secret_exchange, NULL, 0);
+
+  g_simple_async_result_set_op_res_gpointer (operation_result,
+                                             output_key,
+                                             (GDestroyNotify)
+                                             g_free);
+  g_simple_async_result_complete_in_idle (operation_result);
+}
+
+static void
+on_caller_vanished (GDBusConnection    *connection,
+                    const char         *name,
+                    GSimpleAsyncResult *operation_result)
+{
+  GoaIdentityService *self;
+  GCancellable       *cancellable;
+
+  self = GOA_IDENTITY_SERVICE (g_async_result_get_source_object (G_ASYNC_RESULT (operation_result)));
+
+  cancellable = g_object_get_data (G_OBJECT (operation_result), "cancellable");
+  g_cancellable_cancel (cancellable);
+
+  g_hash_table_remove (self->priv->watched_connections, name);
+  g_hash_table_remove (self->priv->key_holders, name);
+
+}
+
+static gboolean
+goa_identity_service_handle_exchange_secret_keys (GoaIdentityServiceManager *manager,
+                                                  GDBusMethodInvocation     *invocation,
+                                                  const char                *input_key)
+{
+  GoaIdentityService     *self = GOA_IDENTITY_SERVICE (manager);
+  GSimpleAsyncResult     *operation_result;
+  GCancellable           *cancellable;
+  guint                   watch_id;
+  const char             *sender;
+
+  cancellable = g_cancellable_new ();
+  operation_result = g_simple_async_result_new (G_OBJECT (self),
+                                                (GAsyncReadyCallback)
+                                                on_secret_keys_exchanged,
+                                                NULL,
+                                                g_object_ref (invocation));
+  g_simple_async_result_set_check_cancellable (operation_result, cancellable);
+  g_object_set_data (G_OBJECT (operation_result), "cancellable", cancellable);
+
+  g_object_set_data_full (G_OBJECT (operation_result),
+                          "input-key",
+                          g_strdup (input_key),
+                          (GDestroyNotify)
+                          g_free);
+  sender = g_dbus_method_invocation_get_sender (invocation);
+  watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION,
+                               sender,
+                               G_BUS_NAME_WATCHER_FLAGS_NONE,
+                               (GBusNameAppearedCallback)
+                               on_caller_watched,
+                               (GBusNameVanishedCallback)
+                               on_caller_vanished,
+                               g_object_ref (operation_result),
+                               (GDestroyNotify)
+                               g_object_unref);
+  g_hash_table_insert (self->priv->watched_connections,
+                       g_strdup (sender),
+                       GUINT_TO_POINTER (watch_id));
+
+  return TRUE;
+}
+
+static void
 identity_service_manager_interface_init (GoaIdentityServiceManagerIface *interface)
 {
   interface->handle_sign_in = goa_identity_service_handle_sign_in;
   interface->handle_sign_out = goa_identity_service_handle_sign_out;
+  interface->handle_exchange_secret_keys = goa_identity_service_handle_exchange_secret_keys;
 }
 
 static void
@@ -407,6 +630,19 @@ goa_identity_service_init (GoaIdentityService *self)
                                             GoaIdentityServicePrivate);
 
   goa_debug ("GoaIdentityService: initializing");
+  self->priv->watched_connections = g_hash_table_new_full (g_str_hash,
+                                                           g_str_equal,
+                                                           (GDestroyNotify)
+                                                           g_free,
+                                                           (GDestroyNotify)
+                                                           g_bus_unwatch_name);
+
+  self->priv->key_holders = g_hash_table_new_full (g_str_hash,
+                                                   g_str_equal,
+                                                   (GDestroyNotify)
+                                                   g_free,
+                                                   (GDestroyNotify)
+                                                   g_object_unref);
 }
 
 static void
@@ -425,6 +661,8 @@ goa_identity_service_finalize (GObject *object)
 
   g_clear_object (&self->priv->identity_manager);
   g_clear_object (&self->priv->identity_object_manager_server);
+  g_clear_object (&self->priv->watched_connections);
+  g_clear_object (&self->priv->key_holders);
 
   G_OBJECT_CLASS (goa_identity_service_parent_class)->finalize (object);
 }
@@ -450,68 +688,6 @@ on_identity_renewed (GoaIdentityManager *manager,
   goa_debug ("GoaIdentityService: identity renewed");
 }
 
-static gboolean
-should_ignore_object (GoaIdentityService *self,
-                      GoaObject          *object)
-{
-  GoaAccount *account;
-
-  account = goa_object_peek_account (object);
-
-  if (goa_account_get_ticketing_disabled (account))
-    return TRUE;
-
-  return FALSE;
-}
-
-static GoaObject *
-find_object_with_principal (GoaIdentityService *self,
-                            const char         *principal)
-{
-  GList      *objects;
-  GList      *node;
-  GoaObject  *found_object;
-
-  objects = goa_client_get_accounts (self->priv->client);
-
-  found_object = NULL;
-  for (node = objects; node != NULL; node = node->next)
-    {
-      GoaObject *object = GOA_OBJECT (node->data);
-      GoaAccount *account;
-      GoaTicketing *ticketing;
-      const char *provider_type;
-      const char *account_identity;
-
-      account = goa_object_peek_account (object);
-
-      if (account == NULL)
-        continue;
-
-      provider_type = goa_account_get_provider_type (account);
-
-      if (g_strcmp0 (provider_type, "kerberos") != 0)
-        continue;
-
-      ticketing = goa_object_peek_ticketing (object);
-
-      if (ticketing == NULL)
-        continue;
-
-      account_identity = goa_account_get_identity (account);
-
-      if (g_strcmp0 (account_identity, principal) == 0)
-        {
-          found_object = g_object_ref (object);
-          break;
-        }
-    }
-  g_list_free_full (objects, (GDestroyNotify) g_object_unref);
-
-  return found_object;
-}
-
-
 static void
 on_identity_needs_renewal (GoaIdentityManager *identity_manager,
                            GoaIdentity        *identity,
@@ -524,7 +700,7 @@ on_identity_needs_renewal (GoaIdentityManager *identity_manager,
 
   goa_debug ("GoaIdentityService: identity %s needs renewal", principal);
 
-  object = find_object_with_principal (self, principal);
+  object = find_object_with_principal (self, principal, TRUE);
 
   if (object != NULL)
     {
@@ -541,64 +717,10 @@ on_identity_needs_renewal (GoaIdentityManager *identity_manager,
                                        self);
 }
 
-typedef struct
-{
-  GoaIdentityService *service;
-  GoaIdentity        *identity;
-  gconstpointer       initial_password;
-  NotifyNotification *notification;
-  GSimpleAsyncResult *result;
-  GCancellable       *cancellable;
-  gulong              refreshed_signal_id;
-
-  GoaIdentitySignInFlags flags;
-} SignInRequest;
-
-static SignInRequest *
-sign_in_request_new (GoaIdentityService *service,
-                     GoaIdentity        *identity,
-                     gconstpointer       initial_password,
-                     GoaIdentitySignInFlags flags,
-                     NotifyNotification *notification,
-                     GSimpleAsyncResult *result,
-                     GCancellable       *cancellable)
-{
-  SignInRequest *request;
-
-  request = g_slice_new0 (SignInRequest);
-
-  request->service = service;
-  request->identity = g_object_ref (identity);
-  /* intentionally not dup'd, it's sitting in mlocked memory */
-  request->initial_password = initial_password;
-  request->flags = flags;
-  request->notification = notification;
-  request->result = result;
-  request->cancellable = g_object_ref (cancellable);
-
-  return request;
-}
-
-static void
-sign_in_request_free (SignInRequest *data)
-{
-  GoaIdentityService *service = data->service;
-
-  g_signal_handler_disconnect (service->priv->identity_manager,
-                               data->refreshed_signal_id);
-  g_object_set_data (G_OBJECT (data->identity),
-                     "sign-in-request",
-                     NULL);
-  g_clear_object (&data->identity);
-  g_clear_object (&data->cancellable);
-  g_clear_object (&data->result);
-  g_slice_free (SignInRequest, data);
-}
-
 static void
 on_identity_signed_in (GoaIdentityManager *manager,
                        GAsyncResult       *result,
-                       SignInRequest      *request)
+                       GSimpleAsyncResult *operation_result)
 {
   GError *error;
   GoaIdentity *identity;
@@ -609,34 +731,63 @@ on_identity_signed_in (GoaIdentityManager *manager,
   if (error != NULL)
     {
       goa_debug ("GoaIdentityService: could not sign in identity: %s",
-               error->message);
-      g_simple_async_result_take_error (request->result, error);
-      g_simple_async_result_complete_in_idle (request->result);
-      g_clear_object (&request->result);
-      g_clear_object (&request->cancellable);
+                 error->message);
+      g_simple_async_result_take_error (operation_result, error);
+    }
+  else
+    {
+      g_simple_async_result_set_op_res_gpointer (operation_result,
+                                                 g_object_ref (identity),
+                                                 (GDestroyNotify)
+                                                 g_object_unref);
+    }
+  g_simple_async_result_complete_in_idle (operation_result);
+  g_object_unref (operation_result);
+
+  goa_debug ("GoaIdentityService: identity signed in");
+}
+
+static void
+on_temporary_account_created_for_identity (GoaIdentityService *self,
+                                           GAsyncResult       *result,
+                                           GoaIdentity        *identity)
+{
+  GoaObject   *object;
+  GError      *error;
+
+  error = NULL;
+  if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), &error))
+    {
+      const char *identifier;
+
+      identifier = goa_identity_get_identifier (identity);
+      goa_debug ("Could not add temporary account for identity %s: %s",
+                 identifier,
+                 error->message);
+      g_error_free (error);
       return;
     }
 
-  g_simple_async_result_set_op_res_gpointer (request->result,
-                                             g_object_ref (identity),
-                                             (GDestroyNotify)
-                                             g_object_unref);
-  g_simple_async_result_complete_in_idle (request->result);
-  g_clear_object (&request->result);
-  g_clear_object (&request->cancellable);
+  object = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
 
-  goa_debug ("GoaIdentityService: identity signed in");
+  if (object != NULL)
+    ensure_account_credentials (self, object);
 }
 
 static void
-on_account_created_for_identity (GoaManager         *manager,
-                                 GAsyncResult       *result,
-                                 GoaIdentityService *self)
+on_account_added (GoaManager         *manager,
+                  GAsyncResult       *result,
+                  GSimpleAsyncResult *operation_result)
 {
+  GoaIdentityService *self;
+  GDBusObjectManager *object_manager;
   char *object_path;
+  GoaObject *object;
   GError *error;
 
+  self = GOA_IDENTITY_SERVICE (g_async_result_get_source_object (G_ASYNC_RESULT (operation_result)));
   object_path = NULL;
+  object = NULL;
   error = NULL;
 
   if (!goa_manager_call_add_account_finish (manager,
@@ -644,37 +795,46 @@ on_account_created_for_identity (GoaManager         *manager,
                                             result,
                                             &error))
     {
-      goa_debug ("Could not create account for identity: %s", error->message);
-      g_error_free (error);
+      g_simple_async_result_take_error (operation_result, error);
+      g_simple_async_result_complete_in_idle (operation_result);
+      g_object_unref (operation_result);
       return;
     }
 
-  if (object_path != NULL)
+  if (object_path != NULL && object_path[0] != '\0')
     {
       goa_debug ("Created account for identity with object path %s", object_path);
+
+      object_manager = goa_client_get_object_manager (self->priv->client);
+      object = GOA_OBJECT (g_dbus_object_manager_get_object (object_manager,
+                                                             object_path));
       g_free (object_path);
     }
+
+  if (object == NULL)
+    g_simple_async_result_set_op_res_gpointer (operation_result, NULL, NULL);
+  else
+    g_simple_async_result_set_op_res_gpointer (operation_result,
+                                               object,
+                                               (GDestroyNotify)
+                                               g_object_unref);
+
+  g_simple_async_result_complete_in_idle (operation_result);
+  g_object_unref (operation_result);
 }
 
 static void
-add_temporary_account_if_necessary (GoaIdentityService *self,
-                                    GoaIdentity        *identity)
+add_temporary_account (GoaIdentityService *self,
+                       GoaIdentity        *identity)
 {
-  char            *realm;
-  const char      *principal;
-  const char      *principal_for_display;
-  GoaObject       *object;
-  GVariantBuilder  credentials;
-  GVariantBuilder  details;
+  char               *realm;
+  const char         *principal;
+  const char         *principal_for_display;
+  GSimpleAsyncResult *operation_result;
+  GVariantBuilder     credentials;
+  GVariantBuilder     details;
 
   principal = goa_identity_get_identifier (identity);
-  object = find_object_with_principal (self, principal);
-
-  if (object != NULL)
-    {
-      g_object_unref (object);
-      return;
-    }
 
   goa_debug ("GoaIdentityService: adding temporary identity %s", principal);
 
@@ -690,6 +850,16 @@ add_temporary_account_if_necessary (GoaIdentityService *self,
   g_variant_builder_init (&details, G_VARIANT_TYPE ("a{ss}"));
   g_variant_builder_add (&details, "{ss}", "Realm", realm);
   g_variant_builder_add (&details, "{ss}", "IsPermanent", "false");
+  g_variant_builder_add (&details, "{ss}", "TicketingEnabled", "true");
+
+
+  goa_debug ("GoaIdentityService: asking to sign back in");
+
+  operation_result = g_simple_async_result_new (G_OBJECT (self),
+                                                (GAsyncReadyCallback)
+                                                on_temporary_account_created_for_identity,
+                                                identity,
+                                                add_temporary_account);
 
   goa_manager_call_add_account (self->priv->accounts_manager,
                                 "kerberos",
@@ -699,8 +869,8 @@ add_temporary_account_if_necessary (GoaIdentityService *self,
                                 g_variant_builder_end (&details),
                                 NULL,
                                 (GAsyncReadyCallback)
-                                on_account_created_for_identity,
-                                self);
+                                on_account_added,
+                                operation_result);
   g_free (realm);
 }
 
@@ -709,8 +879,16 @@ on_identity_added (GoaIdentityManager *identity_manager,
                    GoaIdentity        *identity,
                    GoaIdentityService *self)
 {
+  GoaObject *object;
+  const char *identifier;
+
   export_identity (self, identity);
-  add_temporary_account_if_necessary (self, identity);
+
+  identifier = goa_identity_get_identifier (identity);
+  object = find_object_with_principal (self, identifier, FALSE);
+
+  if (object == NULL)
+    add_temporary_account (self, identity);
 }
 
 static void
@@ -726,7 +904,16 @@ on_identity_refreshed (GoaIdentityManager *identity_manager,
                        GoaIdentity        *identity,
                        GoaIdentityService *self)
 {
-  add_temporary_account_if_necessary (self, identity);
+  GoaObject *object;
+  const char *identifier;
+
+  identifier = goa_identity_get_identifier (identity);
+  object = find_object_with_principal (self, identifier, FALSE);
+
+  if (object == NULL)
+    add_temporary_account (self, identity);
+  else
+    ensure_account_credentials (self, object);
 }
 
 typedef struct
@@ -980,161 +1167,67 @@ on_identity_inquiry (GoaIdentityInquiry *inquiry,
   gcr_system_prompt_open_async (-1,
                                 cancellable,
                                 (GAsyncReadyCallback)
-                                on_system_prompt_open, request);
-}
-
-static void
-on_sign_in_clicked (NotifyNotification *notification,
-                    const char         *action_id,
-                    SignInRequest      *request)
-{
-  GoaIdentityService *self = request->service;
-  GoaIdentity *identity = request->identity;
-  const char *identifier;
-
-  identifier = goa_identity_get_identifier (identity);
-  goa_identity_manager_sign_identity_in (self->priv->identity_manager,
-                                         identifier,
-                                         request->initial_password,
-                                         request->flags,
-                                         (GoaIdentityInquiryFunc)
-                                         on_identity_inquiry,
-                                         self,
-                                         request->cancellable,
-                                         (GAsyncReadyCallback)
-                                         on_identity_signed_in,
-                                         request);
-}
-
-static void
-close_notification (GCancellable       *cancellable,
-                    NotifyNotification *notification)
-{
-  notify_notification_close (notification, NULL);
+                                on_system_prompt_open,
+                                request);
 }
 
 static void
 cancel_sign_in (GoaIdentityManager *identity_manager,
                 GoaIdentity        *identity,
-                SignInRequest      *data)
-{
-  g_cancellable_cancel (data->cancellable);
-  g_clear_object (&data->cancellable);
-}
-
-static void
-ask_to_sign_in (GoaIdentityService            *self,
-                GoaIdentity                   *identity,
-                gconstpointer                  initial_password,
-                GoaIdentitySignInFlags         flags,
-                GCancellable                  *cancellable,
-                GAsyncReadyCallback            callback,
-                gpointer                       user_data)
+                GSimpleAsyncResult *operation_result)
 {
-  NotifyNotification *notification;
-  char *name;
-  char *description;
-  GSimpleAsyncResult *result;
-  SignInRequest *request;
-
-  if (cancellable == NULL)
-    cancellable = g_cancellable_new ();
-
-  result = g_simple_async_result_new (G_OBJECT (self),
-                                      callback,
-                                      user_data,
-                                      ask_to_sign_in);
-  g_simple_async_result_set_check_cancellable (result, cancellable);
-
-  request = g_object_get_data (G_OBJECT (identity), "sign-in-request");
-
-  if (request != NULL)
-    g_cancellable_cancel (request->cancellable);
+  GoaIdentity *operation_identity;
 
-  goa_debug ("GoaIdentityService: asking to sign back in");
-
-  name = goa_identity_manager_name_identity (self->priv->identity_manager, identity);
-  if (goa_identity_is_signed_in (identity))
-    {
-      description =
-        g_strdup_printf (_("The network realm %s will soon be inaccessible."),
-                         name);
-    }
-  else
+  operation_identity = g_simple_async_result_get_source_tag (operation_result);
+  if (operation_identity == identity)
     {
-      description = g_strdup_printf (_("The network realm %s is now inaccessible."),
-                                     name);
-    }
-  g_free (name);
+      GCancellable *cancellable;
 
-  notification = notify_notification_new (_("Realm Access"),
-                                          description,
-                                          "dialog-password-symbolic");
-  g_free (description);
-  notify_notification_set_app_name (notification, _("Network Realm"));
-
-  request = sign_in_request_new (self,
-                                 identity,
-                                 initial_password,
-                                 flags,
-                                 notification,
-                                 result,
-                                 cancellable);
-
-  g_object_set_data (G_OBJECT (identity),
-                     "sign-in-request",
-                     request);
-
-  g_cancellable_connect (cancellable,
-                         G_CALLBACK (close_notification),
-                         notification,
-                         NULL);
-
-  request->refreshed_signal_id =
-    g_signal_connect (G_OBJECT (self->priv->identity_manager),
-                      "identity-refreshed",
-                      G_CALLBACK (cancel_sign_in),
-                      request);
-
-  notify_notification_add_action (notification,
-                                  "sign-in",
-                                  _("Sign In"),
-                                  (NotifyActionCallback)
-                                  on_sign_in_clicked,
-                                  request,
-                                  (GFreeFunc)
-                                  sign_in_request_free);
-
-  notify_notification_show (notification, NULL);
+      cancellable = g_object_get_data (G_OBJECT (operation_result),
+                                       "cancellable");
+      g_cancellable_cancel (cancellable);
+    }
 }
 
 static void
-on_credentials_ensured (GoaAccount         *account,
-                        GAsyncResult       *result,
-                        GoaIdentityService *self)
+sign_in (GoaIdentityService            *self,
+         const char                    *identifier,
+         gconstpointer                  initial_password,
+         GoaIdentitySignInFlags         flags,
+         GCancellable                  *cancellable,
+         GAsyncReadyCallback            callback,
+         gpointer                       user_data)
 {
-  GError     *error;
-  const char *account_identity;
-  int         expires_in;
+  GSimpleAsyncResult *operation_result;
 
-  account_identity = goa_account_get_identity (account);
+  goa_debug ("GoaIdentityService: asking to sign back in");
 
-  error = NULL;
-  if (!goa_account_call_ensure_credentials_finish (account,
-                                                   &expires_in,
-                                                   result,
-                                                   &error))
-    {
-      goa_debug ("GoaIdentityService: could not ensure credentials for account %s: %s",
-                 account_identity,
-                 error->message);
-      g_error_free (error);
-      return;
-    }
+  operation_result = g_simple_async_result_new (G_OBJECT (self),
+                                                callback,
+                                                user_data,
+                                                sign_in);
+  g_simple_async_result_set_check_cancellable (operation_result, cancellable);
+
+  g_object_set_data (G_OBJECT (operation_result),
+                     "cancellable",
+                     cancellable);
+  g_signal_connect_object (G_OBJECT (self->priv->identity_manager),
+                           "identity-refreshed",
+                           G_CALLBACK (cancel_sign_in),
+                           operation_result,
+                           0);
 
-  goa_debug ("GoaIdentityService: credentials for account %s ensured for %d seconds",
-             account_identity,
-             expires_in);
+  goa_identity_manager_sign_identity_in (self->priv->identity_manager,
+                                         identifier,
+                                         initial_password,
+                                         flags,
+                                         (GoaIdentityInquiryFunc)
+                                         on_identity_inquiry,
+                                         self,
+                                         cancellable,
+                                         (GAsyncReadyCallback)
+                                         on_identity_signed_in,
+                                         operation_result);
 }
 
 static void
@@ -1144,26 +1237,17 @@ on_identity_expiring (GoaIdentityManager *identity_manager,
 {
   const char *principal;
   GoaObject  *object;
-  GoaAccount *account;
 
   principal = goa_identity_get_identifier (identity);
 
   goa_debug ("GoaIdentityService: identity %s expiring", principal);
 
-  object = find_object_with_principal (self, principal);
+  object = find_object_with_principal (self, principal, TRUE);
 
   if (object == NULL)
     return;
 
-  if (should_ignore_object (self, object))
-    return;
-
-  account = goa_object_peek_account (object);
-  goa_account_call_ensure_credentials (account,
-                                       NULL,
-                                       (GAsyncReadyCallback)
-                                       on_credentials_ensured,
-                                       self);
+  ensure_account_credentials (self, object);
 }
 
 static void
@@ -1173,27 +1257,17 @@ on_identity_expired (GoaIdentityManager *identity_manager,
 {
   const char *principal;
   GoaObject  *object;
-  GoaAccount *account;
 
   principal = goa_identity_get_identifier (identity);
 
   goa_debug ("GoaIdentityService: identity %s expired", principal);
 
-  object = find_object_with_principal (self, principal);
+  object = find_object_with_principal (self, principal, TRUE);
 
   if (object == NULL)
     return;
 
-  if (should_ignore_object (self, object))
-    return;
-
-  account = goa_object_peek_account (object);
-
-  goa_account_call_ensure_credentials (account,
-                                       NULL,
-                                       (GAsyncReadyCallback)
-                                       on_credentials_ensured,
-                                       self);
+  ensure_account_credentials (self, object);
 }
 
 static void
@@ -1214,6 +1288,32 @@ on_sign_out_for_account_change_done (GoaIdentityService *self,
 }
 
 static void
+on_get_ticket (GoaTicketing       *ticketing,
+               GAsyncResult       *result,
+               GoaAccount         *account)
+{
+  GError     *error;
+  const char *account_identity;
+
+  account_identity = goa_account_get_identity (account);
+
+  error = NULL;
+  if (!goa_ticketing_call_get_ticket_finish (ticketing,
+                                             result,
+                                             &error))
+    {
+      goa_debug ("GoaIdentityService: could not get ticket for account %s: %s",
+                 account_identity,
+                 error->message);
+      g_error_free (error);
+      return;
+    }
+
+  goa_debug ("GoaIdentityService: got ticket for account %s",
+             account_identity);
+}
+
+static void
 on_account_interface_added (GDBusObjectManager *manager,
                             GoaObject          *object,
                             GDBusInterface     *interface,
@@ -1246,11 +1346,11 @@ on_account_interface_added (GDBusObjectManager *manager,
       /* Ticketing interface is present, sign in if not already
        * signed in.
        */
-      goa_account_call_ensure_credentials (account,
-                                           NULL,
-                                           (GAsyncReadyCallback)
-                                           on_credentials_ensured,
-                                           self);
+      goa_ticketing_call_get_ticket (ticketing,
+                                     NULL,
+                                     (GAsyncReadyCallback)
+                                     on_get_ticket,
+                                     account);
       return;
     }
 }
@@ -1355,7 +1455,6 @@ on_identities_listed (GoaIdentityManager *manager,
 {
   GError *error = NULL;
   GList *identities, *node;
-  GDBusObjectManager *object_manager;
 
   g_signal_connect (G_OBJECT (self->priv->identity_manager),
                     "identity-added",
@@ -1387,17 +1486,6 @@ on_identities_listed (GoaIdentityManager *manager,
                     G_CALLBACK (on_account_removed),
                     self);
 
-  object_manager = goa_client_get_object_manager (self->priv->client);
-
-  g_signal_connect (G_OBJECT (object_manager),
-                    "interface-added",
-                    G_CALLBACK (on_account_interface_added),
-                    self);
-  g_signal_connect (G_OBJECT (object_manager),
-                    "interface-removed",
-                    G_CALLBACK (on_account_interface_removed),
-                    self);
-
   identities = goa_identity_manager_list_identities_finish (manager, result, &error);
 
   if (identities == NULL)
@@ -1413,10 +1501,65 @@ on_identities_listed (GoaIdentityManager *manager,
   for (node = identities; node != NULL; node = node->next)
     {
       GoaIdentity *identity = node->data;
+      const char  *principal;
+      GoaObject   *object;
+
+      export_identity (self, identity);
 
-      add_temporary_account_if_necessary (self, identity);
+      principal = goa_identity_get_identifier (identity);
+      object = find_object_with_principal (self, principal, TRUE);
+
+      if (object == NULL)
+        add_temporary_account (self, identity);
+      else
+        g_object_unref (object);
     }
+}
+
+static void
+ensure_credentials_for_accounts (GoaIdentityService *self)
+{
+  GDBusObjectManager *object_manager;
+  GList      *accounts;
+  GList      *node;
+
+  object_manager = goa_client_get_object_manager (self->priv->client);
+
+  g_signal_connect (G_OBJECT (object_manager),
+                    "interface-added",
+                    G_CALLBACK (on_account_interface_added),
+                    self);
+  g_signal_connect (G_OBJECT (object_manager),
+                    "interface-removed",
+                    G_CALLBACK (on_account_interface_removed),
+                    self);
+
+  accounts = goa_client_get_accounts (self->priv->client);
+
+  for (node = accounts; node != NULL; node = node->next)
+    {
+      GoaObject *object = GOA_OBJECT (node->data);
+      GoaAccount *account;
+      GoaTicketing *ticketing;
+      const char *provider_type;
+
+      account = goa_object_peek_account (object);
 
+      if (account == NULL)
+        continue;
+
+      provider_type = goa_account_get_provider_type (account);
+
+      if (g_strcmp0 (provider_type, "kerberos") != 0)
+        continue;
+
+      ticketing = goa_object_peek_ticketing (object);
+
+      if (ticketing == NULL)
+        continue;
+
+      ensure_account_credentials (self, object);
+    }
 }
 
 static void
@@ -1451,6 +1594,8 @@ on_got_client (GoaClient          *client,
                                         (GAsyncReadyCallback)
                                         on_identities_listed,
                                         self);
+
+  ensure_credentials_for_accounts (self);
 }
 
 static void
@@ -1551,6 +1696,9 @@ goa_identity_service_class_init (GoaIdentityServiceClass *service_class)
 
   object_class->finalize = goa_identity_service_finalize;
 
+  goa_identity_utils_register_error_domain (GOA_IDENTITY_ERROR, GOA_TYPE_IDENTITY_ERROR);
+  goa_identity_utils_register_error_domain (GOA_IDENTITY_MANAGER_ERROR, GOA_TYPE_IDENTITY_MANAGER_ERROR);
+
   g_type_class_add_private (service_class, sizeof (GoaIdentityServicePrivate));
 }
 
diff --git a/src/goaidentity/goaidentityutils.c b/src/goaidentity/goaidentityutils.c
index 9cb8838..fb72916 100644
--- a/src/goaidentity/goaidentityutils.c
+++ b/src/goaidentity/goaidentityutils.c
@@ -32,8 +32,8 @@
 #include <gio/gio.h>
 
 char *
-goa_identity_utils_escape_object_path_component (const char *data,
-                                                 gsize       length)
+goa_identity_utils_escape_object_path (const char *data,
+                                       gsize       length)
 {
   const char *p;
   char *object_path;
diff --git a/src/goaidentity/goaidentityutils.h b/src/goaidentity/goaidentityutils.h
index 9c4cd25..6840431 100644
--- a/src/goaidentity/goaidentityutils.h
+++ b/src/goaidentity/goaidentityutils.h
@@ -29,8 +29,8 @@
 
 G_BEGIN_DECLS
 
-char *goa_identity_utils_escape_object_path_component (const char *data,
-                                                       gsize       length);
+char *goa_identity_utils_escape_object_path (const char *data,
+                                             gsize       length);
 void goa_identity_utils_register_error_domain (GQuark error_domain,
                                                GType  error_enum);
 
diff --git a/src/goaidentity/goakerberosidentity.c b/src/goaidentity/goakerberosidentity.c
index a66ff63..dc3e9aa 100644
--- a/src/goaidentity/goakerberosidentity.c
+++ b/src/goaidentity/goakerberosidentity.c
@@ -47,8 +47,6 @@ struct _GoaKerberosIdentityPrivate
   char *identifier;
   guint identifier_idle_id;
 
-  char **identifier_components;
-
   krb5_timestamp expiration_time;
   guint          expiration_time_idle_id;
 
@@ -297,57 +295,6 @@ get_identifier (GoaKerberosIdentity  *self,
   return identifier;
 }
 
-static char **
-get_identifier_components (GoaKerberosIdentity *self)
-{
-  krb5_principal principal;
-  krb5_error_code error_code;
-  int size, i;
-  GPtrArray *array;
-
-  if (self->priv->identifier == NULL)
-    return g_new0 (char *, 1);
-
-  error_code = krb5_parse_name (self->priv->kerberos_context,
-                                self->priv->identifier,
-                                &principal);
-
-  if (error_code != 0)
-    {
-      const char *error_message;
-      error_message =
-        krb5_get_error_message (self->priv->kerberos_context, error_code);
-
-      goa_debug ("GoaKerberosIdentity: Error looking up principal "
-               "identity in credential cache: %s",
-               error_message);
-      krb5_free_error_message (self->priv->kerberos_context, error_message);
-      return g_new0 (char *, 1);
-    }
-
-  array = g_ptr_array_new ();
-
-  g_ptr_array_add (array,
-                   g_strndup (principal->realm.data, principal->realm.length));
-
-  size = krb5_princ_size (self->priv->kerberos_context, principal);
-
-  for (i = 0; i < size; i++)
-    {
-      krb5_data *component;
-      char *component_string;
-
-      component = krb5_princ_component (self->priv->kerberos_context, principal, i);
-
-      component_string = g_strndup (component->data, component->length);
-      g_ptr_array_add (array, component_string);
-
-    }
-  g_ptr_array_add (array, NULL);
-
-  return (char **) g_ptr_array_free (array, FALSE);
-}
-
 static void
 goa_kerberos_identity_init (GoaKerberosIdentity *self)
 {
@@ -478,14 +425,6 @@ goa_kerberos_identity_get_identifier (GoaIdentity *identity)
   return self->priv->identifier;
 }
 
-static char **
-goa_kerberos_identity_get_identifier_components (GoaIdentity *identity)
-{
-  GoaKerberosIdentity *self = GOA_KERBEROS_IDENTITY (identity);
-
-  return g_strdupv (self->priv->identifier_components);
-}
-
 static gboolean
 credentials_validate_existence (GoaKerberosIdentity *self,
                                 krb5_principal principal, krb5_creds * credentials)
@@ -750,7 +689,6 @@ static void
 identity_interface_init (GoaIdentityInterface *interface)
 {
   interface->get_identifier = goa_kerberos_identity_get_identifier;
-  interface->get_identifier_components = goa_kerberos_identity_get_identifier_components;
   interface->is_signed_in = goa_kerberos_identity_is_signed_in;
 }
 
@@ -982,9 +920,6 @@ goa_kerberos_identity_initable_init (GInitable     *initable,
         queue_notify (self, &self->priv->identifier_idle_id, "identifier");
     }
 
-  if (self->priv->identifier_components == NULL)
-    self->priv->identifier_components = get_identifier_components (self);
-
   verification_error = NULL;
   self->priv->cached_verification_level =
     verify_identity (self, &verification_error);
@@ -1053,10 +988,11 @@ on_kerberos_inquiry (krb5_context      kerberos_context,
                            operation->cancellable,
                            operation->inquiry_data);
 
+  if (!goa_identity_inquiry_is_complete (inquiry))
+    g_cancellable_cancel (operation->cancellable);
+
   if (g_cancellable_is_cancelled (operation->cancellable))
     error_code = KRB5_LIBOS_PWDINTR;
-  else if (!goa_identity_inquiry_is_complete (inquiry))
-    error_code = KRB5_LIBOS_PWDINTR;
   else
     error_code = 0;
 
@@ -1113,10 +1049,11 @@ out:
 }
 
 static SignInOperation *
-sign_in_operation_new (GoaKerberosIdentity *identity,
-                       GoaIdentityInquiryFunc inquiry_func,
-                       gpointer inquiry_data,
-                       GDestroyNotify destroy_notify, GCancellable *cancellable)
+sign_in_operation_new (GoaKerberosIdentity    *identity,
+                       GoaIdentityInquiryFunc  inquiry_func,
+                       gpointer                inquiry_data,
+                       GDestroyNotify          destroy_notify,
+                       GCancellable           *cancellable)
 {
   SignInOperation *operation;
 
@@ -1144,14 +1081,15 @@ sign_in_operation_free (SignInOperation *operation)
 }
 
 gboolean
-goa_kerberos_identity_sign_in (GoaKerberosIdentity *self,
-                               const char *principal_name,
-                               gconstpointer initial_password,
-                               GoaIdentitySignInFlags flags,
-                               GoaIdentityInquiryFunc inquiry_func,
-                               gpointer inquiry_data,
-                               GDestroyNotify destroy_notify,
-                               GCancellable *cancellable, GError **error)
+goa_kerberos_identity_sign_in (GoaKerberosIdentity     *self,
+                               const char              *principal_name,
+                               gconstpointer            initial_password,
+                               GoaIdentitySignInFlags   flags,
+                               GoaIdentityInquiryFunc   inquiry_func,
+                               gpointer                 inquiry_data,
+                               GDestroyNotify           destroy_notify,
+                               GCancellable            *cancellable,
+                               GError                 **error)
 {
   SignInOperation *operation;
   krb5_principal principal;
@@ -1163,9 +1101,7 @@ goa_kerberos_identity_sign_in (GoaKerberosIdentity *self,
   gboolean signed_in;
 
   if (g_cancellable_set_error_if_cancelled (cancellable, error))
-    {
-      return FALSE;
-    }
+    return FALSE;
 
   error_code = krb5_get_init_creds_opt_alloc (self->priv->kerberos_context,
                                               &options);
@@ -1176,9 +1112,7 @@ goa_kerberos_identity_sign_in (GoaKerberosIdentity *self,
                                       GOA_IDENTITY_ERROR_ALLOCATING_CREDENTIALS,
                                       error_code, "%k");
       if (destroy_notify)
-        {
-          destroy_notify (inquiry_data);
-        }
+        destroy_notify (inquiry_data);
       return FALSE;
     }
 
@@ -1197,14 +1131,16 @@ goa_kerberos_identity_sign_in (GoaKerberosIdentity *self,
     }
 
   error_code = krb5_parse_name (self->priv->kerberos_context,
-                                principal_name, &principal);
+                                principal_name,
+                                &principal);
 
   if (error_code != 0)
     {
       set_error_from_krb5_error_code (self,
                                       error,
                                       GOA_IDENTITY_ERROR_PARSING_IDENTIFIER,
-                                      error_code, "%k");
+                                      error_code,
+                                      "%k");
       if (destroy_notify)
         destroy_notify (inquiry_data);
       return FALSE;
@@ -1232,12 +1168,27 @@ goa_kerberos_identity_sign_in (GoaKerberosIdentity *self,
                                              start_time,
                                              service_name,
                                              options);
+
+  if (error_code == KRB5_LIBOS_PWDINTR)
+    g_cancellable_cancel (operation->cancellable);
+
+  if (g_cancellable_set_error_if_cancelled (cancellable, error))
+    {
+      if (destroy_notify)
+        destroy_notify (inquiry_data);
+      sign_in_operation_free (operation);
+
+      krb5_free_principal (self->priv->kerberos_context, principal);
+      goto done;
+    }
+
   if (error_code != 0)
     {
       set_error_from_krb5_error_code (self,
                                       error,
                                       GOA_IDENTITY_ERROR_AUTHENTICATION_FAILED,
-                                      error_code, "%k");
+                                      error_code,
+                                      "%k");
       if (destroy_notify)
         destroy_notify (inquiry_data);
       sign_in_operation_free (operation);
@@ -1251,7 +1202,9 @@ goa_kerberos_identity_sign_in (GoaKerberosIdentity *self,
   sign_in_operation_free (operation);
 
   if (!goa_kerberos_identity_update_credentials (self,
-                                                 principal, &new_credentials, error))
+                                                 principal,
+                                                 &new_credentials,
+                                                 error))
     {
       krb5_free_principal (self->priv->kerberos_context, principal);
       goto done;
@@ -1283,38 +1236,6 @@ update_identifier (GoaKerberosIdentity *self, GoaKerberosIdentity *new_identity)
     }
 }
 
-static void
-update_identifier_components (GoaKerberosIdentity *self,
-                              GoaKerberosIdentity *new_identity)
-{
-  char **new_components;
-
-  new_components = get_identifier_components (self);
-
-  if (g_strv_length (self->priv->identifier_components) ==
-      g_strv_length (new_components))
-    {
-      int i;
-
-      for (i = 0; new_components[i] != NULL; i++)
-        {
-          if (g_strcmp0 (self->priv->identifier_components[i],
-                         new_components[i]) != 0)
-            {
-              break;
-            }
-          else
-            {
-              g_strfreev (new_components);
-              return;
-            }
-        }
-    }
-
-  g_strfreev (self->priv->identifier_components);
-  self->priv->identifier_components = new_components;
-}
-
 void
 goa_kerberos_identity_update (GoaKerberosIdentity *self,
                               GoaKerberosIdentity *new_identity)
@@ -1322,9 +1243,7 @@ goa_kerberos_identity_update (GoaKerberosIdentity *self,
   VerificationLevel verification_level;
 
   if (self->priv->credentials_cache != NULL)
-    {
-      krb5_cc_close (self->priv->kerberos_context, self->priv->credentials_cache);
-    }
+    krb5_cc_close (self->priv->kerberos_context, self->priv->credentials_cache);
 
   krb5_cc_dup (new_identity->priv->kerberos_context,
                new_identity->priv->credentials_cache,
@@ -1332,19 +1251,14 @@ goa_kerberos_identity_update (GoaKerberosIdentity *self,
 
   G_LOCK (identity_lock);
   update_identifier (self, new_identity);
-  update_identifier_components (self, new_identity);
   G_UNLOCK (identity_lock);
 
   verification_level = verify_identity (self, NULL);
 
   if (verification_level == VERIFICATION_LEVEL_SIGNED_IN)
-    {
-      reset_alarms (self);
-    }
+    reset_alarms (self);
   else
-    {
-      clear_alarms (self);
-    }
+    clear_alarms (self);
 
   if (verification_level != self->priv->cached_verification_level)
     {
@@ -1358,8 +1272,8 @@ goa_kerberos_identity_update (GoaKerberosIdentity *self,
 
           g_signal_emit (G_OBJECT (self), signals[EXPIRED], 0);
         }
-      if (self->priv->cached_verification_level == VERIFICATION_LEVEL_EXISTS &&
-          verification_level == VERIFICATION_LEVEL_SIGNED_IN)
+      else if (self->priv->cached_verification_level == VERIFICATION_LEVEL_EXISTS &&
+               verification_level == VERIFICATION_LEVEL_SIGNED_IN)
         {
 
           G_LOCK (identity_lock);
@@ -1368,6 +1282,12 @@ goa_kerberos_identity_update (GoaKerberosIdentity *self,
 
           g_signal_emit (G_OBJECT (self), signals[UNEXPIRED], 0);
         }
+      else
+        {
+          G_LOCK (identity_lock);
+          self->priv->cached_verification_level = verification_level;
+          G_UNLOCK (identity_lock);
+        }
       queue_notify (self, &self->priv->is_signed_in_idle_id, "is-signed-in");
     }
 }
@@ -1422,7 +1342,9 @@ goa_kerberos_identity_renew (GoaKerberosIdentity *self, GError **error)
     }
 
   if (!goa_kerberos_identity_update_credentials (self,
-                                                 principal, &new_credentials, error))
+                                                 principal,
+                                                 &new_credentials,
+                                                 error))
     {
       krb5_free_principal (self->priv->kerberos_context, principal);
       goto out;
diff --git a/src/goaidentity/goakerberosidentitymanager.c b/src/goaidentity/goakerberosidentitymanager.c
index b9eeac9..ed27a9a 100644
--- a/src/goaidentity/goakerberosidentitymanager.c
+++ b/src/goaidentity/goakerberosidentitymanager.c
@@ -823,6 +823,15 @@ sign_in_identity (GoaKerberosIdentityManager *self,
                                       operation->cancellable,
                                       &error))
     {
+      if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+        {
+          g_clear_error (&error);
+          g_set_error_literal (&error,
+                               GOA_IDENTITY_ERROR,
+                               GOA_IDENTITY_ERROR_USER_CANCELLED,
+                               _("User cancelled"));
+        }
+
       g_simple_async_result_set_from_error (operation->result, error);
       g_simple_async_result_set_op_res_gpointer (operation->result,
                                                  NULL,
@@ -1127,7 +1136,7 @@ goa_kerberos_identity_manager_renew_identity_finish (GoaIdentityManager  *self,
 static void
 goa_kerberos_identity_manager_sign_identity_in (GoaIdentityManager     *manager,
                                                 const char             *identifier,
-                                                gconstpointer          *initial_password,
+                                                gconstpointer           initial_password,
                                                 GoaIdentitySignInFlags  flags,
                                                 GoaIdentityInquiryFunc  inquiry_func,
                                                 gpointer                inquiry_data,
diff --git a/src/goaidentity/org.gnome.Identity.xml b/src/goaidentity/org.gnome.Identity.xml
index 0bf6394..ac6b66e 100644
--- a/src/goaidentity/org.gnome.Identity.xml
+++ b/src/goaidentity/org.gnome.Identity.xml
@@ -31,6 +31,11 @@
   -->
   <interface name="org.gnome.Identity.Manager">
 
+    <method name="ExchangeSecretKeys">
+      <arg name="input_key" type="s" direction="in"/>
+      <arg name="output_key" type="s" direction="out"/>
+    </method>
+
     <!--
         SignIn:
         @identity: The identifier of the identity (i.e., a kerberos principal name)
@@ -45,6 +50,12 @@
       <arg name="identity_object_path" type="o" direction="out"/>
     </method>
 
+    <!--
+        SignOut:
+        @identity: The identifier of the identity (i.e., a kerberos principal name)
+
+        Signs out an identity.
+    -->
     <method name="SignOut">
       <arg name="identity" type="s" direction="in"/>
     </method>
@@ -68,6 +79,12 @@
     -->
     <property name="ExpirationTimestamp" type="x" access="read"/>
 
+    <!--
+        IsSignedIn:
+        Whether or not the identity is currently signed in
+    -->
+    <property name="IsSignedIn" type="b" access="read"/>
+
   </interface>
 
 </node>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]