[gnome-online-accounts/wip/gnome-3-8-backport: 3/4] oauth2: Adapt to changes in the redirect URI used by Facebook



commit 0fb8de3620b23580fba9d08faeac7a0b543bc229
Author: Debarshi Ray <debarshir gnome org>
Date:   Fri Oct 18 13:34:02 2013 +0200

    oauth2: Adapt to changes in the redirect URI used by Facebook
    
    Once the user has logged into the embedded web view and granted
    permissions, Facebook tries to redirect us to an URI of the form:
      <get_redirect_uri>?#access_token=...
    
    Earlier this used to be of the form:
      <get_redirect_uri>#access_token=...
    
    This confuses the navigation-policy-decision-requested handler to think
    that Facebook is using the query part of the URI to return the
    authorization code, which we will exchange for the access token. In
    reality Facebook is still using the fragment to directly give us the
    access token.
    
    Therefore, lets first look at the fragment, and then the query.
    
    According to the OAuth2 specification, the error is always passed in
    the query component of the URI. So, if we failed to obtain the
    authorization code or the access token, we should look at the query to
    ascertain the cause of the error. See 4.1.2.1 for more information:
    https://tools.ietf.org/html/draft-ietf-oauth-v2-23
    
    Fixes: https://bugzilla.gnome.org/710363

 src/goabackend/goaoauth2provider.c |   95 +++++++++++++++---------------------
 1 files changed, 39 insertions(+), 56 deletions(-)
---
diff --git a/src/goabackend/goaoauth2provider.c b/src/goabackend/goaoauth2provider.c
index c05da8e..5ce052f 100644
--- a/src/goabackend/goaoauth2provider.c
+++ b/src/goabackend/goaoauth2provider.c
@@ -811,6 +811,7 @@ on_web_view_navigation_policy_decision_requested (WebKitWebView             *web
                                                   gpointer                   user_data)
 {
   IdentifyData *data = user_data;
+  GHashTable *key_value_pairs;
   SoupMessage *message;
   SoupURI *uri;
   const gchar *fragment;
@@ -833,44 +834,13 @@ on_web_view_navigation_policy_decision_requested (WebKitWebView             *web
   query = soup_uri_get_query (uri);
 
   /* Two cases:
-   * 1) we can have either the auth code in the query part of the
-   *    URI, with which we'll obtain the token, or
-   * 2) the access_token and other information directly in the
-   *    fragment part of the URI.
+   * 1) we can either have the access_token and other information
+   *    directly in the fragment part of the URI, or
+   * 2) the auth code can be in the query part of the URI, with which
+   *    we'll obtain the token later.
    */
-  if (query != NULL)
-    {
-      GHashTable *key_value_pairs;
-
-      key_value_pairs = soup_form_decode (query);
-
-      data->authorization_code = g_strdup (g_hash_table_lookup (key_value_pairs, "code"));
-      if (data->authorization_code != NULL)
-        {
-          response_id = GTK_RESPONSE_OK;
-        }
-      else
-        {
-          oauth2_error = (const gchar *) g_hash_table_lookup (key_value_pairs, "error");
-          if (g_strcmp0 (oauth2_error, GOA_OAUTH2_ACCESS_DENIED) == 0)
-            response_id = GTK_RESPONSE_CANCEL;
-          else
-            {
-              g_set_error (&priv->error,
-                           GOA_ERROR,
-                           GOA_ERROR_NOT_AUTHORIZED,
-                           _("Authorization response was \"%s\""),
-                           oauth2_error);
-              response_id = GTK_RESPONSE_CLOSE;
-            }
-        }
-      g_hash_table_unref (key_value_pairs);
-      goto ignore_request;
-    }
-  else if (fragment != NULL)
+  if (fragment != NULL)
     {
-      GHashTable *key_value_pairs;
-
       /* fragment is encoded into a key/value pairs for the token and
        * expiration values, using the same syntax as a URL query */
       key_value_pairs = soup_form_decode (fragment);
@@ -895,31 +865,44 @@ on_web_view_navigation_policy_decision_requested (WebKitWebView             *web
 
           response_id = GTK_RESPONSE_OK;
         }
-      else
-        {
-          oauth2_error = (const gchar *) g_hash_table_lookup (key_value_pairs, "error");
-          if (g_strcmp0 (oauth2_error, GOA_OAUTH2_ACCESS_DENIED) == 0)
-            response_id = GTK_RESPONSE_CANCEL;
-          else
-            {
-              g_set_error (&data->error,
-                           GOA_ERROR,
-                           GOA_ERROR_NOT_AUTHORIZED,
-                           _("Authorization response was \"%s\""),
-                           oauth2_error);
-              response_id = GTK_RESPONSE_CLOSE;
-            }
-        }
       g_hash_table_unref (key_value_pairs);
-      goto ignore_request;
     }
+
+  if (priv->access_token != NULL)
+    goto ignore_request;
+
+  if (query != NULL)
+    {
+      key_value_pairs = soup_form_decode (query);
+
+      priv->authorization_code = g_strdup (g_hash_table_lookup (key_value_pairs, "code"));
+      if (priv->authorization_code != NULL)
+        response_id = GTK_RESPONSE_OK;
+
+      g_hash_table_unref (key_value_pairs);
+    }
+
+  if (priv->authorization_code != NULL)
+    goto ignore_request;
+
+  /* In case we don't find the access_token or auth code, then look
+   * for the error in the query part of the URI.
+   */
+  key_value_pairs = soup_form_decode (query);
+  oauth2_error = (const gchar *) g_hash_table_lookup (key_value_pairs, "error");
+  if (g_strcmp0 (oauth2_error, GOA_OAUTH2_ACCESS_DENIED) == 0)
+    response_id = GTK_RESPONSE_CANCEL;
   else
     {
-      /* this actually means that something unexpected happened, either we
-       * did something wrong or the provider's flow changed */
-      goa_debug ("URI format not recognized, DEFAULT BEHAVIOUR");
-      goto default_behaviour;
+      g_set_error (&priv->error,
+                   GOA_ERROR,
+                   GOA_ERROR_NOT_AUTHORIZED,
+                   _("Authorization response was \"%s\""),
+                   oauth2_error);
+      response_id = GTK_RESPONSE_CLOSE;
     }
+  g_hash_table_unref (key_value_pairs);
+  goto ignore_request;
 
  ignore_request:
   gtk_dialog_response (data->dialog, response_id);


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