summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMilan Crha <mcrha@redhat.com>2023-01-04 13:43:00 +0100
committerMilan Crha <mcrha@redhat.com>2023-01-04 13:43:00 +0100
commit120058e4e92d762e5e86bbd77db8acfa1f0de238 (patch)
tree772c4ab97cb6c353f5822323cf421d0dcdd72ffb /src
parent640cc8675d48f69e7e9ffabde5a4c1c9d7b7222f (diff)
downloadevolution-data-server-120058e4e92d762e5e86bbd77db8acfa1f0de238.tar.gz
ews-I#208 - Prompting for password too often
Closes https://gitlab.gnome.org/GNOME/evolution-ews/-/issues/208
Diffstat (limited to 'src')
-rw-r--r--src/libedataserver/e-oauth2-service.c10
-rw-r--r--src/libedataserver/e-soup-auth-bearer.c5
-rw-r--r--src/libedataserver/e-soup-session.c48
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);
}
}