Setting Up Authentication for Server to Server Production Applications

This guide explains how to set up authentication and authorization for server to server production applications. Authentication refers to the process of determining a client's identity. Authorization refers to the process of determining what permissions an authenticated client has for a specific resource. That is, authentication identifies who you are, and authorization determines what you can do. For more information about supported authentication methods and how to choose them, see authentication overview.

Google uses credentials to identify your application for quota and billing. Your credentials are also used to authorize access to GCP APIs, resources, and features.

Providing credentials to your application

GCP client libraries use a strategy called Application Default Credentials (ADC) to find your application's credentials. When your code uses a client library, the strategy checks for your credentials in the following order:

  1. First, ADC checks to see if the environment variable GOOGLE_APPLICATION_CREDENTIALS is set. If the variable is set, ADC uses the service account file that the variable points to.

  2. If the environment variable isn't set, ADC uses the default service account that Compute Engine, Kubernetes Engine, App Engine, and Cloud Functions provide, for applications that run on those services.

  3. If ADC can't use either of the above credentials, an error occurs.

The following code example illustrates this strategy. The example doesn't explicitly specify the application credentials. However, ADC is able to implicitly find the credentials as long as the GOOGLE_APPLICATION_CREDENTIALS environment variable is set, or as long as the application is running on Compute Engine, Kubernetes Engine, App Engine, or Cloud Functions.

C#

public object AuthImplicit(string projectId)
{
    // If you don't specify credentials when constructing the client, the
    // client library will look for credentials in the environment.
    var storage = StorageClient.Create();
    // Make an authenticated API request.
    var buckets = storage.ListBuckets(projectId);
    foreach (var bucket in buckets)
    {
        Console.WriteLine(bucket.Name);
    }
    return null;
}

Go

// For API packages whose import path is starting with "cloud.google.com/go",
// such as cloud.google.com/go/storage in this case, if there are no credentials
// provided, the client library will look for credentials in the environment.
storageClient, err := storage.NewClient(ctx)
if err != nil {
	log.Fatal(err)
}

it := storageClient.Buckets(ctx, "project-id")
for {
	bucketAttrs, err := it.Next()
	if err == iterator.Done {
		break
	}
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(bucketAttrs.Name)
}

// For packages whose import path is starting with "google.golang.org/api",
// such as google.golang.org/api/cloudkms/v1, use the
// golang.org/x/oauth2/google package as shown below.
oauthClient, err := google.DefaultClient(ctx, cloudkms.CloudPlatformScope)
if err != nil {
	log.Fatal(err)
}

kmsService, err := cloudkms.New(oauthClient)
if err != nil {
	log.Fatal(err)
}

Node.js

// Imports the Google Cloud client library.
const Storage = require('@google-cloud/storage');

// Instantiates a client. If you don't specify credentials when constructing
// the client, the client library will look for credentials in the
// environment.
const storage = Storage();

// Makes an authenticated API request.
storage
  .getBuckets()
  .then((results) => {
    const buckets = results[0];

    console.log('Buckets:');
    buckets.forEach((bucket) => {
      console.log(bucket.name);
    });
  })
  .catch((err) => {
    console.error('ERROR:', err);
  });

PHP

namespace Google\Cloud\Samples\Auth;

// Imports the Google Cloud Storage client library.
use Google\Cloud\Storage\StorageClient;

function auth_cloud_implicit($projectId)
{
    $config = [
        'projectId' => $projectId,
    ];

    # If you don't specify credentials when constructing the client, the
    # client library will look for credentials in the environment.
    $storage = new StorageClient($config);

    # Make an authenticated API request (listing storage buckets)
    foreach ($storage->buckets() as $bucket) {
        printf('Bucket: %s' . PHP_EOL, $bucket->name());
    }
}

Python

def implicit():
    from google.cloud import storage

    # If you don't specify credentials when constructing the client, the
    # client library will look for credentials in the environment.
    storage_client = storage.Client()

    # Make an authenticated API request
    buckets = list(storage_client.list_buckets())
    print(buckets)

Ruby

# project_id = "Your Google Cloud project ID"

require "google/cloud/storage"

# If you don't specify credentials when constructing the client, the client
# library will look for credentials in the environment.
storage = Google::Cloud::Storage.new project: project_id

# Make an authenticated API request
storage.buckets.each do |bucket|
  puts bucket.name
end

Obtaining and providing service account credentials manually

If you're developing code locally, deploying your application on-premises, or deploying to another public cloud, you can create and obtain service account credentials manually.

For more information about how to create a service account, see getting started with authentication. Although the linked guide walks you through creating a service account with owner-level permissions, for a production application, restrict access to the permissions, as described in the restricting access section below.

After you've created the service account and set the environment variable, ADC is able to implicitly determine your credentials, as described in the providing credentials to your application section above. We recommend this approach, because it requires less code.

You can alternately choose to explicitly point to your service account file in code, as shown in the following code example.

C#

public object AuthExplicit(string projectId, string jsonPath)
{
    // Explicitly use service account credentials by specifying the private key
    // file.
    GoogleCredential credential = null;
    using (var jsonStream = new FileStream(jsonPath, FileMode.Open,
        FileAccess.Read, FileShare.Read))
    {
        credential = GoogleCredential.FromStream(jsonStream);
    }
    var storage = StorageClient.Create(credential);
    // Make an authenticated API request.
    var buckets = storage.ListBuckets(projectId);
    foreach (var bucket in buckets)
    {
        Console.WriteLine(bucket.Name);
    }
    return null;
}

Node.js

// Imports the Google Cloud client library.
const Storage = require('@google-cloud/storage');

// Instantiates a client. Explicitly use service account credentials by
// specifying the private key file. All clients in google-cloud-node have this
// helper, see https://googlecloudplatform.github.io/google-cloud-node/#/docs/google-cloud/latest/guides/authentication
const storage = Storage({
  keyFilename: '/path/to/keyfile.json'
});

// Makes an authenticated API request.
storage
  .getBuckets()
  .then((results) => {
    const buckets = results[0];

    console.log('Buckets:');
    buckets.forEach((bucket) => {
      console.log(bucket.name);
    });
  })
  .catch((err) => {
    console.error('ERROR:', err);
  });

PHP

namespace Google\Cloud\Samples\Auth;

// Imports the Google Cloud Storage client library.
use Google\Cloud\Storage\StorageClient;

function auth_cloud_explicit($projectId, $serviceAccountPath)
{
    # Explicitly use service account credentials by specifying the private key
    # file.
    $config = [
        'keyFilePath' => $serviceAccountPath,
        'projectId' => $projectId,
    ];
    $storage = new StorageClient($config);

    # Make an authenticated API request (listing storage buckets)
    foreach ($storage->buckets() as $bucket) {
        printf('Bucket: %s' . PHP_EOL, $bucket->name());
    }
}

Python

def explicit():
    from google.cloud import storage

    # Explicitly use service account credentials by specifying the private key
    # file. All clients in google-cloud-python have this helper, see
    # https://google-cloud-python.readthedocs.io/en/latest/core/modules.html
    #   #google.cloud.client.Client.from_service_account_json
    storage_client = storage.Client.from_service_account_json(
        'service_account.json')

    # Make an authenticated API request
    buckets = list(storage_client.list_buckets())
    print(buckets)

Ruby

# project_id = "Your Google Cloud project ID"
# key_file   = "path/to/service-account.json"
require "google/cloud/storage"

# Explicitly use service account credentials by specifying the private key
# file.
storage = Google::Cloud::Storage.new project: project_id, keyfile: key_file

# Make an authenticated API request
storage.buckets.each do |bucket|
  puts bucket.name
end

Obtaining credentials on Compute Engine, Kubernetes Engine, App Engine flexible environment, and Cloud Functions

If your application runs on Compute Engine, Kubernetes Engine, the App Engine flexible environment, or Cloud Functions, you don't need to create your own service account. Compute Engine includes a default service account that is automatically created for you, and you can assign a different service account, per-instance, if needed. When you create a new instance, the instance is automatically enabled to run as the default service account and has a default set of authorization permissions. For more information, see Compute Engine default service account.

After you set up a service account, ADC can implicitly find your credentials without any need to change your code, as described in the section above. If you want to specifically use Compute Engine credentials, you can explicitly do so, as shown in the following code example.

C#

public object AuthExplicitComputeEngine(string projectId)
{
    // Explicitly use service account credentials by specifying the 
    // private key file.
    GoogleCredential credential =
        GoogleCredential.FromComputeCredential();
    var storage = StorageClient.Create(credential);
    // Make an authenticated API request.
    var buckets = storage.ListBuckets(projectId);
    foreach (var bucket in buckets)
    {
        Console.WriteLine(bucket.Name);
    }
    return null;
}

PHP

namespace Google\Cloud\Samples\Auth;

// Imports GCECredentials and the Google Cloud Storage client library.
use Google\Auth\Credentials\GCECredentials;
use Google\Cloud\Storage\StorageClient;

function auth_cloud_explicit_compute_engine($projectId)
{
    $gceCredentials = new GCECredentials();
    $config = [
        'projectId' => $projectId,
        'credentialsFetcher' => $gceCredentials,
    ];
    $storage = new StorageClient($config);

    # Make an authenticated API request (listing storage buckets)
    foreach ($storage->buckets() as $bucket) {
        printf('Bucket: %s' . PHP_EOL, $bucket->name());
    }
}

Python

def explicit_compute_engine(project):
    from google.auth import compute_engine
    from google.cloud import storage

    # Explicitly use Compute Engine credentials. These credentials are
    # available on Compute Engine, App Engine Flexible, and Container Engine.
    credentials = compute_engine.Credentials()

    # Create the client using the credentials and specifying a project ID.
    storage_client = storage.Client(credentials=credentials, project=project)

    # Make an authenticated API request
    buckets = list(storage_client.list_buckets())
    print(buckets)

Ruby

require "googleauth"
require "google/cloud/env"
require "google/cloud/storage"

# Explicitly use Compute Engine credentials and a project ID to create a new
# Cloud Storage client. These credentials are available on Compute Engine,
# App Engine Flexible, and Container Engine.
storage = Google::Cloud::Storage.new project: Google::Cloud.env.project_id,
                                     keyfile: Google::Auth::GCECredentials.new

# Make an authenticated API request
storage.buckets.each do |bucket|
  puts bucket.name
end

Obtaining credentials on App Engine standard environment

If your application runs on App Engine standard environment, you can use the App Engine App Identity API to obtain credentials.

After you set up a service account, ADC can implicitly find your credentials without any need to change your code, as described in the section above. If you want to specifically use App Engine credentials, you can explicitly do so, as shown in the following code example.

PHP

namespace Google\Cloud\Samples\Auth;

// Imports AppIdentityCredentials and the Google Cloud Storage client library.
use Google\Auth\Credentials\AppIdentityCredentials;
use Google\Cloud\Storage\StorageClient;

function auth_cloud_explicit_app_engine($projectId)
{
    # Learn more about scopes at https://cloud.google.com/storage/docs/authentication#oauth-scopes
    $scope = 'https://www.googleapis.com/auth/devstorage.read_only';
    $gaeCredentials = new AppIdentityCredentials($scope);
    $config = [
        'projectId' => $projectId,
        'credentialsFetcher' => $gaeCredentials,
    ];
    $storage = new StorageClient($config);

    # Make an authenticated API request (listing storage buckets)
    foreach ($storage->buckets() as $bucket) {
        printf('Bucket: %s' . PHP_EOL, $bucket->name());
    }
}

Python

def explicit_app_engine(project):
    from google.auth import app_engine
    import googleapiclient.discovery

    # Explicitly use App Engine credentials. These credentials are
    # only available when running on App Engine Standard.
    credentials = app_engine.Credentials()

    # Explicitly pass the credentials to the client library.
    storage_client = googleapiclient.discovery.build(
        'storage', 'v1', credentials=credentials)

    # Make an authenticated API request
    buckets = storage_client.buckets().list(project=project).execute()
    print(buckets)

Restricting access

Only grant your application the authorization permissions that it needs to interact with applicable GCP APIs, features, or resources. GCP uses Cloud Identity and Access Management (Cloud IAM) for access control. When you create a service account, you can choose a Cloud IAM role for limiting access. The walkthrough at getting started with authentication instructs you to choose the Owner role when you create a service account. You can change this value at any time. For more information, see granting roles to service accounts.

Best practices for managing credentials

Credentials provide access to sensitive data. The following practices help protect access to these resources.

  • Do not embed secrets related to authentication in source code, such as API keys, OAuth tokens, and service account credentials. You can use an environment variable pointing to credentials outside of the application's source code, such as Cloud Key Management Service.

  • Do use different credentials in different contexts, such as in testing and production environments.

  • Do transfer credentials only over HTTPS to prevent a third party from intercepting your credentials. Never transfer in clear text or as part of the URL.

  • Never embed long-lived credentials into your client-side app. For example, do not embed service account credentials into a mobile app. Client-side apps can be examined and credentials can easily be found and used by a third party.

  • Do revoke a token if you no longer need it.

Troubleshooting API errors

Learn more about how to troubleshoot failed API requests at Cloud APIs errors.

What's next

Supervisa tus recursos estés donde estés

Obtén la app de Google Cloud Console para ayudarte a administrar tus proyectos.

Enviar comentarios sobre…