This guide helps you choose and configure the appropriate authentication
approach for your Data Manager API production deployment.

## Choose your deployment scenario

Select the authentication approach that matches your application architecture
and deployment environment:

- **[Workloads in Google Cloud](https://developers.google.com/data-manager/api/devguides/concepts/deploy#google-cloud)** : For automated workloads (such as ETL pipelines, batch jobs, or backend services) running on Compute Engine, Cloud Run, Cloud Functions, or GKE, use [Application Default Credentials (ADC)](https://cloud.google.com/docs/authentication/application-default-credentials) with an attached service account or Workload Identity Federation for GKE.
- **[Workloads outside Google Cloud](https://developers.google.com/data-manager/api/devguides/concepts/deploy#outside-google-cloud)** : For automated workloads running on-premises or on other cloud providers, use [Application Default Credentials (ADC)](https://cloud.google.com/docs/authentication/application-default-credentials) with Workload Identity Federation or a service account key.
- **[Act on behalf of users](https://developers.google.com/data-manager/api/devguides/concepts/deploy#on-behalf-of-users)** : For third-party platforms and multi-tenant applications that manage accounts for external users (such as advertisers who sign up on your platform), use the [OAuth 2.0 Web Server flow](https://developers.google.com/identity/protocols/oauth2/web-server) with per-user refresh tokens, or [partner links](https://developers.google.com/data-manager/api/devguides/accounts/partner-links) if you are an approved data partner.

For general guidance on Google Cloud authentication, see the
[Google Cloud authentication decision tree](https://cloud.google.com/docs/authentication#auth-decision-tree).

## Workloads in Google Cloud

When running on Google Cloud,
[attach a service account](https://cloud.google.com/iam/docs/attach-service-accounts) directly to your compute resource or
configure [Workload Identity Federation for GKE](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity). Client libraries use
[ADC](https://cloud.google.com/docs/authentication/application-default-credentials) to retrieve short-lived credentials for the service account
automatically without requiring credential files or environment variables.

### Compute Engine

When creating a virtual machine instance, specify the service account and
the Data Manager API scope so access tokens returned by the instance metadata
server include the required authorization.

    gcloud compute instances create INSTANCE_NAME \
      --service-account="SERVICE_ACCOUNT_EMAIL" \
      --scopes="https://www.googleapis.com/auth/datamanager,https://www.googleapis.com/auth/cloud-platform"

To update the scopes or service account on an existing instance, stop the
instance, update the configuration with `set-service-account`, and restart
the instance:

    gcloud compute instances stop INSTANCE_NAME

    gcloud compute instances set-service-account \
      INSTANCE_NAME \
      --service-account="SERVICE_ACCOUNT_EMAIL" \
      --scopes="https://www.googleapis.com/auth/datamanager,https://www.googleapis.com/auth/cloud-platform"

    gcloud compute instances start INSTANCE_NAME

### Cloud Run

Specify the service account when deploying the service:

    gcloud run deploy SERVICE_NAME \
      --image="IMAGE_URL" \
      --service-account="SERVICE_ACCOUNT_EMAIL"

### Cloud Functions

Specify the service account when deploying the function:

    gcloud functions deploy FUNCTION_NAME \
      --service-account="SERVICE_ACCOUNT_EMAIL" \
      --runtime="RUNTIME" \
      --trigger-http

### GKE

1. Enable [Workload Identity Federation for GKE](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity) on your cluster.
2. Bind your Kubernetes Service Account (KSA) to the Google Service Account
   (GSA):

       # Define the Kubernetes service account member:
       KUBERNETES_MEMBER="serviceAccount:PROJECT_ID.svc.id.goog[KUBERNETES_NAMESPACE/KUBERNETES_SA_NAME]"

       # Grant the Workload Identity User role to the Kubernetes service account:
       gcloud iam service-accounts add-iam-policy-binding \
         SERVICE_ACCOUNT_EMAIL \
         --role="roles/iam.workloadIdentityUser" \
         --member="${KUBERNETES_MEMBER}"

3. Annotate the Kubernetes Service Account with the Google Service Account
   email:

       kubectl annotate serviceaccount KUBERNETES_SA_NAME \
         --namespace="KUBERNETES_NAMESPACE" \
         iam.gke.io/gcp-service-account="SERVICE_ACCOUNT_EMAIL"

4. Specify the Kubernetes Service Account in your pod specification:

       apiVersion: v1
       kind: Pod
       metadata:
         name: data-manager-worker
       spec:
         serviceAccountName: KUBERNETES_SA_NAME
         containers:
         - name: worker
           image: IMAGE_URL

### Verify IAM and account access


Before deploying your production application, verify that your service account
has the necessary permissions:

1. **Google Cloud IAM permissions** : Grant the service account
   the [Service Usage Consumer](https://docs.cloud.google.com/iam/docs/roles-permissions/serviceusage#serviceusage.serviceUsageConsumer) role
   (`roles/serviceusage.serviceUsageConsumer`) in the
   Google Cloud project where the Data Manager API is enabled.

       gcloud projects add-iam-policy-binding PROJECT_ID \
         --member="serviceAccount:SERVICE_ACCOUNT_EMAIL" \
         --role="roles/serviceusage.serviceUsageConsumer"

2. **Destination account access** : Grant the service account the required access
   to your destination accounts. For step-by-step instructions, see
   [Set up account access](https://developers.google.com/data-manager/api/devguides/quickstart/set-up-access#setup-accounts-access).

<br />

## Workloads outside Google Cloud

When running code in on-premises data centers or on other cloud providers,
choose one of the following authentication mechanisms:

- **Workload Identity Federation (Recommended)** : Configure
  [Workload Identity Federation](https://cloud.google.com/iam/docs/workload-identity-federation) to let your application exchange
  credentials from your external identity provider for short-lived
  Google Cloud credentials without managing service account keys.
  Generate a credential configuration file and provide it to ADC using the
  `GOOGLE_APPLICATION_CREDENTIALS` environment variable.

- **Service account keys (Fallback)** : If Workload Identity Federation is not
  available, create a [service account key](https://cloud.google.com/iam/docs/service-account-creds#key-types) and provide it to ADC
  using the `GOOGLE_APPLICATION_CREDENTIALS` environment variable.

  > [!CAUTION]
  > **Caution:** Service account keys are long-lived credentials that present a security risk if leaked or mismanaged. Follow [best practices for managing service account keys](https://cloud.google.com/iam/docs/best-practices-for-managing-service-account-keys), store keys in a secure secret manager, restrict file permissions, and rotate keys regularly.

### Set `GOOGLE_APPLICATION_CREDENTIALS`

Set the `GOOGLE_APPLICATION_CREDENTIALS` environment variable to the absolute
path of the Workload Identity Federation credential configuration file or
service account key file so client libraries can locate your credentials
automatically using [ADC](https://cloud.google.com/docs/authentication/application-default-credentials).

### Linux / macOS

Set the environment variable in your shell profile or deployment script:

    export GOOGLE_APPLICATION_CREDENTIALS=\
      "/path/to/credentials.json"

### Windows (PowerShell)

Set the environment variable in PowerShell:

    $env:GOOGLE_APPLICATION_CREDENTIALS = `
      "C:\path\to\credentials.json"

### Docker / Containers

Mount the credentials file into the container and set the environment
variable:

    ENV GOOGLE_APPLICATION_CREDENTIALS="/secrets/credentials.json"

Or pass the environment variable at runtime:

    HOST_CREDS="/host/path/credentials.json"
    docker run -e GOOGLE_APPLICATION_CREDENTIALS="/secrets/credentials.json" \
      -v "${HOST_CREDS}:/secrets/credentials.json:ro" \
      IMAGE_NAME

### Kubernetes

Mount the credentials as a Secret and reference it in the pod's environment:

    apiVersion: v1
    kind: Pod
    metadata:
      name: data-manager-worker
    spec:
      containers:
      - name: worker
        image: IMAGE_URL
        env:
        - name: GOOGLE_APPLICATION_CREDENTIALS
          value: "/etc/secrets/google/credentials.json"
        volumeMounts:
        - name: credentials-volume
          mountPath: "/etc/secrets/google"
          readOnly: true
      volumes:
      - name: credentials-volume
        secret:
          secretName: data-manager-credentials

### Authenticate REST and curl requests

If your automated pipeline makes raw HTTP requests with `curl` rather than using
a client library, use the Google Cloud CLI to non-interactively authenticate and
manage access tokens without manually signing tokens:

1. Authorize the Google Cloud CLI using the credential file configured in your
   environment:

       gcloud auth login --cred-file="${GOOGLE_APPLICATION_CREDENTIALS}"

2. Pass the generated access token in the `Authorization` header of your API
   requests:

       curl -X POST "https://datamanager.googleapis.com/v1/..." \
         -H "Authorization: Bearer $(gcloud auth print-access-token)" \
         -H "Content-Type: application/json" \
         -d @request.json

   The Google Cloud CLI automatically caches the access token and refreshes it
   before expiration.

### Verify IAM and account access


Before deploying your production application, verify that your service account
has the necessary permissions:

1. **Google Cloud IAM permissions** : Grant the service account
   the [Service Usage Consumer](https://docs.cloud.google.com/iam/docs/roles-permissions/serviceusage#serviceusage.serviceUsageConsumer) role
   (`roles/serviceusage.serviceUsageConsumer`) in the
   Google Cloud project where the Data Manager API is enabled.

       gcloud projects add-iam-policy-binding PROJECT_ID \
         --member="serviceAccount:SERVICE_ACCOUNT_EMAIL" \
         --role="roles/serviceusage.serviceUsageConsumer"

2. **Destination account access** : Grant the service account the required access
   to your destination accounts. For step-by-step instructions, see
   [Set up account access](https://developers.google.com/data-manager/api/devguides/quickstart/set-up-access#setup-accounts-access).

<br />

## Act on behalf of users

Third-party platforms such as marketing platforms and agencies often need to
send API requests on behalf of multiple advertisers who sign up for their
service.

In this architecture, instead of using Application Default Credentials, use the
[OAuth 2.0 Web Server flow](https://developers.google.com/identity/protocols/oauth2/web-server) to obtain user credentials with
offline access from each advertiser, and then use those credentials to configure
the client library at runtime based on which advertiser account the request is
managing.

### Implement the OAuth 2.0 web flow

Here is how to set up user delegation for multi-tenant applications:

1. **Request offline access** : Direct users to Google's OAuth consent screen
   requesting the `https://www.googleapis.com/auth/datamanager` scope with `access_type=offline` and
   `prompt=consent`. Your server exchanges the authorization code for an
   access token and a `refresh_token`. For step-by-step instructions, see
   [OAuth 2.0 for Web Server Applications](https://developers.google.com/identity/protocols/oauth2/web-server).

2. **Store credentials securely**: Store each user's refresh token securely
   in an encrypted credential store associated with their account on your
   platform.

3. **Initialize client libraries at runtime**: When sending an API request on
   behalf of a specific user, construct user credentials from the refresh token
   you stored for the user and the client ID and client secret for your app,
   and pass them when initializing the client:

   ### .NET

       using Google.Ads.DataManager.V1;
       using Google.Apis.Auth.OAuth2;

       UserCredential credential = CredentialFactory.FromJsonParameters<UserCredential>(
           new JsonCredentialParameters
           {
               Type = JsonCredentialParameters.AuthorizedUserCredentialType,
               ClientId = clientId,
               ClientSecret = clientSecret,
               RefreshToken = refreshToken
           });

       IngestionServiceClient client = new IngestionServiceClientBuilder
       {
           Credential = credential
       }.Build();

   ### Go

       import (
           "context"

           datamanager "cloud.google.com/go/datamanager/apiv1"
           "golang.org/x/oauth2"
           "golang.org/x/oauth2/google"
           "google.golang.org/api/option"
       )

       cfg := &oauth2.Config{
           ClientID:     clientID,
           ClientSecret: clientSecret,
           Endpoint:     google.Endpoint,
       }
       ts := cfg.TokenSource(ctx, &oauth2.Token{RefreshToken: refreshToken})

       client, err := datamanager.NewIngestionClient(ctx, option.WithTokenSource(ts))

   ### Java

       import com.google.ads.datamanager.v1.IngestionServiceClient;
       import com.google.ads.datamanager.v1.IngestionServiceSettings;
       import com.google.api.gax.core.FixedCredentialsProvider;
       import com.google.auth.oauth2.UserCredentials;

       UserCredentials credentials =
           UserCredentials.newBuilder()
               .setClientId(clientId)
               .setClientSecret(clientSecret)
               .setRefreshToken(refreshToken)
               .build();

       IngestionServiceSettings settings =
           IngestionServiceSettings.newBuilder()
               .setCredentialsProvider(FixedCredentialsProvider.create(credentials))
               .build();

       try (IngestionServiceClient client = IngestionServiceClient.create(settings)) {
         // Send API requests using client...
       }

   ### Node.js

       const {IngestionServiceClient} = require('@google-ads/datamanager').v1;
       const {UserRefreshClient} = require('google-auth-library');

       const authClient = new UserRefreshClient({
         clientId,
         clientSecret,
         refreshToken,
       });

       const client = new IngestionServiceClient({authClient});

   ### PHP

       use Google\Ads\DataManager\V1\Client\IngestionServiceClient;
       use Google\Auth\Credentials\UserRefreshCredentials;

       $credentials = new UserRefreshCredentials(
           null,
           [
               'client_id' => $clientId,
               'client_secret' => $clientSecret,
               'refresh_token' => $refreshToken,
           ]
       );

       $client = new IngestionServiceClient(['credentials' => $credentials]);

   ### Python

       from google.ads.datamanager_v1 import IngestionServiceClient
       from google.oauth2.credentials import Credentials

       credentials = Credentials.from_authorized_user_info({
           "client_id": client_id,
           "client_secret": client_secret,
           "refresh_token": refresh_token,
       })

       client = IngestionServiceClient(credentials=credentials)

   ### Ruby

       require "google/ads/data_manager/v1"
       require "googleauth"

       credentials = Google::Auth::UserRefreshCredentials.new(
         client_id: client_id,
         client_secret: client_secret,
         refresh_token: refresh_token
       )

       client = Google::Ads::DataManager::V1::IngestionService::Client.new do |config|
         config.credentials = credentials
       end

### Complete OAuth app verification

Because Data Manager API scopes are sensitive scopes, any
Google Cloud app used to obtain user credentials from external
Google Accounts must undergo [Google OAuth verification](https://support.google.com/cloud/answer/7454865)
before going to production:

- **Development** : While the app's publishing status is set to **Testing** on the [Audience page](https://console.cloud.google.com/auth/audience) in the Google Cloud console, only designated test accounts can authorize your application.
- **Production** : Before making your application available to external users, set the publishing status to **In production** and [submit the app for verification](https://support.google.com/cloud/answer/13461325).

> [!IMPORTANT]
> **Important:** If you don't complete OAuth app verification before launching to external users, users encounter an [unverified app screen](https://support.google.com/cloud/answer/7454865#unverified-apps) and you might not be able to obtain credentials for new users. For details on audience configuration phases and demonstration video requirements, see [OAuth app verification](https://developers.google.com/data-manager/api/devguides/concepts/oauth-verification).

App verification isn't required for workloads that run using service accounts.
In addition, there are some exceptions for scenarios such as internal
applications. Check out
[When is verification not needed](https://support.google.com/cloud/answer/13464323) for details.

### Alternative: Partner links

If your organization is an approved data partner, you can use
[partner links](https://developers.google.com/data-manager/api/devguides/accounts/partner-links) instead of managing per-user OAuth tokens for
ongoing data ingestion.

With partner links, advertisers connect their accounts to your data partner
account in the Google Ads, Display \& Video 360, or Google Ad Manager UI. After the link is established,
your application sends ingestion requests using your own service account
credentials through ADC, avoiding the need to store and maintain long-lived user
refresh tokens.

## Production best practices

Review these key operational considerations when moving to production:

- **[Error handling and validation](https://developers.google.com/data-manager/api/devguides/concepts/understand-errors)** : Understand how the API validates requests using the [fast-fail model](https://developers.google.com/data-manager/api/devguides/concepts/understand-errors#fast-fail) and returns structured error details.
- **[Retry strategy](https://developers.google.com/data-manager/api/devguides/concepts/understand-errors#retry-strategy)**: Implement exponential backoff with jitter for transient server errors.
- **[Batching and concurrency](https://developers.google.com/data-manager/api/devguides/concepts/best-practices#optimize)** : Maximize throughput by batching records and sending requests concurrently within [limits](https://developers.google.com/data-manager/api/devguides/limits).
- **[Diagnostics and monitoring](https://developers.google.com/data-manager/api/devguides/diagnostics)**: Capture response request IDs and query the diagnostics service to verify asynchronous processing and detect warnings and errors.