]> git.0d.be Git - empathy.git/blobdiff - libempathy/empathy-uoa-auth-handler.c
Merge remote-tracking branch 'origin/gnome-3-8'
[empathy.git] / libempathy / empathy-uoa-auth-handler.c
index ee377349d10d4bab54a406fe8765c8a8531de77e..7e17b70894903c3113e64ba8acaca3e98fc0cd22 100644 (file)
@@ -19,6 +19,7 @@
  */
 
 #include "config.h"
+#include "empathy-uoa-auth-handler.h"
 
 #include <libaccounts-glib/ag-account.h>
 #include <libaccounts-glib/ag-account-service.h>
 #include <libsignon-glib/signon-identity.h>
 #include <libsignon-glib/signon-auth-session.h>
 
-#define DEBUG_FLAG EMPATHY_DEBUG_SASL
-#include "empathy-debug.h"
+#include "empathy-keyring.h"
 #include "empathy-utils.h"
-#include "empathy-uoa-auth-handler.h"
 #include "empathy-uoa-utils.h"
 #include "empathy-sasl-mechanisms.h"
 
+#define DEBUG_FLAG EMPATHY_DEBUG_SASL
+#include "empathy-debug.h"
+
 struct _EmpathyUoaAuthHandlerPriv
 {
   AgManager *manager;
@@ -81,6 +83,7 @@ empathy_uoa_auth_handler_new (void)
 typedef struct
 {
   TpChannel *channel;
+  AgAccountService *service;
   AgAuthData *auth_data;
   SignonIdentity *identity;
   SignonAuthSession *session;
@@ -97,6 +100,7 @@ auth_context_new (TpChannel *channel,
 
   ctx = g_slice_new0 (AuthContext);
   ctx->channel = g_object_ref (channel);
+  ctx->service = g_object_ref (service);
 
   ctx->auth_data = ag_account_service_get_auth_data (service);
   if (ctx->auth_data == NULL)
@@ -123,6 +127,7 @@ static void
 auth_context_free (AuthContext *ctx)
 {
   g_clear_object (&ctx->channel);
+  g_clear_object (&ctx->service);
   tp_clear_pointer (&ctx->auth_data, ag_auth_data_unref);
   g_clear_object (&ctx->session);
   g_clear_object (&ctx->identity);
@@ -138,6 +143,47 @@ auth_context_done (AuthContext *ctx)
   auth_context_free (ctx);
 }
 
+static void
+request_password_session_process_cb (SignonAuthSession *session,
+    GHashTable *session_data,
+    const GError *error,
+    gpointer user_data)
+{
+  AuthContext *ctx = user_data;
+
+  if (error != NULL)
+    {
+      DEBUG ("Error processing the session to request user's attention: %s",
+          error->message);
+    }
+
+  auth_context_done (ctx);
+}
+
+static void
+request_password (AuthContext *ctx)
+{
+  GHashTable *extra_params;
+
+  DEBUG ("Invalid credentials, request user action");
+
+  /* Inform SSO that the access token (or password) didn't work and it should
+   * ask user to re-grant access (or retype password). */
+  extra_params = tp_asv_new (
+      SIGNON_SESSION_DATA_UI_POLICY, G_TYPE_INT,
+          SIGNON_POLICY_REQUEST_PASSWORD,
+      NULL);
+
+  ag_auth_data_insert_parameters (ctx->auth_data, extra_params);
+
+  signon_auth_session_process (ctx->session,
+      ag_auth_data_get_parameters (ctx->auth_data),
+      ag_auth_data_get_mechanism (ctx->auth_data),
+      request_password_session_process_cb, ctx);
+
+  g_hash_table_unref (extra_params);
+}
+
 static void
 auth_cb (GObject *source,
     GAsyncResult *result,
@@ -149,33 +195,16 @@ auth_cb (GObject *source,
 
   if (!empathy_sasl_auth_finish (channel, result, &error))
     {
-      GHashTable *extra_params;
-
       DEBUG ("SASL Mechanism error: %s", error->message);
       g_clear_error (&error);
 
-      /* Inform SSO that the access token didn't work and it should ask user
-       * to re-grant access. */
-      extra_params = tp_asv_new (
-          SIGNON_SESSION_DATA_UI_POLICY, G_TYPE_INT,
-              SIGNON_POLICY_REQUEST_PASSWORD,
-          NULL);
-
-      ag_auth_data_insert_parameters (ctx->auth_data, extra_params);
-
-      signon_auth_session_process (ctx->session,
-          ag_auth_data_get_parameters (ctx->auth_data),
-          ag_auth_data_get_mechanism (ctx->auth_data),
-          NULL, NULL);
-
-      g_hash_table_unref (extra_params);
+      request_password (ctx);
     }
   else
     {
       DEBUG ("Auth on %s suceeded", tp_proxy_get_object_path (channel));
+      auth_context_done (ctx);
     }
-
-  auth_context_done (ctx);
 }
 
 static void
@@ -219,6 +248,12 @@ session_process_cb (SignonAuthSession *session,
             auth_cb, ctx);
         break;
 
+      case EMPATHY_SASL_MECHANISM_PASSWORD:
+        empathy_sasl_auth_password_async (ctx->channel,
+            tp_asv_get_string (session_data, "Secret"),
+            auth_cb, ctx);
+        break;
+
       default:
         g_assert_not_reached ();
     }
@@ -248,6 +283,37 @@ identity_query_info_cb (SignonIdentity *identity,
       ctx);
 }
 
+static void
+set_account_password_cb (GObject *source,
+    GAsyncResult *result,
+    gpointer user_data)
+{
+  TpAccount *tp_account = (TpAccount *) source;
+  AuthContext *ctx = user_data;
+  AuthContext *new_ctx;
+  GError *error = NULL;
+
+  if (!empathy_keyring_set_account_password_finish (tp_account, result, &error))
+    {
+      DEBUG ("Failed to set empty password on UOA account: %s", error->message);
+      auth_context_done (ctx);
+      return;
+    }
+
+  new_ctx = auth_context_new (ctx->channel, ctx->service);
+  auth_context_free (ctx);
+
+  if (new_ctx->session != NULL)
+    {
+      /* The trick worked! */
+      request_password (new_ctx);
+      return;
+    }
+
+  DEBUG ("Still can't get a signon session, even after setting empty pwd");
+  auth_context_done (new_ctx);
+}
+
 void
 empathy_uoa_auth_handler_start (EmpathyUoaAuthHandler *self,
     TpChannel *channel,
@@ -290,8 +356,12 @@ empathy_uoa_auth_handler_start (EmpathyUoaAuthHandler *self,
   ctx = auth_context_new (channel, service);
   if (ctx->session == NULL)
     {
+      /* This (usually?) means we never stored credentials for this account.
+       * To ask user to type his password SSO needs a SignonIdentity bound to
+       * our account. Let's store an empty password. */
       DEBUG ("Couldn't create a signon session");
-      auth_context_done (ctx);
+      empathy_keyring_set_account_password_async (tp_account, "", FALSE,
+          set_account_password_cb, ctx);
     }
   else
     {
@@ -322,5 +392,6 @@ empathy_uoa_auth_handler_supports (EmpathyUoaAuthHandler *self,
   mech = empathy_sasl_channel_select_mechanism (channel);
   return mech == EMPATHY_SASL_MECHANISM_FACEBOOK ||
       mech == EMPATHY_SASL_MECHANISM_WLM ||
-      mech == EMPATHY_SASL_MECHANISM_GOOGLE;
+      mech == EMPATHY_SASL_MECHANISM_GOOGLE ||
+      mech == EMPATHY_SASL_MECHANISM_PASSWORD;
 }