]> git.ipfire.org Git - pakfire.git/commitdiff
client: Fire a timer just before the access token expires
authorMichael Tremer <michael.tremer@ipfire.org>
Tue, 24 Jun 2025 16:10:51 +0000 (16:10 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Tue, 24 Jun 2025 16:10:51 +0000 (16:10 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/pakfire/client.c

index 289ef8780f145f2a40412ea7871b84fa35f1f027..88475a400bedf70aec2f4c7543a21b323da787c3 100644 (file)
@@ -37,6 +37,7 @@
 #include <pakfire/os.h>
 #include <pakfire/path.h>
 #include <pakfire/string.h>
+#include <pakfire/util.h>
 #include <pakfire/xfer.h>
 
 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;