From: Michael Tremer Date: Sat, 21 Jun 2025 17:09:24 +0000 (+0000) Subject: buildservice: Automatically refresh the access token on expiry X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=19b5663221c31db2b8c451bb4a577c6079805f44;p=pakfire.git buildservice: Automatically refresh the access token on expiry Signed-off-by: Michael Tremer --- diff --git a/src/pakfire/buildservice.c b/src/pakfire/buildservice.c index 03896dfd..df979caa 100644 --- a/src/pakfire/buildservice.c +++ b/src/pakfire/buildservice.c @@ -97,47 +97,6 @@ ERROR: return r; } -static int pakfire_buildservice_auth_refresh(struct pakfire_buildservice* self) { - return 0; // XXX TODO -} - -static int pakfire_buildservice_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 (now - t) < 60; -} - -static int pakfire_buildservice_xfer_auth(struct pakfire_buildservice* self, struct pakfire_xfer* xfer) { - int r; - - // Fail if not authenticated - if (!*self->access_token) - return -ENOTSUP; - - // Refresh if the access token has expired - if (pakfire_buildservice_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_buildservice_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) - return r; - - return 0; -} - static int pakfire_buildservice_set_access_token(struct pakfire_buildservice* self, const char* token) { char expires_at[1024]; int r; @@ -194,6 +153,100 @@ static int pakfire_buildservice_set_refresh_token(struct pakfire_buildservice* s return 0; } +static int pakfire_buildservice_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_buildservice_auth_refresh(struct pakfire_buildservice* self) { + struct pakfire_xfer* xfer = NULL; + struct json_object* request = NULL; + struct json_object* response = NULL; + const char* access_token = NULL; + int r; + + // Cannot do this if we don't have a refresh token + if (!*self->refresh_token) + return -ENOTSUP; + + // We cannot do this either if the refresh token has expired + else if (pakfire_buildservice_token_has_expired(self->refresh_token_expires_at)) + return -ENOTSUP; + + // Create a new transfer + r = pakfire_buildservice_xfer_create(&xfer, self, "/api/v1/auth/refresh"); + if (r < 0) + goto ERROR; + + // Create a new JSON request object + r = pakfire_json_new_object(&request); + if (r < 0) + goto ERROR; + + // Add the refresh token + r = pakfire_json_add_string(request, "refresh_token", self->refresh_token); + if (r < 0) + goto ERROR; + + // Send the request + r = pakfire_xfer_run_api_request(xfer, request, &response); + if (r < 0) + goto ERROR; + + // Extract the new access token + r = pakfire_json_get_string(response, "access_token", &access_token); + if (r < 0) { + ERROR(self->ctx, "Failed to fetch the access token: %s\n", strerror(-r)); + goto ERROR; + } + + // Store the new access token + r = pakfire_buildservice_set_access_token(self, access_token); + if (r < 0) + goto ERROR; + +ERROR: + if (xfer) + pakfire_xfer_unref(xfer); + if (request) + json_object_put(request); + if (response) + json_object_put(response); + + return r; +} + +static int pakfire_buildservice_xfer_auth(struct pakfire_buildservice* self, struct pakfire_xfer* xfer) { + int r; + + // Fail if not authenticated + if (!*self->access_token) + return -ENOTSUP; + + // Refresh if the access token has expired + if (pakfire_buildservice_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_buildservice_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) + return r; + + return 0; +} static int pakfire_buildservice_setup_auth(struct pakfire_buildservice* service) { const char* error = NULL; int r;