diff options
author | Philip Withnall <philip@tecnocode.co.uk> | 2011-06-29 08:56:02 +0100 |
---|---|---|
committer | Philip Withnall <philip@tecnocode.co.uk> | 2011-06-29 08:56:02 +0100 |
commit | 5494aef7d705b9a4ad2d0da7db6dd6c0a43f9560 (patch) | |
tree | affc65b39a27fae615f065f835a971e4cf62449a /gdata | |
parent | baa8e41dd9079411e90c7ec3bd6381a24192bc06 (diff) | |
download | libgdata-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.h | 3 | ||||
-rw-r--r-- | gdata/gdata-client-login-authorizer.c | 2 | ||||
-rw-r--r-- | gdata/gdata-oauth1-authorizer.c | 2 | ||||
-rw-r--r-- | gdata/gdata-service.c | 17 |
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); |