Refresh upstream 2.1.0 release
[profile/ivi/libgsignon-glib.git] / libgsignon-glib / signon-identity.c
1 /* vi: set et sw=4 ts=4 cino=t0,(0: */
2 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 /*
4  * This file is part of libgsignon-glib
5  *
6  * Copyright (C) 2009-2010 Nokia Corporation.
7  * Copyright (C) 2012 Canonical Ltd.
8  * Copyright (C) 2012-2014 Intel Corporation.
9  *
10  * Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
11  * Contact: Jussi Laako <jussi.laako@linux.intel.com>
12  *
13  * This library is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU Lesser General Public License
15  * version 2.1 as published by the Free Software Foundation.
16  *
17  * This library is distributed in the hope that it will be useful, but
18  * WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with this library; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
25  * 02110-1301 USA
26  */
27
28 /**
29  * SECTION:signon-identity
30  * @title: SignonIdentity
31  * @short_description: client side presentation of a credential.
32  *
33  * The #SignonIdentity objects represent identities and provide operations that 
34  * can be performed on them such as identity creation, removal, starting an authentication 
35  * session, and so on. 
36  * 
37  * Identities can also be stored and retrieved from a gSSO database, in which
38  * case they also contain a number of properties that can be retrieved
39  * using signon_identity_query_info() and are represented via #SignonIdentityInfo.
40  * Such identities are identified by a numeric id number and they are subject
41  * to access control.
42  * 
43  * <refsect1><title>Operations on an identity</title></refsect1>
44  * 
45  * - a new identity can be created with signon_identity_new() or
46  * signon_identity_new_with_context(). This operation does not store the
47  * identity to the database, the identity is not visible to other applications,
48  * and accordingly it is not subject to access control.
49  * 
50  * - an authentication session can be started from an identity using 
51  * signon_identity_create_session() or signon_auth_session_new(). If the identity
52  * has been retrieved from a database, only the authentication methods listed
53  * in associated #SignonIdentityInfo are allowed to be used.
54  * 
55  * - identites stored in a database can be enumerated using 
56  * signon_auth_service_query_identities(). Only the identites owned by the 
57  * requesting application are returned.
58  * 
59  * - identities stored in a database can be retrieved using signon_identity_new_from_db()
60  * or signon_identity_new_with_context_from_db(), subject to access control (an
61  * application performing that operation has to be either the identity's owner,
62  * or it has to be on the ACL list).
63  * 
64  * - newly created identities can be stored to the database, and identities already
65  * in the database can be updated using signon_identity_store_credentials_with_info()
66  * (with #SignonIdentityInfo)
67  * or signon_identity_store_credentials_with_args() (with separate arguments that
68  * together form the contents of #SignonIdentityInfo). Only the owners can update
69  * identites.
70  * 
71  * - identites in the database can be removed by their owners using
72  * signon_identity_remove().
73  * 
74  * - identity owners can request to close all authentication sessions and
75  * remove all secrets and tokens using signon_identity_signout().
76  * 
77  * <refsect1><title>Data fields in #SignonIdentityInfo</title></refsect1>
78  * 
79  * These are the data fields that are stored into the database as a part of an
80  * identity record using signon_identity_store_credentials_with_args() or
81  * signon_identity_store_credentials_with_info() and can be retrieved using
82  * signon_identity_query_info() or signon_auth_service_query_identities():
83  * 
84  * - Caption is a display name for the identity, presented to the user. Default
85  * value is an empty caption. 
86  *
87  * - Realms is a list of realms that the identity can be used in.
88  *   Interpretation of this field is up to the method. Typically it is
89  *   a list of internet domains allowed for an authentication request.
90  *   Default value is an empty list.
91  * 
92  * - Type is a #SignonIdentityType. Interpretation of this field is up to the application;
93  * gSSO does not use it. Default value is #SIGNON_IDENTITY_TYPE_OTHER
94  * 
95  * - Owner is a #SignonSecurityContext object, which specifies the identity
96  * owner. Owners are allowed to perform all of the operations on the identity
97  * specified above. By default an identity's owner is determined by gSSO daemon
98  * using system services for the system context, and a string supplied in 
99  * signon_identity_new_with_context() for the application context.
100  * 
101  * - ACL is a list of #SignonSecurityContext objects, that specifies applications
102  * that can access the identity to perform authentication sessions. They're not
103  * allowed to make any changes to the identity. Default value is an empty list,
104  * and depending on how gSSO is configured it's also possible to provide a list 
105  * with a wildcard item to relax the access control restriction 
106  * (see #SignonSecurityContext).
107  * 
108  * - Methods is a #GHashTable containing method names as keys, and lists of 
109  * allowed mechanisms as values (also, a special value "*" means that any 
110  * mechanism is allowed). Only those methods and mechanisms that are in the table
111  * are allowed to be used in authentication sessions. Default is an empty list.
112  * 
113  * - Id is a numeric identification of the identity record in the database. The
114  * application cannot set this, as it's determined by the daemon.
115  * 
116  * - Username is used to provide a username to authentication plugins after 
117  * issuing signon_auth_session_process_async(). Applications can override this
118  * by providing a username explicitly in the @session_data parameter to that 
119  * function. By default there is no username.
120  * 
121  * - Secret is used in the same way as username, but it is write-only (cannot
122  * be retrieved from a #SignonIdentityInfo). It is also possible to prevent
123  * secret from being stored in the database.
124  * 
125  */
126
127 #include "signon-identity.h"
128 #include "signon-auth-session.h"
129 #include "signon-internals.h"
130 #include "signon-dbus-queue.h"
131 #include "signon-utils.h"
132 #include "signon-errors.h"
133 #include "sso-auth-service.h"
134 #include "sso-identity-gen.h"
135
136 G_DEFINE_TYPE (SignonIdentity, signon_identity, G_TYPE_OBJECT);
137
138 enum
139 {
140     PROP_0,
141     PROP_ID,
142     PROP_APPCTX
143 };
144
145 typedef enum {
146     NOT_REGISTERED,
147     PENDING_REGISTRATION,
148     REGISTERED,
149 } IdentityRegistrationState;
150
151 typedef enum  {
152     DATA_UPDATED = 0,
153     IDENTITY_REMOVED,
154     IDENTITY_SIGNED_OUT
155 } RemoteIdentityState;
156
157 struct _SignonIdentityPrivate
158 {
159     SsoIdentity *proxy;
160     SsoAuthService *auth_service_proxy;
161     GCancellable *cancellable;
162
163     SignonIdentityInfo *identity_info;
164
165     GSList *sessions;
166     IdentityRegistrationState registration_state;
167
168     gboolean removed;
169     gboolean signed_out;
170     gboolean updated;
171
172     guint id;
173     gchar *app_ctx;
174
175     guint signal_info_updated;
176     guint signal_unregistered;
177 };
178
179 enum {
180     SIGNEDOUT_SIGNAL,
181     LAST_SIGNAL
182 };
183
184 static guint signals[LAST_SIGNAL];
185
186 #define SIGNON_IDENTITY_PRIV(obj) (SIGNON_IDENTITY(obj)->priv)
187
188 typedef struct _IdentityStoreCredentialsCbData
189 {
190     SignonIdentity *self;
191     SignonIdentityStoreCredentialsCb cb;
192     gpointer user_data;
193 } IdentityStoreCredentialsCbData;
194
195 typedef struct _IdentityStoreCredentialsData
196 {
197     GVariant *info_variant;
198     gpointer cb_data;
199 } IdentityStoreCredentialsData;
200
201 typedef enum {
202     SIGNON_VERIFY_USER,
203     SIGNON_VERIFY_SECRET,
204     SIGNON_INFO,
205     SIGNON_REMOVE,
206     SIGNON_SIGNOUT
207 } IdentityOperation;
208
209 typedef struct _IdentitySessionCbData
210 {
211     SignonIdentity *self;
212     SignonAuthSession *session;
213     SignonIdentitySessionReadyCb cb;
214 } IdentitySessionCbData;
215
216 typedef struct _IdentitySessionData
217 {
218     const gchar *method;
219     gpointer cb_data;
220 } IdentitySessionData;
221
222 typedef struct _IdentityVerifyCbData
223 {
224     SignonIdentity *self;
225     SignonIdentityVerifyCb cb;
226     gpointer user_data;
227 } IdentityVerifyCbData;
228
229 typedef struct _IdentityVerifyData
230 {
231     gchar *data_to_send;
232     GHashTable *params;
233     IdentityOperation operation;
234     gpointer cb_data;
235 } IdentityVerifyData;
236
237 typedef struct _IdentityInfoCbData
238 {
239     SignonIdentity *self;
240     SignonIdentityInfoCb cb;
241     gpointer user_data;
242 } IdentityInfoCbData;
243
244 typedef struct _IdentityVoidCbData
245 {
246     SignonIdentity *self;
247     SignonIdentityVoidCb cb;
248     gpointer user_data;
249 } IdentityVoidCbData;
250
251 typedef struct _IdentityVoidData
252 {
253     IdentityOperation operation;
254     gpointer cb_data;
255 } IdentityVoidData;
256
257 static void identity_check_remote_registration (SignonIdentity *self);
258 static void identity_store_credentials_ready_cb (gpointer object, const GError *error, gpointer user_data);
259 static void identity_store_credentials_reply (GObject *object,
260                                               GAsyncResult *res,
261                                               gpointer userdata);
262 static void identity_verify_data (SignonIdentity *self, const gchar *data_to_send, gint operation,
263                                     SignonIdentityVerifyCb cb, gpointer user_data);
264 static void identity_verify_ready_cb (gpointer object, const GError *error, gpointer user_data);
265
266 static void identity_remove_ready_cb (gpointer object, const GError *error, gpointer user_data);
267 static void identity_signout_ready_cb (gpointer object, const GError *error, gpointer user_data);
268 static void identity_info_ready_cb (gpointer object, const GError *error, gpointer user_data);
269
270 static void identity_process_signout (SignonIdentity *self);
271 static void identity_process_updated (SignonIdentity *self);
272 static void identity_process_removed (SignonIdentity *self);
273 static void identity_get_auth_session_reply (GObject *object,
274                                              GAsyncResult *res,
275                                              gpointer userdata);
276 static void identity_session_ready_cb (gpointer object, const GError *error,
277                                        gpointer user_data);
278 static void identity_session_object_destroyed_cb (gpointer data,
279                                                   GObject *where_the_session_was);
280
281 static GQuark
282 identity_object_quark ()
283 {
284   static GQuark quark = 0;
285
286   if (!quark)
287     quark = g_quark_from_static_string ("identity_object_quark");
288
289   return quark;
290 }
291
292 static void
293 signon_identity_set_property (GObject *object,
294                               guint property_id,
295                               const GValue *value,
296                               GParamSpec *pspec)
297 {
298     SignonIdentity *self = SIGNON_IDENTITY (object);
299
300     switch (property_id)
301     {
302     case PROP_ID:
303         self->priv->id = g_value_get_uint (value);
304         break;
305     case PROP_APPCTX:
306         g_free (self->priv->app_ctx);
307         self->priv->app_ctx = g_strdup (g_value_get_string (value));
308         break;
309     default:
310         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
311         break;
312     }
313 }
314
315 static void
316 signon_identity_get_property (GObject *object,
317                               guint property_id,
318                               GValue *value,
319                               GParamSpec *pspec)
320 {
321     SignonIdentity *self = SIGNON_IDENTITY (object);
322
323     switch (property_id)
324     {
325     case PROP_ID:
326         g_value_set_uint (value, self->priv->id);
327         break;
328     case PROP_APPCTX:
329         g_value_set_string (value, self->priv->app_ctx);
330         break;
331     default:
332         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
333         break;
334     }
335 }
336
337 static void
338 signon_identity_init (SignonIdentity *identity)
339 {
340     SignonIdentityPrivate *priv;
341
342     identity->priv = G_TYPE_INSTANCE_GET_PRIVATE (identity,
343                                                   SIGNON_TYPE_IDENTITY,
344                                                   SignonIdentityPrivate);
345
346     priv = identity->priv;
347     priv->proxy = NULL;
348     priv->auth_service_proxy = sso_auth_service_get_instance();
349     priv->cancellable = g_cancellable_new ();
350     priv->registration_state = NOT_REGISTERED;
351
352     priv->removed = FALSE;
353     priv->signed_out = FALSE;
354     priv->updated = FALSE;
355
356     priv->app_ctx = NULL;
357 }
358
359 static void
360 signon_identity_dispose (GObject *object)
361 {
362     SignonIdentity *identity = SIGNON_IDENTITY (object);
363     SignonIdentityPrivate *priv = identity->priv;
364
365     if (priv->cancellable)
366     {
367         g_cancellable_cancel (priv->cancellable);
368         g_object_unref (priv->cancellable);
369         priv->cancellable = NULL;
370     }
371
372     if (priv->identity_info)
373     {
374         signon_identity_info_free (priv->identity_info);
375         priv->identity_info = NULL;
376     }
377
378     g_clear_object (&priv->auth_service_proxy);
379
380     if (priv->proxy)
381     {
382         g_signal_handler_disconnect (priv->proxy, priv->signal_info_updated);
383         g_signal_handler_disconnect (priv->proxy, priv->signal_unregistered);
384         g_object_unref (priv->proxy);
385         priv->proxy = NULL;
386     }
387
388     if (priv->sessions)
389         g_critical ("SignonIdentity: the list of AuthSessions MUST be empty");
390
391     G_OBJECT_CLASS (signon_identity_parent_class)->dispose (object);
392 }
393
394 static void
395 signon_identity_finalize (GObject *object)
396 {
397     SignonIdentity *identity = SIGNON_IDENTITY (object);
398     if (identity->priv->app_ctx)
399     {
400         g_free(identity->priv->app_ctx);
401         identity->priv->app_ctx = NULL;
402     }
403
404     G_OBJECT_CLASS (signon_identity_parent_class)->finalize (object);
405 }
406
407 static void
408 signon_identity_class_init (SignonIdentityClass *klass)
409 {
410     GObjectClass *object_class = G_OBJECT_CLASS (klass);
411     GParamSpec *pspec;
412
413     object_class->set_property = signon_identity_set_property;
414     object_class->get_property = signon_identity_get_property;
415
416     pspec = g_param_spec_uint ("id",
417                                "Identity ID",
418                                "Set/Get Identity ID",
419                                0,
420                                G_MAXUINT,
421                                0,
422                                G_PARAM_READWRITE);
423     g_object_class_install_property (object_class,
424                                      PROP_ID,
425                                      pspec);
426
427     pspec = g_param_spec_string ("app_ctx",
428                                  "Application Context",
429                                  "Set/Get Application Security Context",
430                                  "",
431                                  G_PARAM_READWRITE);
432     g_object_class_install_property (object_class,
433                                      PROP_APPCTX,
434                                      pspec);
435
436     g_type_class_add_private (object_class, sizeof (SignonIdentityPrivate));
437
438     /**
439      * SignonIdentity::signout:
440      *
441      * Emitted when the identity was signed out.
442      */
443     signals[SIGNEDOUT_SIGNAL] = g_signal_new("signout",
444                                     G_TYPE_FROM_CLASS (klass),
445                                     G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
446                                     0 /* class closure */,
447                                     NULL /* accumulator */,
448                                     NULL /* accu_data */,
449                                     g_cclosure_marshal_VOID__VOID,
450                                     G_TYPE_NONE /* return_type */,
451                                     0);
452
453     object_class->dispose = signon_identity_dispose;
454     object_class->finalize = signon_identity_finalize;
455 }
456
457 static void
458 identity_state_changed_cb (GDBusProxy *proxy,
459                            gint state,
460                            gpointer user_data)
461 {
462     g_return_if_fail (SIGNON_IS_IDENTITY (user_data));
463     SignonIdentity *self = SIGNON_IDENTITY (user_data);
464
465     switch (state) {
466         case DATA_UPDATED:
467             DEBUG ("State changed to DATA_UPDATED");
468             identity_process_updated (self);
469             break;
470         case IDENTITY_REMOVED:
471             DEBUG ("State changed to IDENTITY_REMOVED");
472             identity_process_removed (self);
473             break;
474         case IDENTITY_SIGNED_OUT:
475             DEBUG ("State changed to IDENTITY_SIGNED_OUT");
476             identity_process_signout (self);
477             break;
478         default:
479             g_critical ("wrong state value obtained from signon daemon");
480     };
481 }
482
483 static void
484 identity_remote_object_destroyed_cb(GDBusProxy *proxy,
485                                     gpointer user_data)
486 {
487     g_return_if_fail (SIGNON_IS_IDENTITY (user_data));
488     SignonIdentity *self = SIGNON_IDENTITY (user_data);
489
490     SignonIdentityPrivate *priv = self->priv;
491     g_return_if_fail (priv != NULL);
492
493     if (priv->proxy)
494     {
495         g_object_unref (priv->proxy);
496         priv->proxy = NULL;
497     }
498
499     DEBUG ("%s %d", G_STRFUNC, __LINE__);
500
501     _signon_object_not_ready(self);
502
503     priv->registration_state = NOT_REGISTERED;
504
505     signon_identity_info_free (priv->identity_info);
506     priv->identity_info = NULL;
507
508     priv->removed = FALSE;
509     priv->signed_out = FALSE;
510     priv->updated = FALSE;
511 }
512
513 static void
514 identity_registered (SignonIdentity *identity,
515                      char *object_path, GVariant *identity_data,
516                      GError *error)
517 {
518     g_return_if_fail (SIGNON_IS_IDENTITY (identity));
519
520     SignonIdentityPrivate *priv;
521     priv = identity->priv;
522
523     g_return_if_fail (priv != NULL);
524
525     if (!error)
526     {
527         GDBusConnection *connection;
528         GDBusProxy *auth_service_proxy;
529         const gchar *bus_name;
530         GError *proxy_error = NULL;
531
532         DEBUG("%s: %s", G_STRFUNC, object_path);
533         /*
534          * TODO: as Aurel will finalize the code polishing so we will
535          * need to implement the refresh of the proxy to SignonIdentity
536          * */
537         g_return_if_fail (priv->proxy == NULL);
538
539         auth_service_proxy = (GDBusProxy *)priv->auth_service_proxy;
540         connection = g_dbus_proxy_get_connection (auth_service_proxy);
541         bus_name = g_dbus_proxy_get_name (auth_service_proxy);
542
543         priv->proxy =
544             sso_identity_proxy_new_sync (connection,
545                                          G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
546                                          bus_name,
547                                          object_path,
548                                          priv->cancellable,
549                                          &proxy_error);
550         if (G_UNLIKELY (proxy_error != NULL))
551         {
552             g_warning ("Failed to initialize Identity proxy: %s",
553                        proxy_error->message);
554             g_clear_error (&proxy_error);
555         }
556
557         priv->signal_info_updated =
558             g_signal_connect (priv->proxy,
559                               "info-updated",
560                               G_CALLBACK (identity_state_changed_cb),
561                               identity);
562
563         priv->signal_unregistered =
564             g_signal_connect (priv->proxy,
565                               "unregistered",
566                               G_CALLBACK (identity_remote_object_destroyed_cb),
567                               identity);
568
569         if (identity_data)
570         {
571             DEBUG("%s: ", G_STRFUNC);
572             priv->identity_info =
573                 signon_identity_info_new_from_variant (identity_data);
574             g_variant_unref (identity_data);
575         }
576
577         priv->updated = TRUE;
578     }
579     else
580         g_warning ("%s: %s", G_STRFUNC, error->message);
581
582     /*
583      * execute queued operations or emit errors on each of them
584      * */
585     priv->registration_state = REGISTERED;
586
587     /*
588      * TODO: if we will add a new state for identity: "INVALID"
589      * consider emission of another error, like "invalid"
590      * */
591     _signon_object_ready (identity, identity_object_quark (), error);
592
593     /*
594      * as the registration failed we do not
595      * request for new registration, but emit
596      * same error again and again
597      * */
598 }
599
600 /**
601  * signon_identity_get_last_error:
602  * @identity: the #SignonIdentity.
603  *
604  * Get the most recent error that occurred on @identity.
605  *
606  * Returns: a #GError containing the most recent error, or %NULL on failure.
607  */
608 const GError *
609 signon_identity_get_last_error (SignonIdentity *identity)
610 {
611     g_return_val_if_fail (SIGNON_IS_IDENTITY (identity), NULL);
612     return _signon_object_last_error(identity);
613 }
614
615 static void
616 identity_new_cb (GObject *object, GAsyncResult *res,
617                  gpointer userdata)
618 {
619     SignonIdentity *identity = (SignonIdentity*)userdata;
620     SsoAuthService *proxy = SSO_AUTH_SERVICE (object);
621     gchar *object_path = NULL;
622     GError *error = NULL;
623
624     g_return_if_fail (identity != NULL);
625     DEBUG ("%s", G_STRFUNC);
626
627     sso_auth_service_call_register_new_identity_finish (proxy,
628                                                         &object_path,
629                                                         res,
630                                                         &error);
631     if (SIGNON_IS_NOT_CANCELLED (error))
632     {
633         identity_registered (identity, object_path, NULL, error);
634     }
635     if (object_path) g_free (object_path);
636     g_clear_error (&error);
637 }
638
639 static void
640 identity_new_from_db_cb (GObject *object, GAsyncResult *res,
641                          gpointer userdata)
642 {
643     SignonIdentity *identity = (SignonIdentity*)userdata;
644     SsoAuthService *proxy = SSO_AUTH_SERVICE (object);
645     gchar *object_path = NULL;
646     GVariant *identity_data;
647     GError *error = NULL;
648
649     g_return_if_fail (identity != NULL);
650     DEBUG ("%s", G_STRFUNC);
651
652     sso_auth_service_call_get_identity_finish (proxy,
653                                                &object_path,
654                                                &identity_data,
655                                                res,
656                                                &error);
657     if (SIGNON_IS_NOT_CANCELLED (error))
658     {
659         identity_registered (identity, object_path, identity_data, error);
660     }
661     if (object_path) g_free (object_path);
662     g_clear_error (&error);
663 }
664
665 static void
666 identity_check_remote_registration (SignonIdentity *self)
667 {
668     g_return_if_fail (self != NULL);
669     SignonIdentityPrivate *priv = self->priv;
670
671     g_return_if_fail (priv != NULL);
672
673     if (priv->registration_state != NOT_REGISTERED)
674         return;
675
676     if (priv->id != 0)
677         sso_auth_service_call_get_identity (priv->auth_service_proxy,
678                                             priv->id,
679                                             priv->app_ctx,
680                                             priv->cancellable,
681                                             identity_new_from_db_cb,
682                                             self);
683     else
684         sso_auth_service_call_register_new_identity (priv->auth_service_proxy,
685                                                      priv->app_ctx,
686                                                      priv->cancellable,
687                                                      identity_new_cb,
688                                                      self);
689
690     priv->registration_state = PENDING_REGISTRATION;
691 }
692
693 /**
694  * signon_identity_new_from_db:
695  * @id: identity ID.
696  *
697  * Construct an identity object associated with an existing identity
698  * record.
699  * This is essentially equivalent to calling
700  * signon_identity_new_with_context_from_db() and passing %NULL as the
701  * application context.
702  * 
703  * Applications can determine the @id either by enumerating the identities with 
704  * signon_auth_service_query_identities() (if they're the owner of the identity) 
705  * or via other means (such as the system's accounts service, or an application 
706  * configuration).
707  * 
708  * Returns: an instance of a #SignonIdentity.
709  */
710 SignonIdentity *
711 signon_identity_new_from_db (guint32 id)
712 {
713     return signon_identity_new_with_context_from_db (id, NULL);
714 }
715
716 /**
717  * signon_identity_new_with_context_from_db:
718  * @id: identity ID.
719  * @application_context: application security context, can be %NULL.
720  *
721  * Construct an identity object associated with an existing identity
722  * record. See #SignonSecurityContext for a discussion of @application_context contents.
723  * Together with the system context it is used to determine by the gSSO daemon 
724  * if the application can access the identity (the application needs to be either the 
725  * identity's owner or to be present on the ACL).
726  * 
727  * Applications can determine the @id either by enumerating the identities with 
728  * signon_auth_service_query_identities() (if they're the owner of the identity) 
729  * or via other means (such as the system's accounts service, or an application 
730  * configuration).
731  * 
732  * Returns: an instance of a #SignonIdentity.
733  */
734 SignonIdentity*
735 signon_identity_new_with_context_from_db (guint32 id, const gchar *application_context)
736 {
737     SignonIdentity *identity;
738     DEBUG ("%s %d: %d\n", G_STRFUNC, __LINE__, id);
739     if (id == 0)
740         return NULL;
741
742     identity = g_object_new (SIGNON_TYPE_IDENTITY,
743                              "id", id,
744                              "app_ctx", application_context,
745                              NULL);
746     g_return_val_if_fail (SIGNON_IS_IDENTITY (identity), NULL);
747     g_return_val_if_fail (identity->priv != NULL, NULL);
748
749     identity->priv->id = id;
750     identity->priv->app_ctx = (application_context) ?
751         g_strdup (application_context) : g_strdup ("");
752     identity_check_remote_registration (identity);
753
754     return identity;
755 }
756
757 /**
758  * signon_identity_new:
759  *
760  * Construct a new, empty, identity object.
761  * This is essentially equivalent to calling signon_identity_new_with_context()
762  * and passing %NULL as the application context.
763  *
764  * Returns: an instance of an #SignonIdentity.
765  */
766 SignonIdentity *
767 signon_identity_new ()
768 {
769     return signon_identity_new_with_context (NULL);
770 }
771
772 /**
773  * signon_identity_new_with_context:
774  * @application_context: application security context, can be %NULL.
775  *
776  * Construct a new, empty, identity object. See #SignonSecurityContext for a 
777  * discussion of @application_context contents. @application_context is used to set the identity's owner
778  * if the identity is stored to the database with signon_identity_store_credentials_with_args()
779  * or signon_identity_store_credentials_with_info().
780  *
781  * Returns: an instance of an #SignonIdentity.
782  */
783 SignonIdentity*
784 signon_identity_new_with_context (const gchar *application_context)
785 {
786     DEBUG ("%s %d", G_STRFUNC, __LINE__);
787     SignonIdentity *identity = g_object_new (
788                                      SIGNON_TYPE_IDENTITY,
789                                      "app_ctx", application_context,
790                                      NULL);
791     g_return_val_if_fail (SIGNON_IS_IDENTITY (identity), NULL);
792     g_return_val_if_fail (identity->priv != NULL, NULL);
793
794     identity->priv->app_ctx = (application_context) ?
795         g_strdup (application_context) : g_strdup ("");
796     identity_check_remote_registration (identity);
797
798     return identity;
799 }
800
801 /**
802  * signon_identity_create_session:
803  * @self: the #SignonIdentity.
804  * @method: authentication method.
805  * @error: pointer to a location which will receive the error, if any.
806  *
807  * Creates an authentication session for this identity. If the identity has been
808  * retrieved from the database, the authentication method must be one of those 
809  * listed in signon_identity_info_get_methods(), otherwise it can be any method
810  * supported by gSSO.
811  *
812  * Returns: (transfer full): a new #SignonAuthSession.
813  */
814 SignonAuthSession *
815 signon_identity_create_session(SignonIdentity *self,
816                                const gchar *method,
817                                GError **error)
818 {
819     g_return_val_if_fail (SIGNON_IS_IDENTITY (self), NULL);
820
821     SignonIdentityPrivate *priv = self->priv;
822     g_return_val_if_fail (priv != NULL, NULL);
823
824     DEBUG ("%s %d", G_STRFUNC, __LINE__);
825
826     if (method == NULL)
827     {
828         DEBUG ("NULL method as input. Aborting.");
829         g_set_error(error,
830                     signon_error_quark(),
831                     SIGNON_ERROR_UNKNOWN,
832                     "NULL input method.");
833         return NULL;
834     }
835
836     GSList *list = priv->sessions;
837     while (list)
838     {
839         SignonAuthSession *session = SIGNON_AUTH_SESSION (priv->sessions->data);
840         const gchar *sessionMethod = signon_auth_session_get_method (session);
841         if (g_strcmp0(sessionMethod, method) == 0)
842         {
843             DEBUG ("Auth Session with method `%s` already created.", method);
844             g_set_error (error,
845                          signon_error_quark(),
846                          SIGNON_ERROR_METHOD_NOT_AVAILABLE,
847                          "Authentication session for this method already requested.");
848             return NULL;
849         }
850
851         list = list->next;
852     }
853
854     SignonAuthSession *session =
855         signon_auth_session_new_for_identity (self,
856                                               method,
857                                               error);
858     if (session)
859     {
860         DEBUG ("%s %d - success", G_STRFUNC, __LINE__);
861         priv->sessions = g_slist_append(priv->sessions, session);
862         g_object_weak_ref (G_OBJECT(session),
863                            identity_session_object_destroyed_cb,
864                            self);
865         /*
866          * if you want to delete the identity
867          * you MUST delete all authsessions
868          * first
869          * */
870         g_object_ref (self);
871         priv->signed_out = FALSE;
872     }
873
874     return session;
875 }
876
877 /**
878  * signon_identity_store_credentials_with_info:
879  * @self: the #SignonIdentity.
880  * @info: the #SignonIdentityInfo data to store.
881  * @cb: (scope async): callback.
882  * @user_data: user_data.
883  *
884  * Stores the data contained in @info into the identity record in the database.
885  * See above for the detailed discussion of the meaning of various fields and
886  * their defaults.
887  */
888 void
889 signon_identity_store_credentials_with_info(SignonIdentity *self,
890                                             const SignonIdentityInfo *info,
891                                             SignonIdentityStoreCredentialsCb cb,
892                                             gpointer user_data)
893 {
894     IdentityStoreCredentialsCbData *cb_data;
895     IdentityStoreCredentialsData *operation_data;
896
897     DEBUG ();
898     g_return_if_fail (SIGNON_IS_IDENTITY (self));
899     g_return_if_fail (info != NULL);
900
901     SignonIdentityPrivate *priv = self->priv;
902     SignonIdentityInfo *new_info = signon_identity_info_copy (info);
903     if (priv->identity_info)
904         signon_identity_info_free (priv->identity_info);
905     priv->identity_info = new_info;
906
907     cb_data = g_slice_new0 (IdentityStoreCredentialsCbData);
908     cb_data->self = self;
909     cb_data->cb = cb;
910     cb_data->user_data = user_data;
911
912     operation_data = g_slice_new0 (IdentityStoreCredentialsData);
913     operation_data->info_variant =
914         signon_identity_info_to_variant (priv->identity_info);
915     operation_data->cb_data = cb_data;
916
917     identity_check_remote_registration (self);
918     _signon_object_call_when_ready (self,
919                                     identity_object_quark(),
920                                     identity_store_credentials_ready_cb,
921                                     operation_data);
922 }
923
924 /**
925  * signon_identity_store_credentials_with_args:
926  * @self: the #SignonIdentity.
927  * @username: (allow-none): username.
928  * @secret: (allow-none): secret.
929  * @store_secret: whether gSSO should save the password in secret storage.
930  * @methods: (transfer none) (element-type utf8 GStrv): allowed methods.
931  * @caption: (allow-none): caption.
932  * @realms: (allow-none): allowed realms.
933  * @owner: (allow-none): owner.
934  * @access_control_list: (allow-none): access control list.
935  * @type: the type of the identity.
936  * @cb: (scope async): callback.
937  * @user_data: user_data.
938  *
939  * Stores the given data into the identity. See above for the meaning
940  * of the specific fields.
941  */
942 void signon_identity_store_credentials_with_args(SignonIdentity *self,
943                                                  const gchar *username,
944                                                  const gchar *secret,
945                                                  const gboolean store_secret,
946                                                  GHashTable *methods,
947                                                  const gchar *caption,
948                                                  const gchar* const *realms,
949                                                  const SignonSecurityContext *owner,
950                                                  SignonSecurityContextList *access_control_list,
951                                                  SignonIdentityType type,
952                                                  SignonIdentityStoreCredentialsCb cb,
953                                                  gpointer user_data)
954 {
955     SignonIdentityInfo *info;
956
957     g_return_if_fail (SIGNON_IS_IDENTITY (self));
958
959     info = signon_identity_info_new ();
960     signon_identity_info_set_username (info, username);
961     signon_identity_info_set_secret (info, secret, store_secret);
962     signon_identity_info_set_methods (info, methods);
963     signon_identity_info_set_caption (info, caption);
964     signon_identity_info_set_realms (info, realms);
965     if (owner)
966     {
967         signon_identity_info_set_owner (info, owner);
968     }
969     if (access_control_list)
970     {
971         signon_identity_info_set_access_control_list (info,
972                                                       access_control_list);
973     }
974     signon_identity_info_set_identity_type (info, type);
975
976     signon_identity_store_credentials_with_info (self, info, cb, user_data);
977     signon_identity_info_free (info);
978 }
979
980 static void
981 identity_store_credentials_ready_cb (gpointer object, const GError *error, gpointer user_data)
982 {
983     g_return_if_fail (SIGNON_IS_IDENTITY (object));
984
985     SignonIdentity *self = SIGNON_IDENTITY (object);
986     SignonIdentityPrivate *priv = self->priv;
987     g_return_if_fail (priv != NULL);
988
989     DEBUG ("%s %d", G_STRFUNC, __LINE__);
990
991     IdentityStoreCredentialsData *operation_data =
992         (IdentityStoreCredentialsData *)user_data;
993     g_return_if_fail (operation_data != NULL);
994
995     IdentityStoreCredentialsCbData *cb_data = operation_data->cb_data;
996     g_return_if_fail (cb_data != NULL);
997
998     if (error)
999     {
1000         DEBUG ("IdentityError: %s", error->message);
1001
1002         if (cb_data->cb)
1003         {
1004             (cb_data->cb) (self, 0, error, cb_data->user_data);
1005         }
1006
1007         g_slice_free (IdentityStoreCredentialsCbData, cb_data);
1008     }
1009     else
1010     {
1011         g_return_if_fail (priv->proxy != NULL);
1012
1013         sso_identity_call_store (priv->proxy,
1014                                  operation_data->info_variant,
1015                                  priv->cancellable,
1016                                  identity_store_credentials_reply,
1017                                  cb_data);
1018     }
1019
1020     g_slice_free (IdentityStoreCredentialsData, operation_data);
1021 }
1022
1023 static void
1024 identity_store_credentials_reply (GObject *object, GAsyncResult *res,
1025                                   gpointer userdata)
1026 {
1027     IdentityStoreCredentialsCbData *cb_data = (IdentityStoreCredentialsCbData *)userdata;
1028     SsoIdentity *proxy = SSO_IDENTITY (object);
1029     guint id;
1030     GError *error = NULL;
1031
1032     g_return_if_fail (cb_data != NULL);
1033     g_return_if_fail (cb_data->self != NULL);
1034     g_return_if_fail (cb_data->self->priv != NULL);
1035
1036     SignonIdentityPrivate *priv = cb_data->self->priv;
1037
1038     sso_identity_call_store_finish (proxy, &id, res, &error);
1039
1040     if (error == NULL)
1041     {
1042         g_return_if_fail (priv->identity_info == NULL);
1043
1044         g_object_set (cb_data->self, "id", id, NULL);
1045         cb_data->self->priv->id = id;
1046
1047         /*
1048          * if the previous state was REMOVED
1049          * then we need to reset it
1050          * */
1051         priv->removed = FALSE;
1052     }
1053
1054     if (SIGNON_IS_NOT_CANCELLED (error) && cb_data->cb)
1055     {
1056         (cb_data->cb) (cb_data->self, id, error, cb_data->user_data);
1057     }
1058
1059     g_clear_error(&error);
1060     g_slice_free (IdentityStoreCredentialsCbData, cb_data);
1061 }
1062
1063 static void
1064 identity_verify_reply (GObject *object, GAsyncResult *res,
1065                        gpointer userdata)
1066 {
1067     SsoIdentity *proxy = SSO_IDENTITY (object);
1068     gboolean valid;
1069     GError *error = NULL;
1070     IdentityVerifyCbData *cb_data = (IdentityVerifyCbData *)userdata;
1071
1072     g_return_if_fail (cb_data != NULL);
1073     g_return_if_fail (cb_data->self != NULL);
1074
1075     sso_identity_call_verify_secret_finish (proxy, &valid, res, &error);
1076
1077     if (SIGNON_IS_NOT_CANCELLED (error) && cb_data->cb)
1078     {
1079         (cb_data->cb) (cb_data->self, valid, error, cb_data->user_data);
1080     }
1081
1082     g_clear_error(&error);
1083     g_slice_free (IdentityVerifyCbData, cb_data);
1084 }
1085
1086 static void
1087 identity_verify_ready_cb (gpointer object, const GError *error, gpointer user_data)
1088 {
1089     g_return_if_fail (SIGNON_IS_IDENTITY (object));
1090
1091     SignonIdentity *self = SIGNON_IDENTITY (object);
1092     SignonIdentityPrivate *priv = self->priv;
1093     g_return_if_fail (priv != NULL);
1094
1095     DEBUG ("%s %d", G_STRFUNC, __LINE__);
1096
1097     IdentityVerifyData *operation_data =
1098         (IdentityVerifyData *)user_data;
1099     g_return_if_fail (operation_data != NULL);
1100
1101     IdentityVerifyCbData *cb_data = operation_data->cb_data;
1102     g_return_if_fail (cb_data != NULL);
1103
1104     if (priv->removed == TRUE)
1105     {
1106         GError *new_error = g_error_new (signon_error_quark(),
1107                                          SIGNON_ERROR_IDENTITY_NOT_FOUND,
1108                                          "Already removed from database.");
1109
1110         if (cb_data->cb)
1111         {
1112             (cb_data->cb) (self, FALSE, new_error, cb_data->user_data);
1113         }
1114
1115         g_error_free (new_error);
1116         g_slice_free (IdentityVerifyCbData, cb_data);
1117     }
1118     else if (error)
1119     {
1120         DEBUG ("IdentityError: %s", error->message);
1121
1122         if (cb_data->cb)
1123         {
1124             (cb_data->cb) (self, FALSE, error, cb_data->user_data);
1125         }
1126
1127         g_slice_free (IdentityVerifyCbData, cb_data);
1128     }
1129     else
1130     {
1131         DEBUG ("%s %d", G_STRFUNC, __LINE__);
1132         g_return_if_fail (priv->proxy != NULL);
1133
1134         switch (operation_data->operation) {
1135         case SIGNON_VERIFY_SECRET:
1136             sso_identity_call_verify_secret (priv->proxy,
1137                                              operation_data->data_to_send,
1138                                              priv->cancellable,
1139                                              identity_verify_reply,
1140                                              cb_data);
1141             break;
1142         default: g_critical ("Wrong operation code");
1143         };
1144     }
1145     g_free (operation_data->params);
1146     g_free (operation_data->data_to_send);
1147     g_slice_free (IdentityVerifyData, operation_data);
1148 }
1149
1150 static void
1151 identity_verify_data(SignonIdentity *self,
1152                      const gchar *data_to_send,
1153                      gint operation,
1154                      SignonIdentityVerifyCb cb,
1155                      gpointer user_data)
1156 {
1157     g_return_if_fail (SIGNON_IS_IDENTITY (self));
1158
1159     SignonIdentityPrivate *priv = self->priv;
1160     g_return_if_fail (priv != NULL);
1161
1162     DEBUG ("%s %d", G_STRFUNC, __LINE__);
1163
1164     IdentityVerifyCbData *cb_data = g_slice_new0 (IdentityVerifyCbData);
1165     cb_data->self = self;
1166     cb_data->cb = cb;
1167     cb_data->user_data = user_data;
1168
1169     IdentityVerifyData *operation_data = g_slice_new0 (IdentityVerifyData);
1170
1171     operation_data->params = NULL;
1172     operation_data->data_to_send = g_strdup (data_to_send);
1173     operation_data->operation = operation;
1174     operation_data->cb_data = cb_data;
1175
1176     identity_check_remote_registration (self);
1177     _signon_object_call_when_ready (self,
1178                                     identity_object_quark(),
1179                                     identity_verify_ready_cb,
1180                                     operation_data);
1181 }
1182
1183 /**
1184  * signon_identity_verify_secret:
1185  * @self: the #SignonIdentity.
1186  * @secret: the secret (password) to be verified.
1187  * @cb: (scope async): callback.
1188  * @user_data: user_data.
1189  *
1190  * Verifies the given secret. Not currently supported by gSSO.
1191  */
1192 void signon_identity_verify_secret(SignonIdentity *self,
1193                                   const gchar *secret,
1194                                   SignonIdentityVerifyCb cb,
1195                                   gpointer user_data)
1196 {
1197     identity_verify_data (self,
1198                           secret,
1199                           SIGNON_VERIFY_SECRET,
1200                           cb,
1201                           user_data);
1202 }
1203
1204 static void
1205 identity_process_updated (SignonIdentity *self)
1206 {
1207     DEBUG ("%d %s", __LINE__, __func__);
1208
1209     g_return_if_fail (self != NULL);
1210     g_return_if_fail (self->priv != NULL);
1211
1212     SignonIdentityPrivate *priv = self->priv;
1213     g_return_if_fail (priv->proxy != NULL);
1214
1215     signon_identity_info_free (priv->identity_info);
1216     priv->identity_info = NULL;
1217     priv->updated = FALSE;
1218
1219     DEBUG ("%s info freed, to be updated", __func__);
1220 }
1221
1222 static void
1223 identity_process_removed (SignonIdentity *self)
1224 {
1225     g_return_if_fail (self != NULL);
1226     g_return_if_fail (self->priv != NULL);
1227
1228     DEBUG ("%d %s", __LINE__, __func__);
1229
1230     SignonIdentityPrivate *priv = self->priv;
1231
1232     if (priv->removed == TRUE)
1233         return;
1234
1235     priv->removed = TRUE;
1236     signon_identity_info_free (priv->identity_info);
1237     priv->identity_info = NULL;
1238
1239     g_object_set (self, "id", 0, NULL);
1240     priv->id = 0;
1241 }
1242
1243 static void
1244 identity_process_signout(SignonIdentity *self)
1245 {
1246     g_return_if_fail (self != NULL);
1247     g_return_if_fail (self->priv != NULL);
1248
1249     DEBUG ("%d %s", __LINE__, __func__);
1250     SignonIdentityPrivate *priv = self->priv;
1251
1252     if (priv->signed_out == TRUE)
1253         return;
1254
1255     GSList *llink = priv->sessions;
1256     while (llink)
1257     {
1258         GSList *next = llink->next;
1259         g_object_unref (G_OBJECT(llink->data));
1260         llink = next;
1261     }
1262
1263     priv->signed_out = TRUE;
1264     g_signal_emit(G_OBJECT(self), signals[SIGNEDOUT_SIGNAL], 0);
1265 }
1266
1267 /*
1268  * TODO: fix the implementation
1269  * of signond: it returns result = TRUE
1270  * in ANY CASE
1271  * */
1272 static void
1273 identity_signout_reply (GObject *object, GAsyncResult *res,
1274                         gpointer userdata)
1275 {
1276     SsoIdentity *proxy = SSO_IDENTITY (object);
1277     gboolean result;
1278     GError *error = NULL;
1279     IdentityVoidCbData *cb_data = (IdentityVoidCbData *)userdata;
1280
1281     g_return_if_fail (cb_data != NULL);
1282     g_return_if_fail (cb_data->self != NULL);
1283     g_return_if_fail (cb_data->self->priv != NULL);
1284
1285     sso_identity_call_sign_out_finish (proxy, &result, res, &error);
1286
1287     if (SIGNON_IS_NOT_CANCELLED (error) && cb_data->cb)
1288     {
1289         (cb_data->cb) (cb_data->self, error, cb_data->user_data);
1290     }
1291
1292     g_clear_error(&error);
1293     g_slice_free (IdentityVoidCbData, cb_data);
1294 }
1295
1296 static void
1297 identity_removed_reply (GObject *object, GAsyncResult *res,
1298                         gpointer userdata)
1299 {
1300     SsoIdentity *proxy = SSO_IDENTITY (object);
1301     GError *error = NULL;
1302     IdentityVoidCbData *cb_data = (IdentityVoidCbData *)userdata;
1303
1304     g_return_if_fail (cb_data != NULL);
1305     g_return_if_fail (cb_data->self != NULL);
1306     g_return_if_fail (cb_data->self->priv != NULL);
1307
1308     sso_identity_call_remove_finish (proxy, res, &error);
1309
1310     if (SIGNON_IS_NOT_CANCELLED (error) && cb_data->cb)
1311     {
1312         (cb_data->cb) (cb_data->self, error, cb_data->user_data);
1313     }
1314
1315     g_clear_error(&error);
1316     g_slice_free (IdentityVoidCbData, cb_data);
1317 }
1318
1319 static void
1320 identity_info_reply(GObject *object, GAsyncResult *res,
1321                     gpointer userdata)
1322 {
1323     SsoIdentity *proxy = SSO_IDENTITY (object);
1324     GVariant *identity_data = NULL;
1325     DEBUG ("%d %s", __LINE__, __func__);
1326
1327     GError *error = NULL;
1328     IdentityInfoCbData *cb_data = (IdentityInfoCbData *)userdata;
1329
1330     g_return_if_fail (cb_data != NULL);
1331     g_return_if_fail (cb_data->self != NULL);
1332     g_return_if_fail (cb_data->self->priv != NULL);
1333
1334     SignonIdentityPrivate *priv = cb_data->self->priv;
1335
1336     sso_identity_call_get_info_finish (proxy, &identity_data, res, &error);
1337
1338     if (identity_data != NULL)
1339     {
1340         priv->identity_info =
1341                 signon_identity_info_new_from_variant (identity_data);
1342         g_variant_unref (identity_data);
1343     }
1344
1345     if (SIGNON_IS_NOT_CANCELLED (error) && cb_data->cb)
1346     {
1347         (cb_data->cb) (cb_data->self, priv->identity_info, error, cb_data->user_data);
1348     }
1349
1350     g_clear_error(&error);
1351     g_slice_free (IdentityInfoCbData, cb_data);
1352
1353     priv->updated = TRUE;
1354 }
1355
1356 static void
1357 identity_info_ready_cb(gpointer object, const GError *error, gpointer user_data)
1358 {
1359     g_return_if_fail (SIGNON_IS_IDENTITY (object));
1360
1361     SignonIdentity *self = SIGNON_IDENTITY (object);
1362     SignonIdentityPrivate *priv = self->priv;
1363     g_return_if_fail (priv != NULL);
1364
1365     DEBUG ("%s %d", G_STRFUNC, __LINE__);
1366
1367     IdentityVoidData *operation_data =
1368         (IdentityVoidData *)user_data;
1369     g_return_if_fail (operation_data != NULL);
1370
1371     IdentityInfoCbData *cb_data = operation_data->cb_data;
1372     g_return_if_fail (cb_data != NULL);
1373
1374     if (priv->removed == TRUE)
1375     {
1376         DEBUG ("%s identity removed", G_STRFUNC);
1377
1378         GError *new_error = g_error_new (signon_error_quark(),
1379                                          SIGNON_ERROR_IDENTITY_NOT_FOUND,
1380                                          "Already removed from database.");
1381         if (cb_data->cb)
1382             (cb_data->cb) (self, NULL, new_error, cb_data->user_data);
1383
1384         g_error_free (new_error);
1385     }
1386     else if (error || priv->id == 0)
1387     {
1388         DEBUG ("%s identity is new", G_STRFUNC);
1389
1390         if (error)
1391             DEBUG ("IdentityError: %s", error->message);
1392         else
1393             DEBUG ("Identity is not stored and has no info yet");
1394
1395         if (cb_data->cb)
1396             (cb_data->cb) (self, NULL, error, cb_data->user_data);
1397     }
1398     else if (priv->updated == FALSE)
1399     {
1400         DEBUG ("%s identity needs update, call daemon", G_STRFUNC);
1401
1402         g_return_if_fail (priv->proxy != NULL);
1403         sso_identity_call_get_info (priv->proxy,
1404                                     priv->cancellable,
1405                                     identity_info_reply,
1406                                     cb_data);
1407         goto free_op_data;
1408     }
1409     else
1410     {
1411         DEBUG ("%s pass existing one", G_STRFUNC);
1412
1413         if (cb_data->cb)
1414             (cb_data->cb) (self, priv->identity_info, error, cb_data->user_data);
1415     }
1416
1417     g_slice_free (IdentityInfoCbData, cb_data);
1418
1419 free_op_data:
1420     g_slice_free (IdentityVoidData, operation_data);
1421 }
1422
1423 static void
1424 identity_signout_ready_cb(gpointer object, const GError *error, gpointer user_data)
1425 {
1426     g_return_if_fail (SIGNON_IS_IDENTITY (object));
1427
1428     SignonIdentity *self = SIGNON_IDENTITY (object);
1429     SignonIdentityPrivate *priv = self->priv;
1430     g_return_if_fail (priv != NULL);
1431
1432     DEBUG ("%s %d", G_STRFUNC, __LINE__);
1433     IdentityVoidCbData *cb_data = (IdentityVoidCbData *)user_data;
1434
1435     g_return_if_fail (cb_data != NULL);
1436
1437     if (priv->removed == TRUE)
1438     {
1439         GError *new_error = g_error_new (signon_error_quark(),
1440                                          SIGNON_ERROR_IDENTITY_NOT_FOUND,
1441                                          "Already removed from database.");
1442         if (cb_data->cb)
1443         {
1444             (cb_data->cb) (self, new_error, cb_data->user_data);
1445         }
1446
1447         g_error_free (new_error);
1448         g_slice_free (IdentityVoidCbData, cb_data);
1449     }
1450     else if (error)
1451     {
1452         DEBUG ("IdentityError: %s", error->message);
1453         if (cb_data->cb)
1454         {
1455             (cb_data->cb) (self, error, cb_data->user_data);
1456         }
1457
1458         g_slice_free (IdentityVoidCbData, cb_data);
1459     }
1460     else
1461     {
1462         g_return_if_fail (priv->proxy != NULL);
1463         sso_identity_call_sign_out (priv->proxy,
1464                                     priv->cancellable,
1465                                     identity_signout_reply,
1466                                     cb_data);
1467     }
1468 }
1469
1470 static void
1471 identity_remove_ready_cb(gpointer object, const GError *error, gpointer user_data)
1472 {
1473     g_return_if_fail (SIGNON_IS_IDENTITY (object));
1474
1475     SignonIdentity *self = SIGNON_IDENTITY (object);
1476     SignonIdentityPrivate *priv = self->priv;
1477     g_return_if_fail (priv != NULL);
1478
1479     DEBUG ("%s %d", G_STRFUNC, __LINE__);
1480     IdentityVoidCbData *cb_data = (IdentityVoidCbData *)user_data;
1481     g_return_if_fail (cb_data != NULL);
1482
1483     if (priv->removed == TRUE)
1484     {
1485         GError *new_error = g_error_new (signon_error_quark(),
1486                                           SIGNON_ERROR_IDENTITY_NOT_FOUND,
1487                                          "Already removed from database.");
1488         if (cb_data->cb)
1489         {
1490             (cb_data->cb) (self, new_error, cb_data->user_data);
1491         }
1492
1493         g_error_free (new_error);
1494         g_slice_free (IdentityVoidCbData, cb_data);
1495     }
1496     else if (error)
1497     {
1498         DEBUG ("IdentityError: %s", error->message);
1499         if (cb_data->cb)
1500         {
1501             (cb_data->cb) (self, error, cb_data->user_data);
1502         }
1503
1504         g_slice_free (IdentityVoidCbData, cb_data);
1505     }
1506     else
1507     {
1508         g_return_if_fail (priv->proxy != NULL);
1509         sso_identity_call_remove (priv->proxy,
1510                                   priv->cancellable,
1511                                   identity_removed_reply,
1512                                   cb_data);
1513     }
1514 }
1515
1516 void static
1517 identity_void_operation(SignonIdentity *self,
1518                         gint operation,
1519                         gpointer cb_data)
1520 {
1521     g_return_if_fail (SIGNON_IS_IDENTITY (self));
1522
1523     SignonIdentityPrivate *priv = self->priv;
1524     g_return_if_fail (priv != NULL);
1525
1526     DEBUG ("%s %d", G_STRFUNC, __LINE__);
1527
1528     IdentityVoidData *operation_data = g_slice_new0 (IdentityVoidData);
1529     operation_data->cb_data = cb_data;
1530     _signon_object_call_when_ready (self,
1531                                     identity_object_quark(),
1532                                     identity_info_ready_cb,
1533                                     operation_data);
1534 }
1535
1536 /**
1537  * signon_identity_remove:
1538  * @self: the #SignonIdentity.
1539  * @cb: (scope async): callback to be called when the operation has completed.
1540  * @user_data: user_data to pass to the callback.
1541  *
1542  * Removes the corresponding credentials record from the database.
1543  */
1544 void signon_identity_remove(SignonIdentity *self,
1545                            SignonIdentityRemovedCb cb,
1546                            gpointer user_data)
1547 {
1548     g_return_if_fail (SIGNON_IS_IDENTITY (self));
1549
1550     SignonIdentityPrivate *priv = self->priv;
1551     g_return_if_fail (priv != NULL);
1552
1553     IdentityVoidCbData *cb_data = g_slice_new0 (IdentityVoidCbData);
1554     cb_data->self = self;
1555     cb_data->cb = (SignonIdentityVoidCb)cb;
1556     cb_data->user_data = user_data;
1557
1558     DEBUG ("%s %d", G_STRFUNC, __LINE__);
1559
1560     identity_check_remote_registration (self);
1561     _signon_object_call_when_ready (self,
1562                                     identity_object_quark(),
1563                                     identity_remove_ready_cb,
1564                                     cb_data);
1565 }
1566
1567 /**
1568  * signon_identity_signout:
1569  * @self: the #SignonIdentity.
1570  * @cb: (scope async): callback.
1571  * @user_data: user_data.
1572  *
1573  * Asks signond to close all authentication sessions for this
1574  * identity, and to remove any stored secrets associated with it (password and
1575  * authentication tokens).
1576  */
1577 void signon_identity_signout(SignonIdentity *self,
1578                              SignonIdentitySignedOutCb cb,
1579                              gpointer user_data)
1580 {
1581     g_return_if_fail (SIGNON_IS_IDENTITY (self));
1582
1583     SignonIdentityPrivate *priv = self->priv;
1584     g_return_if_fail (priv != NULL);
1585
1586     IdentityVoidCbData *cb_data = g_slice_new0 (IdentityVoidCbData);
1587     cb_data->self = self;
1588     cb_data->cb = (SignonIdentityVoidCb)cb;
1589     cb_data->user_data = user_data;
1590
1591     identity_check_remote_registration (self);
1592     _signon_object_call_when_ready (self,
1593                                     identity_object_quark(),
1594                                     identity_signout_ready_cb,
1595                                     cb_data);
1596 }
1597
1598 /**
1599  * signon_identity_add_reference:
1600  * @self: the #SignonIdentity.
1601  * @reference: reference to be added
1602  * @cb: callback
1603  * @user_data: user_data.
1604  *
1605  * Adds named reference to identity. Not currently supported by gSSO.
1606  */
1607 void signon_identity_add_reference(SignonIdentity *self,
1608                              const gchar *reference,
1609                              SignonIdentityReferenceAddedCb cb,
1610                              gpointer user_data)
1611 {
1612     g_return_if_fail (SIGNON_IS_IDENTITY (self));
1613
1614     SignonIdentityPrivate *priv = self->priv;
1615     g_return_if_fail (priv != NULL);
1616
1617     //TODO implement
1618
1619     if (cb)
1620         (cb) (self, NULL, user_data);
1621 }
1622
1623 /**
1624  * signon_identity_remove_reference:
1625  * @self: the #SignonIdentity.
1626  * @reference: reference to be removed
1627  * @cb: callback
1628  * @user_data: user_data.
1629  *
1630  * Removes named reference from identity. Not currently supported by gSSO.
1631  */
1632 void signon_identity_remove_reference(SignonIdentity *self,
1633                              const gchar *reference,
1634                              SignonIdentityReferenceRemovedCb cb,
1635                              gpointer user_data)
1636 {
1637     g_return_if_fail (SIGNON_IS_IDENTITY (self));
1638
1639     SignonIdentityPrivate *priv = self->priv;
1640     g_return_if_fail (priv != NULL);
1641
1642     //TODO implement
1643
1644     if (cb)
1645         (cb) (self, NULL, user_data);
1646 }
1647
1648 /**
1649  * signon_identity_query_info:
1650  * @self: the #SignonIdentity.
1651  * @cb: (scope async): callback.
1652  * @user_data: user_data.
1653  *
1654  * Fetches the #SignonIdentityInfo data associated with this
1655  * identity.
1656  */
1657 void signon_identity_query_info(SignonIdentity *self,
1658                                 SignonIdentityInfoCb cb,
1659                                 gpointer user_data)
1660 {
1661     g_return_if_fail (SIGNON_IS_IDENTITY (self));
1662
1663     SignonIdentityPrivate *priv = self->priv;
1664     g_return_if_fail (priv != NULL);
1665
1666     IdentityInfoCbData *cb_data = g_slice_new0 (IdentityInfoCbData);
1667     cb_data->self = self;
1668     cb_data->cb = cb;
1669     cb_data->user_data = user_data;
1670
1671     identity_check_remote_registration (self);
1672     identity_void_operation(self,
1673                             SIGNON_INFO,
1674                             cb_data);
1675 }
1676
1677 static void
1678 identity_get_auth_session_reply (GObject *object, GAsyncResult *res,
1679                                  gpointer userdata)
1680 {
1681     SsoIdentity *proxy = SSO_IDENTITY (object);
1682     gchar *object_path = NULL;
1683     GError *error = NULL;
1684
1685     DEBUG ("%s %d", G_STRFUNC, __LINE__);
1686
1687     sso_identity_call_get_auth_session_finish (proxy,
1688                                                &object_path,
1689                                                res,
1690                                                &error);
1691
1692     IdentitySessionCbData *cb_data = (IdentitySessionCbData *) userdata;
1693     g_return_if_fail (cb_data != NULL);
1694     g_return_if_fail (cb_data->cb != NULL);
1695
1696     if (SIGNON_IS_NOT_CANCELLED (error))
1697     {
1698         (cb_data->cb) (cb_data->session,
1699                 error,
1700                 g_dbus_proxy_get_connection ((GDBusProxy *)proxy),
1701                 g_dbus_proxy_get_name ((GDBusProxy *)proxy),
1702                 object_path);
1703     }
1704     g_slice_free (IdentitySessionCbData, cb_data);
1705     if (object_path) g_free (object_path);
1706     g_clear_error (&error);
1707 }
1708
1709 static void
1710 identity_session_ready_cb(gpointer object, const GError *error, gpointer user_data)
1711 {
1712     g_return_if_fail (SIGNON_IS_IDENTITY (object));
1713     DEBUG ("%s %d", G_STRFUNC, __LINE__);
1714
1715     SignonIdentity *self = SIGNON_IDENTITY (object);
1716     SignonIdentityPrivate *priv = self->priv;
1717     g_return_if_fail (priv != NULL);
1718
1719     IdentitySessionData *operation_data = (IdentitySessionData *) user_data;
1720     g_return_if_fail (operation_data != NULL);
1721
1722     IdentitySessionCbData *cb_data = operation_data->cb_data;
1723     g_return_if_fail (cb_data != NULL);
1724     g_return_if_fail (cb_data->cb != NULL);
1725
1726     if (error)
1727     {
1728         (cb_data->cb) (cb_data->session, (GError *)error, NULL, NULL, NULL);
1729     }
1730     else if (priv->removed == TRUE)
1731     {
1732         GError *new_error = g_error_new (signon_error_quark(),
1733                                          SIGNON_ERROR_IDENTITY_NOT_FOUND,
1734                                          "Already removed from database.");
1735         (cb_data->cb) (cb_data->session, new_error, NULL, NULL, NULL);
1736         g_error_free (new_error);
1737     }
1738     else
1739     {
1740         g_return_if_fail (priv->proxy != NULL);
1741
1742         sso_identity_call_get_auth_session (
1743             priv->proxy,
1744             operation_data->method,
1745             priv->cancellable,
1746             identity_get_auth_session_reply,
1747             cb_data);
1748     }
1749
1750     g_slice_free (IdentitySessionData, operation_data);
1751 }
1752
1753 static void
1754 identity_session_object_destroyed_cb(gpointer data,
1755                                      GObject *where_the_session_was)
1756 {
1757     g_return_if_fail (SIGNON_IS_IDENTITY (data));
1758     DEBUG ("%s %d", G_STRFUNC, __LINE__);
1759
1760     SignonIdentity *self = SIGNON_IDENTITY (data);
1761     SignonIdentityPrivate *priv = self->priv;
1762     g_return_if_fail (priv != NULL);
1763
1764     priv->sessions = g_slist_remove(priv->sessions, (gpointer)where_the_session_was);
1765     g_object_unref (self);
1766 }
1767
1768 //FIXME: is this a private method?
1769 /**
1770  * signon_identity_get_auth_session:
1771  * @self: the #SignonIdentity.
1772  * @session: the #SignonAuthSession object to get the remote object for.
1773  * @method: method name for the session.
1774  * @cb: (scope async): completion callback.
1775  *
1776  * Obtain a remote object for a local session object. Should not be used by
1777  * applications.
1778  */
1779 void signon_identity_get_auth_session (SignonIdentity *self,
1780                                        SignonAuthSession *session,
1781                                        const gchar *method,
1782                                        SignonIdentitySessionReadyCb cb)
1783 {
1784     g_return_if_fail (SIGNON_IS_IDENTITY (self));
1785     DEBUG ("%s %d", G_STRFUNC, __LINE__);
1786
1787     SignonIdentityPrivate *priv = self->priv;
1788     g_return_if_fail (priv != NULL);
1789
1790     IdentitySessionCbData *cb_data = g_slice_new0 (IdentitySessionCbData);
1791     cb_data->self = self;
1792     cb_data->session = session;
1793     cb_data->cb = cb;
1794
1795     IdentitySessionData *operation_data = g_slice_new0 (IdentitySessionData);
1796     operation_data->method = method;
1797     operation_data->cb_data = cb_data;
1798
1799     identity_check_remote_registration (self);
1800     _signon_object_call_when_ready (self,
1801                                     identity_object_quark(),
1802                                     identity_session_ready_cb,
1803                                     operation_data);
1804 }
1805