From Vertex AI SDK to Google Gen AI SDK: Service Account Authentication for Python and Go


On June 25th, 2025, Google sent an important announcement to all Vertex AI users: the Google Gen AI SDK has become the new preferred method for accessing generative models on Vertex AI. While Google provided a Vertex AI SDK migration guide to help with the transition, there’s a critical gap in the documentation—it doesn’t adequately cover authentication using service accounts, which many production applications rely on.

The Migration Guide Gap

Google’s announcement included a helpful comparison table showing the SDK replacements for different programming languages. This article focuses on the two most commonly used languages in cloud applications: Python and Go.

Language Vertex AI SDKs Replacement Google Gen AI SDKs
Python google-cloud-aiplatform google-genai
Go cloud.google.com/go/vertexai/genai google.golang.org/genai

The official migration guide uses a straightforward before-and-after approach, showing you exactly how to update your existing code. However, there’s a significant limitation: it primarily focuses on Application Default Credentials (ADC).

Here’s where many developers get stuck: If your application uses a JSON Service Account for authentication—a common pattern in production environments—the official guide leaves you without clear direction. Following the migration steps blindly will result in authentication failures that can be frustrating to debug.

The following sections provide the missing pieces to successfully migrate your service account-based authentication in both Python and Go.

Python

For Python applications, migrating service account authentication requires creating a Credentials object using the google.oauth2.service_account package. The key insight here is that OAuth2 scopes are critical—without the correct scopes, Google’s servers will reject your requests with authentication errors.

    from google import genai
    from google.genai import types
    from google.oauth2.service_account import Credentials

    # Define the OAuth2 scopes required for accessing Google Cloud Platform
    scopes = [
        "https://www.googleapis.com/auth/cloud-platform",
    ]
    
    # Create credentials from the service account JSON file with the required scopes
    credentials = Credentials.from_service_account_file(
        os.getenv("SERVICE_ACCOUNT_FILE_PATH"), scopes=scopes
    )
    
    # Create the Gen AI Client specifying the location by env var
    # and use the project ID from environment variables
    client = genai.Client(
        vertexai=True,
        project=os.getenv("GCLOUD_PROJECT_ID"),
        location=os.getenv("GCLOUD_LOCATION"),
        credentials=credentials,
    )

This approach leverages Python’s convenient from_service_account_file() method, which automatically handles the JSON parsing and credential creation. The environment variables (SERVICE_ACCOUNT_FILE_PATH, GCLOUD_PROJECT_ID, GCLOUD_LOCATION) should point to your service account JSON file path, Google Cloud project ID, and preferred region respectively.

Go

Go requires a more hands-on approach since there’s no equivalent to Python’s convenient from_service_account_file() function. Instead, we need to manually parse the service account JSON and construct a credential object with its own OAuth2 token provider.


import (
    "fmt"
    "json"
    "os"

    "cloud.google.com/go/auth"
    "google.golang.org/genai"
)

// ...

// Get the service account content
key, err := os.ReadFile(os.getenv("SERVICE_ACCOUNT_FILE_PATH"))
if err != nil {
    return fmt.Errorf("failed to read service account key: %s", err)
    
}

var serviceAccount struct {
    ClientEmail string `json:"client_email"`
    PrivateKey  string `json:"private_key"`
    TokenURI    string `json:"token_uri"`
    ProjectID   string `json:"project_id"`
}
if err := json.Unmarshal(key, &serviceAccount); err != nil {
    return fmt.Errorf("invalid service-account JSON: %s", err)
}

// Create the 2-legged OAuth token provider
tp, err := auth.New2LOTokenProvider(&auth.Options2LO{
    Email:      serviceAccount.ClientEmail,
    PrivateKey: []byte(serviceAccount.PrivateKey),
    TokenURL:   serviceAccount.TokenURI,
    Scopes:     []string{"https://www.googleapis.com/auth/cloud-platform"},
})
if err != nil {
    return fmt.Errorf("failed to create 2LO token provider: %s", err)
}

// Create the credentials using the token provider
credentials := auth.NewCredentials(&auth.CredentialsOptions{
    TokenProvider: tp,
    JSON:          key,
})

// Create the Gen AI Client specifying the location by env var
// and use the project ID specified in the service account
ctx := context.Background()
genaiClient, err := genai.NewClient(ctx, &genai.ClientConfig{
    Project:     serviceAccount.ProjectID,
    Location:    os.getenv("GCLOUD_LOCATION"),
    Backend:     genai.BackendVertexAI,
    Credentials: credentials,
})
if err != nil {
    return fmt.Errorf("failed to create genai client: %s", err)
}

Understanding OAuth2 Scopes for Vertex AI

Throughout both implementations, we used the https://www.googleapis.com/auth/cloud-platform scope because it provides comprehensive access to Vertex AI endpoints and other Google Cloud services. This broad scope essentially allows our applications to perform any operation that the service account is authorized to do within the Google Cloud project.

For developers who want to understand all available scopes across Google’s APIs, the complete reference is available in the OAuth 2.0 Scopes for Google APIs documentation. However, when it comes to Vertex AI specifically, Google’s scope options are surprisingly limited:

Scope Description
https://www.googleapis.com/auth/cloud-platform Full access: See, edit, configure, and delete your Google Cloud data
https://www.googleapis.com/auth/cloud-platform.read-only Read-only access: View your data across Google Cloud services

The Fine-Grained Access Problem

This binary choice between “full access” and “read-only” represents a significant limitation in Google’s OAuth2 implementation for Vertex AI. In production environments, you might want more granular permissions—for example, allowing an application to create and run inference requests while preventing it from deleting models or modifying training jobs. Unfortunately, Google doesn’t provide such fine-grained scopes for Vertex AI, forcing developers to choose between overly broad permissions or overly restrictive read-only access.

This lack of granular control is a notable pain point when implementing the principle of least privilege in cloud applications. I wasn’t expecting it from Google.

Key Takeaways

Migrating from Vertex AI SDK to Google Gen AI SDK with service account authentication requires careful attention to OAuth2 scope configuration and credential management. While the official migration guide covers the basic API changes, the authentication patterns shown here are essential for production applications that can’t rely on Application Default Credentials.

  • Always specify the https://www.googleapis.com/auth/cloud-platform scope for OAuth2 authentication, since it’s pretty much the only scope we have
  • Python developers can leverage the convenient from_service_account_file() method
  • Go developers need to manually construct the OAuth2 token provider but gain more control over the authentication flow

Don't you want to miss the next article? Do you want to be kept updated?
Subscribe to the newsletter!

Related Posts

Getting back to the EU: from Google Cloud to Self-Hosted EU Infrastructure

A detailed walkthrough of migrating a web service from Google Cloud to OVH, covering PostgreSQL database migration, CI/CD pipeline setup on Github Actions, and significant cost savings by migrating from Cloud to a self hosted solution. This migration represents a first step toward reducing dependency on US cloud providers while maintaining service quality.

Using AI for Coding: My Journey with Cline and Large Language Models

How I leveraged AI tools like Cline to enhance the UI/UX of a website and streamline backend tasks. From redesigning pages and translating content to navigating the benefits and challenges of AI-assisted development, this blog post highlights the potential of using large language models to boost productivity while sharing key lessons learned.

Fixing the code signing and notarization issues of Unreal Engine (5.3+) projects

Starting from Unreal Engine 5.3, Epic Games added support for the so-called modern Xcode workflow. This workflow allows the Unreal Build Tool (UBT) to be more consistent with the standard Xcode app projects, and to be compliant with the Apple requirements for distributing applications... In theory! 😅 In practice this workflow is flawed: both the code signing and the framework supports are not correctly implemented, making the creation of working apps and their distribution impossible. In this article, we'll go through the problems faced during the packaging, code signing, and notarization of an Unreal Engine application on macOS and end up with the step-by-step process to solve them all.

The (Hidden?) Costs of Vertex AI Resource Pools: A Cautionary Tale

In the article "Custom model training & deployment on Google Cloud using Vertex AI in Go" we explored how to leverage Go to create a resource pool and train a machine learning model using Vertex AI's allocated resources. While this approach offers flexibility, there's a crucial aspect to consider: the cost implications of resource pools. This article details my experience with a sudden price increase in Vertex AI and the hidden culprit – a seemingly innocuous resource pool.

Building a RAG for tabular data in Go with PostgreSQL & Gemini

In this article we explore how to combine a large language model (LLM) with a relational database to allow users to ask questions about their data in a natural way. It demonstrates a Retrieval-Augmented Generation (RAG) system built with Go that utilizes PostgreSQL and pgvector for data storage and retrieval. The provided code showcases the core functionalities. This is an overview of how the "chat with your data" feature of fitsleepinsights.app is being developed.

Using Gemini in a Go application: limits and details

This article explores using Gemini within Go applications via Vertex AI. We'll delve into the limitations encountered, including the model's context window size and regional restrictions. We'll also explore various methods for feeding data to Gemini, highlighting the challenges faced due to these limitations. Finally, we'll briefly introduce RAG (Retrieval-Augmented Generation) as a potential solution, but leave its implementation details for future exploration.

Custom model training & deployment on Google Cloud using Vertex AI in Go

This article shows a different approach to solving the same problem presented in the article AutoML pipeline for tabular data on VertexAI in Go. This time, instead of relying on AutoML we will define the model and the training job ourselves. This is a more advanced usage that allows the experienced machine learning practitioner to have full control on the pipeline from the model definition to the hardware to use for training and deploying. At the end of the article, we will also see how to use the deployed model. All of this, in Go and with the help of Python and Docker for the custom training job definition.

Integrating third-party libraries as Unreal Engine plugins: solving the ABI compatibility issues on Linux when the source code is available

In this article, we will discuss the challenges and potential issues that may arise during the integration process of a third-party library when the source code is available. It will provide guidance on how to handle the compilation and linking of the third-party library, manage dependencies, and resolve compatibility issues. We'll realize a plugin for redis plus plus as a real use case scenario, and we'll see how tough can it be to correctly compile the library for Unreal Engine - we'll solve every problem step by step.

AutoML pipeline for tabular data on VertexAI in Go

In this article, we delve into the development and deployment of tabular models using VertexAI and AutoML with Go, showcasing the actual Go code and sharing insights gained through trial & error and extensive Google research to overcome documentation limitations.

Advent of Code 2022 in pure TensorFlow - Day 12

Solving problem 12 of the AoC 2022 in pure TensorFlow is a great exercise in graph theory and more specifically in using the Breadth-First Search (BFS) algorithm. This problem requires working with a grid of characters representing a graph, and the BFS algorithm allows us to traverse the graph in the most efficient way to solve the problem.