[libgdata] core: Add support for OAuth 2.0 to the GOA authoriser



commit 811ccbefe1b711a29763700a2bbb5b54b06384d5
Author: Philip Withnall <philip tecnocode co uk>
Date:   Sun Oct 21 11:54:56 2012 +0100

    core: Add support for OAuth 2.0 to the GOA authoriser
    
    This is based very heavily on work by Matthew Barnes <mbarnes redhat com> for
    EDSâ EGDataGoaAuthorizer:
     â http://git.gnome.org/browse/evolution-data-server/commit/addressbook/backends/google/e-gdata-goa-authorizer.c?id=f23f88b2b5e4662730bada1797378fbddfe7ddfa
     â http://git.gnome.org/browse/evolution-data-server/commit/addressbook/backends/google/e-gdata-goa-authorizer.c?id=870bcc9eced87f74807cfeacb16f995a797eb277
    
    As he mentions, this hasnât been tested against GOA 3.7 yet, so may well not
    work.
    
    Closes: https://bugzilla.gnome.org/show_bug.cgi?id=685289

 gdata/gdata-goa-authorizer.c |   82 +++++++++++++++++++++++++++++++++++------
 1 files changed, 70 insertions(+), 12 deletions(-)
---
diff --git a/gdata/gdata-goa-authorizer.c b/gdata/gdata-goa-authorizer.c
index 6f0c525..8b2ed65 100644
--- a/gdata/gdata-goa-authorizer.c
+++ b/gdata/gdata-goa-authorizer.c
@@ -97,8 +97,8 @@ G_DEFINE_TYPE_WITH_CODE (GDataGoaAuthorizer, gdata_goa_authorizer, G_TYPE_OBJECT
                          G_IMPLEMENT_INTERFACE (GDATA_TYPE_AUTHORIZER, gdata_goa_authorizer_interface_init))
 
 static GHashTable *
-gdata_goa_authorizer_get_parameters (SoupMessage *message, const gchar *consumer_key, const gchar *consumer_secret, const gchar *access_token,
-                                     const gchar *access_token_secret)
+gdata_goa_authorizer_get_oauth1_parameters (SoupMessage *message, const gchar *consumer_key, const gchar *consumer_secret, const gchar *access_token,
+                                            const gchar *access_token_secret)
 {
 	GString *query;
 	GString *base_string;
@@ -226,7 +226,7 @@ gdata_goa_authorizer_get_parameters (SoupMessage *message, const gchar *consumer
 }
 
 static void
-gdata_goa_authorizer_add_authorization (GDataAuthorizer *authorizer, SoupMessage *message)
+gdata_goa_authorizer_add_oauth1_authorization (GDataAuthorizer *authorizer, SoupMessage *message)
 {
 	GDataGoaAuthorizerPrivate *priv;
 	GoaOAuthBased *goa_oauth_based;
@@ -263,7 +263,8 @@ gdata_goa_authorizer_add_authorization (GDataAuthorizer *authorizer, SoupMessage
 	consumer_key = goa_oauth_based_get_consumer_key (goa_oauth_based);
 	consumer_secret = goa_oauth_based_get_consumer_secret (goa_oauth_based);
 
-	parameters = gdata_goa_authorizer_get_parameters (message, consumer_key, consumer_secret, priv->access_token, priv->access_token_secret);
+	parameters = gdata_goa_authorizer_get_oauth1_parameters (message, consumer_key, consumer_secret,
+	                                                         priv->access_token, priv->access_token_secret);
 
 	authorization = g_string_new ("OAuth ");
 
@@ -295,6 +296,48 @@ gdata_goa_authorizer_add_authorization (GDataAuthorizer *authorizer, SoupMessage
 	g_object_unref (goa_oauth_based);
 }
 
+static void
+gdata_goa_authorizer_add_oauth2_authorization (GDataAuthorizer *authorizer, SoupMessage *message)
+{
+	GDataGoaAuthorizerPrivate *priv;
+	GString *authorization;
+
+	/* This MUST be called with the mutex already locked. */
+
+	priv = GDATA_GOA_AUTHORIZER (authorizer)->priv;
+
+	/* We can't add an Authorization header without an access token. Let the request fail. GData should refresh us if it gets back a
+	 * "401 Authorization required" response from Google, and then automatically retry the request. */
+	if (priv->access_token == NULL) {
+		return;
+	}
+
+	authorization = g_string_new ("OAuth ");
+	g_string_append (authorization, priv->access_token);
+
+	/* Use replace here, not append, to make sure there's only one "Authorization" header. */
+	soup_message_headers_replace (message->request_headers, "Authorization", authorization->str);
+
+	g_string_free (authorization, TRUE);
+}
+
+static void
+gdata_goa_authorizer_add_authorization (GDataAuthorizer *authorizer, SoupMessage *message)
+{
+	GDataGoaAuthorizerPrivate *priv;
+
+	/* This MUST be called with the mutex already locked. */
+
+	priv = GDATA_GOA_AUTHORIZER (authorizer)->priv;
+
+	/* Prefer OAuth 2.0 over OAuth 1.0. */
+	if (goa_object_peek_oauth2_based (priv->goa_object) != NULL) {
+		gdata_goa_authorizer_add_oauth2_authorization (authorizer, message);
+	} else if (goa_object_peek_oauth_based (priv->goa_object) != NULL) {
+		gdata_goa_authorizer_add_oauth1_authorization (authorizer, message);
+	}
+}
+
 static gboolean
 gdata_goa_authorizer_is_authorized (GDataAuthorizer *authorizer, GDataAuthorizationDomain *domain)
 {
@@ -431,9 +474,10 @@ static gboolean
 gdata_goa_authorizer_refresh_authorization (GDataAuthorizer *authorizer, GCancellable *cancellable, GError **error)
 {
 	GDataGoaAuthorizerPrivate *priv;
-	GoaOAuthBased *goa_oauth_based;
+	GoaOAuthBased *goa_oauth1_based;
+	GoaOAuth2Based *goa_oauth2_based;
 	GoaAccount *goa_account;
-	gboolean success = TRUE;
+	gboolean success = FALSE;
 
 	priv = GDATA_GOA_AUTHORIZER (authorizer)->priv;
 
@@ -446,15 +490,29 @@ gdata_goa_authorizer_refresh_authorization (GDataAuthorizer *authorizer, GCancel
 	priv->access_token_secret = NULL;
 
 	goa_account = goa_object_get_account (priv->goa_object);
-	goa_oauth_based = goa_object_get_oauth_based (priv->goa_object);
+	goa_oauth1_based = goa_object_get_oauth_based (priv->goa_object);
+	goa_oauth2_based = goa_object_get_oauth2_based (priv->goa_object);
 
-	success &= goa_account_call_ensure_credentials_sync (goa_account, NULL, cancellable, error);
+	success = goa_account_call_ensure_credentials_sync (goa_account, NULL, cancellable, error);
 
-	success &= goa_oauth_based_call_get_access_token_sync (goa_oauth_based, &priv->access_token, &priv->access_token_secret, NULL,
-	                                                       cancellable, error);
+	if (success == FALSE) {
+		goto exit;
+	}
 
-	g_object_unref (goa_account);
-	g_object_unref (goa_oauth_based);
+	/* Prefer OAuth 2.0 over OAuth 1.0. */
+	if (goa_oauth2_based != NULL) {
+		success = goa_oauth2_based_call_get_access_token_sync (goa_oauth2_based, &priv->access_token, NULL, cancellable, error);
+	} else if (goa_oauth1_based != NULL) {
+		success = goa_oauth_based_call_get_access_token_sync (goa_oauth1_based, &priv->access_token, &priv->access_token_secret, NULL,
+		                                                      cancellable, error);
+	} else {
+		g_warn_if_reached (); /* should never happen */
+	}
+
+exit:
+	g_clear_object (&goa_account);
+	g_clear_object (&goa_oauth1_based);
+	g_clear_object (&goa_oauth2_based);
 
 	g_static_mutex_unlock (&mutex);
 



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