Authentication Between Services

This page demonstrates how to implement authentication between services using a service account in a gRPC service. This page demonstrates service-to-service authentication by walking you through a complete example, including how to configure the Extensible Service Proxy (ESP) in a gRPC service to support authenticated requests, and how to call the service from a gRPC client. It assumes that you've already read Authenticating Users, which also describes ESP's other supported authentication methods.

In order for any service to make authenticated calls into an Endpoints API, the calling service must have a service account and it must send an auth token in the call. The caller must use a Google ID token or a custom JSON Web Token (JWT) that is signed only by the service account of the caller. ESP validates that the "iss" claim in the JWT matches the issuer setting in the service configuration. ESP does not check for Cloud Identity and Access Management permissions that have been granted on the service account.

In our example, we'll set up and use the very simplest form of service-to- service authentication, where the client uses their Google Cloud Platform service account to generate authenticating JWTs. The approach for other authentication methods is similar, though the client-side process for getting valid authentication tokens depends on the authentication method used.

Google projects and setup

This guide uses the Bookstore example we used in our Tutorials. If you want to work along with the steps yourself:

  1. Clone the git repo where the gRPC example code is hosted:

    git clone
  2. Change your working directory:

    cd python-docs-samples/endpoints/bookstore-grpc/

We'll use deployment to GKE in our example, though the authentication setup is the same for Compute Engine/Docker.

In the example, we'll talk about two Google Cloud Platform projects:

  • the service producer project, which is the project that owns the gRPC Endpoints service
  • the service consumer project, which is the project that owns the gRPC client

If you're working through the example yourself, it's OK to use the same project for both. Follow the instructions in the Tutorials to set up a project if you don't have one already.

Creating the consumer service account and key

Use the following procedure to create the service account and key for the consumer project. You'll need the details for this account to set up authentication in the next section.

  1. In the GCP Console, go to APIs & services.

    APIs & services

  2. Make sure you are in your consumer project.
  3. On the Credentials page, select Service Account Key from the Create Credentials drop-down list.
  4. On the Create service account key page, if you have an existing service account that you'd like to use, select it. Otherwise, select New service account from the Service account drop-down list and type an account name. A corresponding Service account ID is created for you. Make note of the full ID, as you'll need it in the following sections. For example:
  5. Click the Role drop-down list and select the following roles:

    • Service Accounts > Service Account User
    • Service Accounts > Service Account Token Creator
  6. Ensure the JSON key type is selected.

  7. Click Create. Your service account JSON key file is downloaded to your local machine. Note the location and make sure it's stored securely because you'll need to use this later to generate tokens.

Configuring authentication for the service

Now let's look at what you need to do to set up authentication requirements for our gRPC Endpoints service. If you are using two separate producer and consumer projects, don't forget to use the producer project for all steps in this section.

Set up authentication in the gRPC API Configuration

Authentication for ESP is configured in your gRPC API Configuration YAML file in its authentication section. The configuration with authentication for our example service is in api_config_auth.yaml.

  - id: google_service_account
    # Replace SERVICE-ACCOUNT-ID with your service account's email address.
  # This auth rule will apply to all methods.
  - selector: "*"
      - provider_id: google_service_account

The providers section specifies the authentication provider(s) you want to use - in this case, that you want to use a Google service account as an authentication provider. The rules section specifies that you require tokens from this provider for access to all your service's methods.

In your own copy of this file from the cloned repo:

  • Change MY_PROJECT_ID to your producer project ID.
  • Change SERVICE-ACCOUNT-ID in the authentication section (in both the issuer and jwks_uri values) to the full consumer service account ID you noted in the last section. This tells ESP that you want to grant access to your service to users who provide valid tokens from this particular service account.

Save the file for the next step.

Deploy the configuration and service

These steps are the same as in Getting Started with gRPC on GKE:

  1. Deploy your service configuration to Endpoints: you'll need to do this even if you did so for the tutorial, as we're using a different configuration. Note the returned service name.

    gcloud endpoints services deploy api_descriptor.pb api_config_auth.yaml --project PRODUCER_PROJECT
  2. Create a container cluster and authenticate kubectl to the cluster, if you haven't already done so.

  3. Deploy the sample API and ESP to the cluster. If you are using separate producer and consumer projects, first make sure that you have set the appropriate project within the gcloud command-line tool:

    gcloud config set project PRODUCER_PROJECT

Calling authenticated methods from a gRPC client

Finally, on the client side, let's look at how to use the service account key to generate a JWT token and then use the token to call an authenticated Bookstore method. If you want to work along with the examples, first install the appropriate Python requirements to both generate the token and run the example client. Ensure that you are in the python-docs-samples/endpoints/bookstore-grpc folder of your cloned client, then:

virtualenv bookstore-env
source bookstore-env/bin/activate
pip install -r requirements.txt

Generate a JWT token

In our example, the Bookstore is using service-to-service authentication where the calling service is purely authenticated by its service account, so creating an appropriate token to send with our requests is simple. Note that you can also require more stringent service-to-service authentication where the generated token must be further authenticated by Google (using a Google ID token).

For this example, we've provided a Python script that can generate a token from the JSON key file downloaded earlier, using a dummy user ID and email.

#!/usr/bin/env python

# Copyright 2016 Google Inc. All Rights Reserved.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# See the License for the specific language governing permissions and
# limitations under the License.

"""Example of generating a JWT signed from a service account file."""

import argparse
import json
import time

import google.auth.crypt
import google.auth.jwt

"""Max lifetime of the token (one hour, in seconds)."""

def generate_jwt(service_account_file, issuer, audiences):
    """Generates a signed JSON Web Token using a Google API Service Account."""
    with open(service_account_file, 'r') as fh:
        service_account_info = json.load(fh)

    signer = google.auth.crypt.RSASigner.from_string(

    now = int(time.time())

    payload = {
        'iat': now,
        'exp': now + MAX_TOKEN_LIFETIME_SECS,
        # aud must match 'audience' in the security configuration in your
        # swagger spec. It can be any string.
        'aud': audiences,
        # iss must match 'issuer' in the security configuration in your
        # swagger spec. It can be any string.
        'iss': issuer,
        # sub and email are mapped to the user id and email respectively.
        'sub': '12345678',
        'email': ''

    signed_jwt = google.auth.jwt.encode(signer, payload)
    return signed_jwt

if __name__ == '__main__':
    parser = argparse.ArgumentParser(
                        help='The path to your service account json file.')
    parser.add_argument('--issuer', default='', help='issuer')
    parser.add_argument('--audiences', default='', help='audiences')

    args = parser.parse_args()

    signed_jwt = generate_jwt(args.file, args.issuer, args.audiences)

To generate a token using the script:

  • Use the following command to generate a JWT token and assign it to the variable $JWT_TOKEN:



    • SERVICE_ACCOUNT_FILE is the downloaded consumer service account JSON key file
    • SERVICE_NAME is the name of the Bookstore service that was returned when we deployed its updated service configuration to Endpoints
    • SERVICE-ACCOUNT-ID is the full consumer service account ID we got when generating our service account

Make an authenticated gRPC call

This last step uses, which is the same client used in the Tutorials. To make an authenticated call, the client passes the JWT as metadata with their method call.

def run(host, port, api_key, auth_token, timeout):
    """Makes a basic ListShelves call against a gRPC Bookstore server."""

    channel = grpc.insecure_channel('{}:{}'.format(host, port))

    stub = bookstore_pb2_grpc.BookstoreStub(channel)
    metadata = []
    if api_key:
        metadata.append(('x-api-key', api_key))
    if auth_token:
        metadata.append(('authorization', 'Bearer ' + auth_token))
    shelves = stub.ListShelves(empty_pb2.Empty(), timeout, metadata=metadata)
    print('ListShelves: {}'.format(shelves))

To run the example:

  1. Use kubectl get services to get the external IP address for our deployed Bookstore:

    #kubectl get services
    NAME                 CLUSTER-IP      EXTERNAL-IP      PORT(S)           AGE
    echo          80/TCP            10d
    endpoints     80/TCP,8090/TCP   10d
    esp-grpc-bookstore    80/TCP            1d
    kubernetes      <none>           443/TCP           10d

    In this case, it's the esp-grpc-bookstore service and its external IP is

  2. Assign the IP address to the variable EXTERNAL_IP

  3. Run the following command to list all the shelves from the Bookstore service:

    python --port=80 --host=$EXTERNAL_IP --auth_token=$JWT_TOKEN

The service should return all the shelves in the current Bookstore. You can double check it by not providing a token, or by specifying the wrong service account ID when generating the JWT: the command should fail.

See also

Was this page helpful? Let us know how we did:

Send feedback about...

Cloud Endpoints with gRPC
Need help? Visit our support page.