From: Michael Tremer Date: Tue, 24 Jun 2025 16:10:51 +0000 (+0000) Subject: client: Fire a timer just before the access token expires X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=12e4783a4c19dd290768008e18b763320945ae4f;p=pakfire.git client: Fire a timer just before the access token expires Signed-off-by: Michael Tremer --- diff --git a/src/pakfire/client.c b/src/pakfire/client.c index 289ef878..88475a40 100644 --- a/src/pakfire/client.c +++ b/src/pakfire/client.c @@ -37,6 +37,7 @@ #include #include #include +#include #include struct pakfire_client { @@ -63,9 +64,7 @@ struct pakfire_client { // Tokens char access_token[1024]; - time_t access_token_expires_at; char refresh_token[1024]; - time_t refresh_token_expires_at; // Callbacks struct pakfire_client_auth_callback { @@ -110,74 +109,6 @@ ERROR: return r; } -static int pakfire_client_set_access_token(struct pakfire_client* self, const char* token) { - char expires_at[1024]; - int r; - - // Store the token - r = pakfire_string_set(self->access_token, token); - if (r < 0) - return r; - - // Fetch the expiry time - self->access_token_expires_at = pakfire_jwt_expires_at(self->access_token); - if (self->access_token_expires_at < 0) { - ERROR(self->ctx, "Failed to fetch the JWT expiry time: %s\n", strerror(-r)); - return self->access_token_expires_at; - } - - // Format the expiry time - r = pakfire_strftime(expires_at, "%Y-%m-%dT%H:%M:%SZ", self->access_token_expires_at); - if (r < 0) - return r; - - // Log action - DEBUG(self->ctx, "Set access token: %s\n", self->access_token); - DEBUG(self->ctx, " Expires: %s\n", expires_at); - - return 0; -} - -static int pakfire_client_set_refresh_token(struct pakfire_client* self, const char* token) { - char expires_at[1024]; - int r; - - // Store the token - r = pakfire_string_set(self->refresh_token, token); - if (r < 0) - return r; - - // Fetch the expiry time - self->refresh_token_expires_at = pakfire_jwt_expires_at(self->refresh_token); - if (self->refresh_token_expires_at < 0) { - ERROR(self->ctx, "Failed to fetch the JWT expiry time: %s\n", strerror(-r)); - return self->refresh_token_expires_at; - } - - // Format the expiry time - r = pakfire_strftime(expires_at, "%Y-%m-%dT%H:%M:%SZ", self->refresh_token_expires_at); - if (r < 0) - return r; - - // Log action - DEBUG(self->ctx, "Set refresh token: %s\n", self->refresh_token); - DEBUG(self->ctx, " Expires: %s\n", expires_at); - - return 0; -} - -static int pakfire_client_token_has_expired(const time_t t) { - time_t now = -1; - - // Fetch the current time - now = time(NULL); - if (now < 0) - return -errno; - - // We consider the token as expired if there are less than 60 seconds left - return (t - now) < 60; -} - static int pakfire_client_auth_refresh(struct pakfire_client* self) { struct pakfire_xfer* xfer = NULL; struct json_object* request = NULL; @@ -189,10 +120,6 @@ static int pakfire_client_auth_refresh(struct pakfire_client* self) { if (!*self->refresh_token) return -ENOTSUP; - // We cannot do this either if the refresh token has expired - else if (pakfire_client_token_has_expired(self->refresh_token_expires_at)) - return -ENOTSUP; - // Create a new transfer r = pakfire_client_xfer_create(&xfer, self, "/api/v1/auth/refresh"); if (r < 0) @@ -221,7 +148,7 @@ static int pakfire_client_auth_refresh(struct pakfire_client* self) { } // Store the new access token - r = pakfire_client_set_access_token(self, access_token); + r = pakfire_string_set(self->access_token, access_token); if (r < 0) goto ERROR; @@ -251,16 +178,6 @@ static int pakfire_client_xfer_auth(struct pakfire_client* self, struct pakfire_ if (!*self->access_token) return -ENOTSUP; - // Refresh if the access token has expired - if (pakfire_client_token_has_expired(self->access_token_expires_at)) { - DEBUG(self->ctx, "The access token has expired. Trying to refresh...\n"); - - // Refresh the access token - r = pakfire_client_auth_refresh(self); - if (r < 0) - return r; - } - // Set the access token r = pakfire_xfer_add_header(xfer, "Authorization: Bearer %s", self->access_token); if (r < 0) @@ -380,6 +297,7 @@ static int pakfire_client_auth_successful( struct pakfire_client* self, struct json_object* response) { const char* refresh_token = NULL; const char* access_token = NULL; + time_t expires_at = -1; int r; // Log action @@ -400,12 +318,29 @@ static int pakfire_client_auth_successful( } // Store the access token - r = pakfire_client_set_access_token(self, access_token); + r = pakfire_string_set(self->access_token, access_token); if (r < 0) return r; // Store the refresh token - r = pakfire_client_set_refresh_token(self, refresh_token); + r = pakfire_string_set(self->refresh_token, refresh_token); + if (r < 0) + return r; + + // Extract the expiry time of the access token + expires_at = r = pakfire_jwt_expires_at(self->access_token); + if (expires_at < 0) { + ERROR(self->ctx, "Failed to fetch the expiry time of the access token: %s\n", strerror(-r)); + return r; + } + + // Call the timer just before the access token expires + r = sd_event_source_set_time(self->auth.timer, S_TO_US(expires_at - 60)); + if (r < 0) + return r; + + // Enable the timer to fire once + r = sd_event_source_set_enabled(self->auth.timer, SD_EVENT_ONESHOT); if (r < 0) return r;