[evolution-data-server] Bug 771547 - Internal Google OAuth2 authentication fails with expired token
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] Bug 771547 - Internal Google OAuth2 authentication fails with expired token
- Date: Tue, 20 Sep 2016 10:30:02 +0000 (UTC)
commit eaf719213b7f0e052b1e535e87b00eea8b6c5719
Author: Milan Crha <mcrha redhat com>
Date: Tue Sep 20 12:29:48 2016 +0200
Bug 771547 - Internal Google OAuth2 authentication fails with expired token
calendar/backends/caldav/e-cal-backend-caldav.c | 2 +-
libedataserver/e-data-server-util.c | 16 +++++++++---
.../e-source-credentials-provider-impl-google.c | 2 +-
.../e-credentials-prompter-impl-google.c | 27 ++++++++++++++++++-
libedataserverui/e-credentials-prompter.c | 16 +++++++++--
5 files changed, 52 insertions(+), 11 deletions(-)
---
diff --git a/calendar/backends/caldav/e-cal-backend-caldav.c b/calendar/backends/caldav/e-cal-backend-caldav.c
index 53f7d0e..bebd87e 100644
--- a/calendar/backends/caldav/e-cal-backend-caldav.c
+++ b/calendar/backends/caldav/e-cal-backend-caldav.c
@@ -697,7 +697,7 @@ status_code_to_result (SoupMessage *message,
gchar *body = g_strndup (message->response_body->data,
message->response_body->length);
/* Do not localize this string, it is returned by the server. */
- if (body && (e_util_strstrcase (body, "Daily Limit Exceeded") ||
+ if (body && (e_util_strstrcase (body, "Daily Limit") ||
e_util_strstrcase (body, "https://console.developers.google.com/"))) {
/* Special-case this condition and provide this error up to the UI. */
g_propagate_error (perror,
diff --git a/libedataserver/e-data-server-util.c b/libedataserver/e-data-server-util.c
index 60bb63d..63dc300 100644
--- a/libedataserver/e-data-server-util.c
+++ b/libedataserver/e-data-server-util.c
@@ -2915,10 +2915,18 @@ e_util_get_source_oauth2_access_token_sync (ESource *source,
source, cancellable, out_access_token,
out_expires_in_seconds, error);
} else if (g_strcmp0 (auth_method, "Google") == 0) {
- success = TRUE;
-
- e_source_credentials_google_util_extract_from_credentials (
- credentials, out_access_token, out_expires_in_seconds);
+ gint expires_in_seconds = -1;
+
+ success = e_source_credentials_google_util_extract_from_credentials (
+ credentials, out_access_token, &expires_in_seconds);
+ if (!success || expires_in_seconds <= 0) {
+ /* Ask to refresh the token, if it's expired */
+ e_source_invoke_credentials_required_sync (source,
+ expires_in_seconds < 0 ? E_SOURCE_AUTHENTICATION_REQUIRED :
E_SOURCE_AUTHENTICATION_REJECTED,
+ NULL, 0, NULL, cancellable, error);
+ } else if (out_expires_in_seconds) {
+ *out_expires_in_seconds = expires_in_seconds;
+ }
}
g_free (auth_method);
diff --git a/libedataserver/e-source-credentials-provider-impl-google.c
b/libedataserver/e-source-credentials-provider-impl-google.c
index 5761a17..7aecf47 100644
--- a/libedataserver/e-source-credentials-provider-impl-google.c
+++ b/libedataserver/e-source-credentials-provider-impl-google.c
@@ -465,7 +465,7 @@ e_source_credentials_google_util_extract_from_credentials (const ENamedParameter
if (out_expires_in_seconds) {
now = g_get_real_time () / G_USEC_PER_SEC;
- if (now < expires_after_tm)
+ if (now > expires_after_tm)
now = expires_after_tm;
*out_expires_in_seconds = (gint) (expires_after_tm - now);
diff --git a/libedataserverui/e-credentials-prompter-impl-google.c
b/libedataserverui/e-credentials-prompter-impl-google.c
index 2acfeb2..f968d7a 100644
--- a/libedataserverui/e-credentials-prompter-impl-google.c
+++ b/libedataserverui/e-credentials-prompter-impl-google.c
@@ -291,9 +291,9 @@ cpi_google_update_prompter_credentials (GWeakRef *prompter_google_wr,
success = TRUE;
}
- g_object_unref (prompter_google);
g_free (secret);
}
+ g_clear_object (&prompter_google);
g_free (expires_after);
@@ -332,8 +332,10 @@ e_credentials_prompter_impl_google_finish_dialog_idle_cb (gpointer user_data)
g_return_val_if_fail (E_IS_CREDENTIALS_PROMPTER_IMPL_GOOGLE (prompter_google), FALSE);
+ g_mutex_lock (&prompter_google->priv->property_lock);
if (g_source_get_id (g_main_current_source ()) == prompter_google->priv->show_dialog_idle_id) {
prompter_google->priv->show_dialog_idle_id = 0;
+ g_mutex_unlock (&prompter_google->priv->property_lock);
g_warn_if_fail (prompter_google->priv->dialog != NULL);
@@ -343,6 +345,8 @@ e_credentials_prompter_impl_google_finish_dialog_idle_cb (gpointer user_data)
e_credentials_prompter_impl_google_show_html (prompter_google->priv->web_view,
"Finished with error", prompter_google->priv->error_text);
}
+ } else {
+ g_mutex_unlock (&prompter_google->priv->property_lock);
}
return FALSE;
@@ -442,9 +446,11 @@ cpi_google_get_access_token_thread (gpointer user_data)
GOOGLE_TOKEN_URI, soup_status, soup_status_get_phrase (soup_status));
}
+ g_mutex_lock (&prompter_google->priv->property_lock);
prompter_google->priv->show_dialog_idle_id = g_idle_add (
e_credentials_prompter_impl_google_finish_dialog_idle_cb,
prompter_google);
+ g_mutex_unlock (&prompter_google->priv->property_lock);
}
g_clear_object (&prompter_google);
@@ -843,10 +849,12 @@ e_credentials_prompter_impl_google_manage_dialog_idle_cb (gpointer user_data)
g_return_val_if_fail (E_IS_CREDENTIALS_PROMPTER_IMPL_GOOGLE (prompter_google), FALSE);
+ g_mutex_lock (&prompter_google->priv->property_lock);
if (g_source_get_id (g_main_current_source ()) == prompter_google->priv->show_dialog_idle_id) {
gboolean success;
prompter_google->priv->show_dialog_idle_id = 0;
+ g_mutex_unlock (&prompter_google->priv->property_lock);
g_warn_if_fail (prompter_google->priv->dialog == NULL);
@@ -861,6 +869,8 @@ e_credentials_prompter_impl_google_manage_dialog_idle_cb (gpointer user_data)
success ? prompter_google->priv->credentials : NULL);
e_credentials_prompter_impl_google_free_prompt_data (prompter_google);
+ } else {
+ g_mutex_unlock (&prompter_google->priv->property_lock);
}
return FALSE;
@@ -942,9 +952,11 @@ cpi_google_check_existing_token_thread (gpointer user_data)
exit:
prompter_google = g_weak_ref_get (td->prompter_google);
if (prompter_google && !g_cancellable_is_cancelled (cancellable)) {
+ g_mutex_lock (&prompter_google->priv->property_lock);
prompter_google->priv->show_dialog_idle_id = g_idle_add (
e_credentials_prompter_impl_google_manage_dialog_idle_cb,
prompter_google);
+ g_mutex_unlock (&prompter_google->priv->property_lock);
}
g_clear_object (&prompter_google);
@@ -970,7 +982,14 @@ e_credentials_prompter_impl_google_process_prompt (ECredentialsPrompterImpl *pro
prompter_google = E_CREDENTIALS_PROMPTER_IMPL_GOOGLE (prompter_impl);
g_return_if_fail (prompter_google->priv->prompt_id == NULL);
- g_return_if_fail (prompter_google->priv->show_dialog_idle_id == 0);
+
+ g_mutex_lock (&prompter_google->priv->property_lock);
+ if (prompter_google->priv->show_dialog_idle_id != 0) {
+ g_mutex_unlock (&prompter_google->priv->property_lock);
+ g_warning ("%s: Already processing other prompt", G_STRFUNC);
+ return;
+ }
+ g_mutex_unlock (&prompter_google->priv->property_lock);
prompter_google->priv->prompt_id = prompt_id;
prompter_google->priv->auth_source = g_object_ref (auth_source);
@@ -1021,9 +1040,11 @@ e_credentials_prompter_impl_google_process_prompt (ECredentialsPrompterImpl *pro
g_thread_unref (thread);
} else {
#endif /* ENABLE_GOOGLE_AUTH */
+ g_mutex_lock (&prompter_google->priv->property_lock);
prompter_google->priv->show_dialog_idle_id = g_idle_add (
e_credentials_prompter_impl_google_manage_dialog_idle_cb,
prompter_google);
+ g_mutex_unlock (&prompter_google->priv->property_lock);
#ifdef ENABLE_GOOGLE_AUTH
}
#endif /* ENABLE_GOOGLE_AUTH */
@@ -1053,10 +1074,12 @@ e_credentials_prompter_impl_google_dispose (GObject *object)
{
ECredentialsPrompterImplGoogle *prompter_google = E_CREDENTIALS_PROMPTER_IMPL_GOOGLE (object);
+ g_mutex_lock (&prompter_google->priv->property_lock);
if (prompter_google->priv->show_dialog_idle_id) {
g_source_remove (prompter_google->priv->show_dialog_idle_id);
prompter_google->priv->show_dialog_idle_id = 0;
}
+ g_mutex_unlock (&prompter_google->priv->property_lock);
if (prompter_google->priv->cancellable) {
g_cancellable_cancel (prompter_google->priv->cancellable);
diff --git a/libedataserverui/e-credentials-prompter.c b/libedataserverui/e-credentials-prompter.c
index 40c39a7..1e0458e 100644
--- a/libedataserverui/e-credentials-prompter.c
+++ b/libedataserverui/e-credentials-prompter.c
@@ -152,7 +152,7 @@ credentials_prompter_lookup_source_details_thread (GTask *task,
provider = e_credentials_prompter_get_provider (prompter);
cred_source = e_source_credentials_provider_ref_credentials_source (provider, source);
- e_source_credentials_provider_lookup_sync (prompter->priv->provider, cred_source ? cred_source :
source, cancellable, &credentials, &local_error);
+ e_source_credentials_provider_lookup_sync (provider, cred_source ? cred_source : source, cancellable,
&credentials, &local_error);
/* Interested only in the cancelled error, which means the prompter is freed. */
if (local_error != NULL && g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
@@ -760,19 +760,29 @@ credentials_prompter_credentials_required_cb (ESourceRegistry *registry,
const GError *op_error,
ECredentialsPrompter *prompter)
{
+ ESource *cred_source;
+
g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
g_return_if_fail (E_IS_SOURCE (source));
g_return_if_fail (E_IS_CREDENTIALS_PROMPTER (prompter));
/* Only these two reasons are meant to be used to prompt the user for credentials. */
if (reason != E_SOURCE_CREDENTIALS_REASON_REQUIRED &&
- reason != E_SOURCE_CREDENTIALS_REASON_REJECTED)
+ reason != E_SOURCE_CREDENTIALS_REASON_REJECTED) {
return;
+ }
+
+ cred_source = e_source_credentials_provider_ref_credentials_source
(e_credentials_prompter_get_provider (prompter), source);
/* Global auto-prompt or the source's auto-prompt is disabled. */
if (!e_credentials_prompter_get_auto_prompt (prompter) ||
- e_credentials_prompter_get_auto_prompt_disabled_for (prompter, source))
+ (e_credentials_prompter_get_auto_prompt_disabled_for (prompter, source) &&
+ (!cred_source || e_credentials_prompter_get_auto_prompt_disabled_for (prompter, cred_source)))) {
+ g_clear_object (&cred_source);
return;
+ }
+
+ g_clear_object (&cred_source);
/* This is a re-prompt, but the source cannot be prompted for credentials. */
if (reason == E_SOURCE_CREDENTIALS_REASON_REJECTED &&
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]