google-cloud-storageballerinaballerina-http

How can I authenticate and upload files to Google Cloud Storage in Ballerina without manually generating access tokens?


I'm trying to upload files to a Google Cloud Storage bucket from a Ballerina application. Right now, the only way I’ve found to authenticate is by manually generating an access token using a service-account.json file from the Google Cloud Console.

My question: Is there a way in Ballerina to:

If so, what’s the right way to do this using Ballerina’s built-in modules?

What I tried:

What I want: I’d like to programmatically authenticate using a service account key or some supported method in Ballerina, so the token can be generated or refreshed within the app.


Solution

  • As Tharindu Weerasinghe suggested, I used the Ballerina Google OAuth2 library to generate and manage access tokens with a refresh token. This allows my Ballerina application to authenticate with Google Cloud Storage (GCS) without manually generating tokens every time.

    Here’s what I did:

    1. I went through the OAuth 2.0 flow once to get a refresh_token, client_id, and client_secret.
    2. Then I used the OAuth2RefreshTokenGrantConfig provided by the Ballerina module to automatically get and refresh access tokens.
    3. I used that config directly with an http:Client to send upload requests to GCS. The auth header is handled automatically—no need to manually set the Bearer token.

    Working Code

    import ballerina/http;
    import ballerina/io;
    import ballerinax/googleapis.oauth2 as oauth2;
    
    configurable string bucket = ?;
    configurable string clientId = ?;
    configurable string clientSecret = ?;
    configurable string refreshToken = ?;
    
    oauth2:OAuth2RefreshTokenGrantConfig grantConfig = {
        clientId: clientId,
        clientSecret: clientSecret,
        refreshToken: refreshToken,
        refreshUrl: "https://oauth2.googleapis.com/token"
    };
    
    public function main() returns error? {
        byte[] fileBytes = check io:fileReadBytes("Tasks and Notifications.png");
        string objectName = "yourfile4.png";
    
        http:Client gcs = check new ("https://storage.googleapis.com", {
            auth: grantConfig
        });
    
        http:Response res = check gcs->post(
            string `/upload/storage/v1/b/${bucket}/o?uploadType=media&name=${objectName}`,
            fileBytes,
            {
                "Content-Type": "application/octet-stream"
            }
        );
    
        io:println(res.getJsonPayload());
    }
    

    Why this works well