summaryrefslogtreecommitdiff
path: root/gdata
diff options
context:
space:
mode:
authorPhilip Withnall <philip@tecnocode.co.uk>2011-06-29 08:56:02 +0100
committerPhilip Withnall <philip@tecnocode.co.uk>2011-06-29 08:56:02 +0100
commit5494aef7d705b9a4ad2d0da7db6dd6c0a43f9560 (patch)
treeaffc65b39a27fae615f065f835a971e4cf62449a /gdata
parentbaa8e41dd9079411e90c7ec3bd6381a24192bc06 (diff)
downloadlibgdata-5494aef7d705b9a4ad2d0da7db6dd6c0a43f9560.tar.gz
Bug 653535 — Let GDataAuthorizer re-process request after refreshing
After receiving a 401 status (unauthorised) from the server and refreshing the current GDataAuthorizer, re-process the message in question with the authoriser before re-sending it, so that it has updated credentials set on it. This involves a slight change in the semantics of GDataAuthorizer->process_request, which now has to handle being called multiple times on a given message. Closes: bgo#653535
Diffstat (limited to 'gdata')
-rw-r--r--gdata/gdata-authorizer.h3
-rw-r--r--gdata/gdata-client-login-authorizer.c2
-rw-r--r--gdata/gdata-oauth1-authorizer.c2
-rw-r--r--gdata/gdata-service.c17
4 files changed, 20 insertions, 4 deletions
diff --git a/gdata/gdata-authorizer.h b/gdata/gdata-authorizer.h
index 5898348f..3df0da02 100644
--- a/gdata/gdata-authorizer.h
+++ b/gdata/gdata-authorizer.h
@@ -48,7 +48,8 @@ typedef struct _GDataAuthorizer GDataAuthorizer; /* dummy typedef */
* GDataAuthorizerInterface:
* @parent: the parent type
* @process_request: a function to append authorization headers to queries before they are submitted to the online service under the given
- * authorization domain (which may be %NULL); this must be implemented and must be thread safe
+ * authorization domain (which may be %NULL); this must be implemented and must be thread safe, and must also handle being called multiple times on
+ * the same #SoupMessage instance (so must be careful to replace headers rather than append them, for example)
* @is_authorized_for_domain: a function to check whether the authorizer is authorized against the given domain; this must be implemented and must
* be thread safe
* @refresh_authorization: (allow-none): a function to force a refresh of any authorization tokens the authorizer holds, returning %TRUE if a refresh
diff --git a/gdata/gdata-client-login-authorizer.c b/gdata/gdata-client-login-authorizer.c
index ab7f66c5..ce50522d 100644
--- a/gdata/gdata-client-login-authorizer.c
+++ b/gdata/gdata-client-login-authorizer.c
@@ -401,7 +401,7 @@ process_request (GDataAuthorizer *self, GDataAuthorizationDomain *domain, SoupMe
g_warning ("Not authorizing a non-HTTPS message with the user's ClientLogin auth token as the connection isn't secure.");
} else {
gchar *authorisation_header = g_strdup_printf ("GoogleLogin auth=%s", auth_token);
- soup_message_headers_append (message->request_headers, "Authorization", authorisation_header);
+ soup_message_headers_replace (message->request_headers, "Authorization", authorisation_header);
g_free (authorisation_header);
}
}
diff --git a/gdata/gdata-oauth1-authorizer.c b/gdata/gdata-oauth1-authorizer.c
index 0b635dc4..bce48b76 100644
--- a/gdata/gdata-oauth1-authorizer.c
+++ b/gdata/gdata-oauth1-authorizer.c
@@ -558,7 +558,7 @@ sign_message (GDataOAuth1Authorizer *self, SoupMessage *message, const gchar *to
g_string_append_uri_escaped (authorization_header, nonce, NULL, FALSE);
g_string_append (authorization_header, "\",oauth_version=\"1.0\"");
- soup_message_headers_append (message->request_headers, "Authorization", authorization_header->str);
+ soup_message_headers_replace (message->request_headers, "Authorization", authorization_header->str);
g_string_free (authorization_header, TRUE);
free (signature);
diff --git a/gdata/gdata-service.c b/gdata/gdata-service.c
index 848914c9..74c0e214 100644
--- a/gdata/gdata-service.c
+++ b/gdata/gdata-service.c
@@ -284,6 +284,10 @@ real_append_query_headers (GDataService *self, GDataAuthorizationDomain *domain,
/* Set the authorisation header */
if (self->priv->authorizer != NULL) {
gdata_authorizer_process_request (self->priv->authorizer, domain, message);
+
+ /* Store the authorisation domain on the message so that we can access it again after refreshing authorisation if necessary.
+ * See _gdata_service_send_message(). */
+ g_object_set_data_full (G_OBJECT (message), "gdata-authorization-domain", g_object_ref (domain), (GDestroyNotify) g_object_unref);
}
/* Set the GData-Version header to tell it we want to use the v2 API */
@@ -680,11 +684,22 @@ _gdata_service_send_message (GDataService *self, SoupMessage *message, GCancella
}
/* Not authorised, or authorisation has expired. If we were authorised in the first place, attempt to refresh the authorisation and
- * try sending the message again (but only once, so we don't get caught in an infinite loop of denied authorisation errors). */
+ * try sending the message again (but only once, so we don't get caught in an infinite loop of denied authorisation errors).
+ *
+ * Note that we have to re-process the message with the authoriser so that its authorisation headers get updated after the refresh
+ * (bgo#653535). */
if (message->status_code == SOUP_STATUS_UNAUTHORIZED) {
GDataAuthorizer *authorizer = self->priv->authorizer;
if (authorizer != NULL && gdata_authorizer_refresh_authorization (authorizer, cancellable, NULL) == TRUE) {
+ GDataAuthorizationDomain *domain;
+
+ /* Re-process the request */
+ domain = g_object_get_data (G_OBJECT (message), "gdata-authorization-domain");
+ g_assert (domain == NULL || GDATA_IS_AUTHORIZATION_DOMAIN (domain));
+
+ gdata_authorizer_process_request (authorizer, domain, message);
+
/* Send the message again */
g_clear_error (error);
_gdata_service_actually_send_message (self->priv->session, message, cancellable, error);