diff options
author | Milan Crha <mcrha@redhat.com> | 2023-01-04 13:43:00 +0100 |
---|---|---|
committer | Milan Crha <mcrha@redhat.com> | 2023-01-04 13:43:00 +0100 |
commit | 120058e4e92d762e5e86bbd77db8acfa1f0de238 (patch) | |
tree | 772c4ab97cb6c353f5822323cf421d0dcdd72ffb | |
parent | 640cc8675d48f69e7e9ffabde5a4c1c9d7b7222f (diff) | |
download | evolution-data-server-120058e4e92d762e5e86bbd77db8acfa1f0de238.tar.gz |
ews-I#208 - Prompting for password too often
Closes https://gitlab.gnome.org/GNOME/evolution-ews/-/issues/208
-rw-r--r-- | src/libedataserver/e-oauth2-service.c | 10 | ||||
-rw-r--r-- | src/libedataserver/e-soup-auth-bearer.c | 5 | ||||
-rw-r--r-- | src/libedataserver/e-soup-session.c | 48 |
3 files changed, 55 insertions, 8 deletions
diff --git a/src/libedataserver/e-oauth2-service.c b/src/libedataserver/e-oauth2-service.c index 778378118..b0c24103f 100644 --- a/src/libedataserver/e-oauth2-service.c +++ b/src/libedataserver/e-oauth2-service.c @@ -42,6 +42,10 @@ #include "e-oauth2-service.h" +/* How many seconds earlier than reported by the server is the token considered expired + and will be refreshed. */ +#define TOKEN_VALIDITY_GAP_SECS 10 + G_DEFINE_INTERFACE (EOAuth2Service, e_oauth2_service, G_TYPE_OBJECT) static gboolean @@ -1705,7 +1709,9 @@ e_oauth2_service_get_access_token_sync (EOAuth2Service *service, G_LOCK (access_token_requests); resp = eos_wait_for_access_token_request_locked (source, out_access_token, out_expires_in, cancellable, error); - if (resp != RESPONSE_UNKNOWN) { + if (resp != RESPONSE_UNKNOWN && resp != RESPONSE_FAILURE && *out_expires_in <= TOKEN_VALIDITY_GAP_SECS) { + *out_expires_in = 0; + } else if (resp != RESPONSE_UNKNOWN) { G_UNLOCK (access_token_requests); return resp != RESPONSE_FAILURE; @@ -1723,7 +1729,7 @@ e_oauth2_service_get_access_token_sync (EOAuth2Service *service, return FALSE; } - if (local_expires_in <= 0 && refresh_token) { + if (local_expires_in <= TOKEN_VALIDITY_GAP_SECS && refresh_token) { success = e_oauth2_service_refresh_and_store_token_sync (service, source, refresh_token, ref_source, ref_source_user_data, cancellable, &local_error); diff --git a/src/libedataserver/e-soup-auth-bearer.c b/src/libedataserver/e-soup-auth-bearer.c index f88a10a24..ccf0136d2 100644 --- a/src/libedataserver/e-soup-auth-bearer.c +++ b/src/libedataserver/e-soup-auth-bearer.c @@ -42,6 +42,9 @@ #define EXPIRY_INVALID ((time_t) -1) +/* How many seconds earlier than reported by the server is the token considered expired. */ +#define TOKEN_VALIDITY_GAP_SECS 5 + struct _ESoupAuthBearerPrivate { GMutex property_lock; gchar *access_token; @@ -288,7 +291,7 @@ e_soup_auth_bearer_set_access_token (ESoupAuthBearer *bearer, } if (expires_in_seconds > 0) - bearer->priv->expiry = time (NULL) + expires_in_seconds - 5; + bearer->priv->expiry = time (NULL) + expires_in_seconds - TOKEN_VALIDITY_GAP_SECS; else bearer->priv->expiry = EXPIRY_INVALID; diff --git a/src/libedataserver/e-soup-session.c b/src/libedataserver/e-soup-session.c index 1a861c3f8..f6645aea6 100644 --- a/src/libedataserver/e-soup-session.c +++ b/src/libedataserver/e-soup-session.c @@ -1264,6 +1264,8 @@ typedef struct _AsyncSendData { gulong restarted_id; gchar *certificate_pem; GTlsCertificateFlags certificate_errors; + gint io_priority; + gboolean caught_bearer_expired; } AsyncSendData; static void @@ -1395,6 +1397,7 @@ e_soup_session_send_message_ready_cb (GObject *source_object, SoupMessage *message; GInputStream *input_stream; GError *local_error = NULL; + gboolean caught_bearer_expired = FALSE; g_return_if_fail (asd != NULL); @@ -1426,14 +1429,36 @@ e_soup_session_send_message_ready_cb (GObject *source_object, g_rec_mutex_unlock (&esession->priv->session_lock); - if (local_error) { - g_task_return_error (asd->task, local_error); + if (message && soup_message_get_status (message) == SOUP_STATUS_UNAUTHORIZED && !asd->caught_bearer_expired) { + g_mutex_lock (&esession->priv->property_lock); + if (esession->priv->using_bearer_auth && e_soup_auth_bearer_is_expired (esession->priv->using_bearer_auth)) { + g_signal_emit_by_name (message, "restarted"); + asd->caught_bearer_expired = TRUE; + caught_bearer_expired = TRUE; + } + g_mutex_unlock (&esession->priv->property_lock); + } + + if (caught_bearer_expired) { + g_clear_error (&local_error); g_clear_object (&input_stream); + + g_rec_mutex_lock (&esession->priv->session_lock); + + soup_session_send_async (session, message, asd->io_priority, g_task_get_cancellable (asd->task), + e_soup_session_send_message_ready_cb, asd); + + g_rec_mutex_unlock (&esession->priv->session_lock); } else { - g_task_return_pointer (asd->task, input_stream, g_object_unref); - } + if (local_error) { + g_task_return_error (asd->task, local_error); + g_clear_object (&input_stream); + } else { + g_task_return_pointer (asd->task, input_stream, g_object_unref); + } - g_object_unref (asd->task); + g_object_unref (asd->task); + } } /** @@ -1475,6 +1500,8 @@ e_soup_session_send_message (ESoupSession *session, asd->session = g_object_ref (session); asd->task = g_task_new (session, cancellable, callback, user_data); + asd->caught_bearer_expired = FALSE; + asd->io_priority = io_priority; g_task_set_source_tag (asd->task, e_soup_session_send_message); g_task_set_task_data (asd->task, asd, async_send_data_free); @@ -1581,6 +1608,7 @@ e_soup_session_send_message_sync (ESoupSession *session, { GInputStream *input_stream; gboolean redirected; + gboolean caught_bearer_expired = FALSE; gint resend_count = 0; gulong authenticate_id = 0; gulong restarted_id = 0; @@ -1644,6 +1672,16 @@ e_soup_session_send_message_sync (ESoupSession *session, } } } + } else if (soup_message_get_status (message) == SOUP_STATUS_UNAUTHORIZED && !caught_bearer_expired) { + g_mutex_lock (&session->priv->property_lock); + if (session->priv->using_bearer_auth && e_soup_auth_bearer_is_expired (session->priv->using_bearer_auth)) { + g_signal_emit_by_name (message, "restarted"); + resend_count++; + redirected = TRUE; + caught_bearer_expired = TRUE; + g_clear_error (&local_error); + } + g_mutex_unlock (&session->priv->property_lock); } } |