2 * empathy-auth-uoa.c - Source for Uoa SASL authentication
3 * Copyright (C) 2012 Collabora Ltd.
4 * @author Xavier Claessens <xavier.claessens@collabora.co.uk>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 #include <libaccounts-glib/ag-account.h>
24 #include <libaccounts-glib/ag-account-service.h>
25 #include <libaccounts-glib/ag-auth-data.h>
26 #include <libaccounts-glib/ag-manager.h>
27 #include <libaccounts-glib/ag-service.h>
29 #include <libsignon-glib/signon-identity.h>
30 #include <libsignon-glib/signon-auth-session.h>
32 #define DEBUG_FLAG EMPATHY_DEBUG_SASL
33 #include "empathy-debug.h"
34 #include "empathy-utils.h"
35 #include "empathy-uoa-auth-handler.h"
36 #include "empathy-sasl-mechanisms.h"
38 #define SERVICE_TYPE "IM"
40 struct _EmpathyUoaAuthHandlerPriv
45 G_DEFINE_TYPE (EmpathyUoaAuthHandler, empathy_uoa_auth_handler, G_TYPE_OBJECT);
48 empathy_uoa_auth_handler_init (EmpathyUoaAuthHandler *self)
50 self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
51 EMPATHY_TYPE_UOA_AUTH_HANDLER, EmpathyUoaAuthHandlerPriv);
53 self->priv->manager = ag_manager_new_for_service_type (SERVICE_TYPE);
57 empathy_uoa_auth_handler_dispose (GObject *object)
59 EmpathyUoaAuthHandler *self = (EmpathyUoaAuthHandler *) object;
61 tp_clear_object (&self->priv->manager);
63 G_OBJECT_CLASS (empathy_uoa_auth_handler_parent_class)->dispose (object);
67 empathy_uoa_auth_handler_class_init (EmpathyUoaAuthHandlerClass *klass)
69 GObjectClass *oclass = G_OBJECT_CLASS (klass);
71 oclass->dispose = empathy_uoa_auth_handler_dispose;
73 g_type_class_add_private (klass, sizeof (EmpathyUoaAuthHandlerPriv));
76 EmpathyUoaAuthHandler *
77 empathy_uoa_auth_handler_new (void)
79 return g_object_new (EMPATHY_TYPE_UOA_AUTH_HANDLER, NULL);
83 auth_cb (GObject *source,
87 TpChannel *channel = (TpChannel *) source;
90 if (!empathy_sasl_auth_finish (channel, result, &error))
92 DEBUG ("SASL Mechanism error: %s", error->message);
93 g_clear_error (&error);
96 DEBUG ("Auth on %s suceeded", tp_proxy_get_object_path (channel));
98 tp_channel_close_async (channel, NULL, NULL);
104 AgAuthData *auth_data;
105 SignonAuthSession *session;
106 SignonIdentity *identity;
111 static QueryInfoData *
112 query_info_data_new (TpChannel *channel,
113 AgAuthData *auth_data,
114 SignonAuthSession *session,
115 SignonIdentity *identity)
119 data = g_slice_new0 (QueryInfoData);
120 data->channel = g_object_ref (channel);
121 data->auth_data = ag_auth_data_ref (auth_data);
122 data->session = g_object_ref (session);
123 data->identity = g_object_ref (identity);
129 query_info_data_free (QueryInfoData *data)
131 g_object_unref (data->channel);
132 ag_auth_data_unref (data->auth_data);
133 g_object_unref (data->session);
134 g_object_unref (data->identity);
135 g_free (data->username);
136 g_slice_free (QueryInfoData, data);
140 session_process_cb (SignonAuthSession *session,
141 GHashTable *session_data,
145 QueryInfoData *data = user_data;
146 const gchar *access_token;
147 const gchar *client_id;
151 DEBUG ("Error processing the session: %s", error->message);
152 tp_channel_close_async (data->channel, NULL, NULL);
153 query_info_data_free (data);
157 access_token = tp_asv_get_string (session_data, "AccessToken");
158 client_id = tp_asv_get_string (ag_auth_data_get_parameters (data->auth_data),
161 switch (empathy_sasl_channel_select_mechanism (data->channel))
163 case EMPATHY_SASL_MECHANISM_FACEBOOK:
164 empathy_sasl_auth_facebook_async (data->channel,
165 client_id, access_token,
169 case EMPATHY_SASL_MECHANISM_WLM:
170 empathy_sasl_auth_wlm_async (data->channel,
175 case EMPATHY_SASL_MECHANISM_GOOGLE:
176 empathy_sasl_auth_google_async (data->channel,
177 data->username, access_token,
182 g_assert_not_reached ();
185 query_info_data_free (data);
189 identity_query_info_cb (SignonIdentity *identity,
190 const SignonIdentityInfo *info,
194 QueryInfoData *data = user_data;
198 DEBUG ("Error querying info from identity: %s", error->message);
199 tp_channel_close_async (data->channel, NULL, NULL);
200 query_info_data_free (data);
204 data->username = g_strdup (signon_identity_info_get_username (info));
206 signon_auth_session_process (data->session,
207 ag_auth_data_get_parameters (data->auth_data),
208 ag_auth_data_get_mechanism (data->auth_data),
214 empathy_uoa_auth_handler_start (EmpathyUoaAuthHandler *self,
216 TpAccount *tp_account)
218 const GValue *id_value;
222 AgAccountService *service;
223 AgAuthData *auth_data;
225 SignonIdentity *identity;
226 SignonAuthSession *session;
227 GError *error = NULL;
229 g_return_if_fail (TP_IS_CHANNEL (channel));
230 g_return_if_fail (TP_IS_ACCOUNT (tp_account));
231 g_return_if_fail (empathy_uoa_auth_handler_supports (self, channel,
234 DEBUG ("Start UOA auth for account: %s",
235 tp_proxy_get_object_path (tp_account));
237 id_value = tp_account_get_storage_identifier (tp_account);
238 id = g_value_get_uint (id_value);
240 account = ag_manager_get_account (self->priv->manager, id);
242 l = ag_account_list_services_by_type (account, SERVICE_TYPE);
245 DEBUG ("Couldn't find IM service for AgAccountId %u", id);
246 g_object_unref (account);
247 tp_channel_close_async (channel, NULL, NULL);
251 /* Assume there is only one IM service */
252 service = ag_account_service_new (account, l->data);
253 ag_service_list_free (l);
254 g_object_unref (account);
256 auth_data = ag_account_service_get_auth_data (service);
257 cred_id = ag_auth_data_get_credentials_id (auth_data);
258 identity = signon_identity_new_from_db (cred_id);
259 session = signon_identity_create_session (identity,
260 ag_auth_data_get_method (auth_data),
264 DEBUG ("Error creating a SignonAuthSession: %s", error->message);
265 tp_channel_close_async (channel, NULL, NULL);
269 /* Query UOA for more info */
270 signon_identity_query_info (identity,
271 identity_query_info_cb,
272 query_info_data_new (channel, auth_data, session, identity));
275 ag_auth_data_unref (auth_data);
276 g_object_unref (service);
277 g_object_unref (identity);
278 g_object_unref (session);
282 empathy_uoa_auth_handler_supports (EmpathyUoaAuthHandler *self,
286 const gchar *provider;
287 EmpathySaslMechanism mech;
289 g_return_val_if_fail (TP_IS_CHANNEL (channel), FALSE);
290 g_return_val_if_fail (TP_IS_ACCOUNT (account), FALSE);
292 provider = tp_account_get_storage_provider (account);
294 if (tp_strdiff (provider, EMPATHY_UOA_PROVIDER))
297 mech = empathy_sasl_channel_select_mechanism (channel);
298 return mech == EMPATHY_SASL_MECHANISM_FACEBOOK ||
299 mech == EMPATHY_SASL_MECHANISM_WLM ||
300 mech == EMPATHY_SASL_MECHANISM_GOOGLE;