Google Authentication Extension

Version: 1.0.2

Authenticate with Google for access to the Google APIs you specify.

Use this extension to obtain a token (OAuth or JWT) for Google Cloud services, then use the token for subsequent calls to the Google API, such as by using a ServiceCallout policy.

For example, in an API proxy you might get a token with this extension, cache the token using the PopulateCache policy, then pass the token via the ServiceCallout policy to access Google Cloud services from within an API proxy flow.

Prerequisites

This content provides reference for configuring and using this extension. Before using the extension from an API proxy using the ExtensionCallout policy, you must:

  1. Ensure that the account the extension will be using -- the account represented by the service account you'll use for credentials -- has access to the Google Cloud services the extension will authenticate with.

  2. Use the GCP Console to generate a key for the service account.

  3. Use the contents of the resulting service account key JSON file when adding and configuring the extension using the configuration reference.

About authenticating with Google Cloud

This extension requests authentication from Google Cloud by representing a specific member defined in your Google Cloud project. You use that project member's service account JSON file when configuring this extension.

As a result, this extension will have access to only those resources for which that member has permission. In other words, successful authentication by this extension depends on a match between permissions granted in the Google Cloud console and access requested by the extension (through scopes or audience) at runtime.

Generally, your steps for authenticating for access to APIs from this extension will be the following:

  1. Ensure that the member service account this extension is representing has access to the Google resource you want to access. You can use the Cloud Identity and Access Management (Cloud IAM) page in the Google Cloud console to grant roles to the project member this extension represents.

  2. Use that member's service account key JSON when configuring this extension.

  3. When configuring an ExtensionCallout policy to use this extension, request authentication only for resources to which your project member has access.

Samples

The following examples illustrate how to authenticate with Google Cloud using the ExtensionCallout policy.

Get an access token

In the following example, the extension's getOauth2AccessToken action retrieves a token for use in requests to the Cloud Translation API.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ConnectorCallout async="false" continueOnError="true" enabled="true" name="Get-Access-Token">
    <DisplayName>Get Access Token</DisplayName>
    <Connector>google-auth</Connector>
    <Action>getOauth2AccessToken</Action>
    <Input><![CDATA[{
      "scope" : [
        "https://www.googleapis.com/auth/cloud-translation"
      ]
    }]]></Input>
    <Output>google.credentials</Output>
</ConnectorCallout>

The response value looks something like this:

{
  "access_token":"ya29.c.ElpSB...BMgkALBJ0kou-8",
  "token_type":"Bearer",
  "expiresInSec": 3600
}

The following AssignMessage policy retrieves the response value from the ExtensionCallout policy above and copies it in the response payload. This can be useful for debugging. In actual practice, you might not want to return the token to the client.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AssignMessage async="false" continueOnError="false" enabled="true" name="Retrieve-Auth-Token">
    <DisplayName>Retrieve Auth Token</DisplayName>
    <AssignTo type="response" createNew="false"/>
    <Set>
        <Payload contentType="application/json">{google.credentials.access_token}</Payload>
    </Set>
</AssignMessage>

Cache an access token

To avoid making unnecessary calls to retrieve a token, consider caching the token you receive. For subsquent calls requiring a token, retrieving the token from the Apigee Edge cache will be faster than getting a new token. When the cached token expires, retrieve a new token and refresh the cache with it.

The following code from an example API proxy illustrate how to set and use a cached token to call the Google Translation API with a ServiceCallout policy. Each code example here is for a different policy in the flow.

The following policies are executed in the sequence described by the following flow XML:

  <Request>
    <!-- Attempt to get a token from the cache. -->
    <Step>
        <Name>Get-Cached-Auth-Token</Name>
    </Step>
    <!-- Only execute the following ExtensionCallout policy if the call to the
      cache couldn't retrieve a cached token. -->
    <Step>
        <Name>Google-Auth-Callout</Name>
        <Condition>lookupcache.Get-Cached-Auth-Token.cachehit is false</Condition>
    </Step>
    <!-- Only execute the following PopulateCache policy if the call to the
      cache couldn't retrieve a cached token. -->
    <Step>
        <Name>Cache-Auth-Token</Name>
        <Condition>lookupcache.Get-Cached-Auth-Token.cachehit is false</Condition>
    </Step>
    <!-- Use the ServiceCallout policy to call the translate API. -->
    <Step>
        <Name>Translate-Text</Name>
    </Step>
</Request>
  1. The following LookupCache policy attempts to get a token from the cache. If the token has already been obtained and cached, this policy will get it for use by the API proxy.

      <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
      <LookupCache async="false" continueOnError="false" enabled="true" name="Get-Cached-Auth-Token">
          <DisplayName>Get Cached Auth Token</DisplayName>
          <!-- Give cache key and scope to specify the entry for the cached token. -->
          <CacheKey>
              <Prefix/>
              <KeyFragment>gcp_translate_token_</KeyFragment>
          </CacheKey>
          <Scope>Exclusive</Scope>
          <!-- Assign the retrieved token (if any) to a variable, where it
           can be retrieved by policies. -->
          <AssignTo>cloud.translation.auth.token</AssignTo>
      </LookupCache>
    
  2. If the cache lookup doesn't retrieve a cached token, the following ExtensionCallout policy retrieves a new OAuth token, specifying the Google Cloud Translation API as the scope for the token. Google Cloud returns a valid token if the service account credentials used when configuring the Google-Auth-Callout extension represent a project member that has access to the API.

      <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
      <ConnectorCallout async="false" continueOnError="true" enabled="true" name="Google-Auth-Callout">
          <DisplayName>Google-Auth-Callout</DisplayName>
          <Connector>example-auth-extension</Connector>
          <Action>getOauth2AccessToken</Action>
          <Input><![CDATA[{
            "scope" : ["https://www.googleapis.com/auth/cloud-translation"]
          }]]></Input>
          <Output parsed="false">cloud.translation.auth.token</Output>
      </ConnectorCallout>
    
  3. After the ExtensionCallout policy has retrieved a new token, the PopulateCache policy caches it for use later by policies in the API proxy.

      <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
      <PopulateCache async="false" continueOnError="false" enabled="true" name="Cache-Auth-Token">
          <DisplayName>Cache Auth Token</DisplayName>
          <Properties/>
          <!-- Set cache key information to specify a unique key for this entry. -->
          <CacheKey>
              <Prefix/>
              <KeyFragment>gcp_translate_token_</KeyFragment>
          </CacheKey>
          <Scope>Exclusive</Scope>
          <ExpirySettings>
              <TimeoutInSec>5</TimeoutInSec>
          </ExpirySettings>
          <!-- Get the token to cache from the variable where the ExtensionCallout put it. -->
          <Source>cloud.translation.auth.token</Source>
      </PopulateCache>
    

Actions

getOauth2AccessToken

Gets an OAuth 2.0 access token. Use this action to support two-legged OAuth between your API proxy and Google APIs when the Google APIs require an OAuth token.

In two-legged OAuth, this extension action retrieves an OAuth token by authenticating with Google using a service account JSON (you add that JSON when you configure this extension). Once this action retrieves the OAuth token, your API proxy can use the token to make calls to Google APIs, effectively calling the APIs on behalf of the Google service account.

Access to Google Cloud APIs is filtered through the scopes listed in OAuth 2.0 scopes for Google APIs.

For more about server-to-server interactions with OAuth 2.0, see Using OAuth 2.0 for Server to Server Applications

Syntax

<Action>getOauth2AccessToken</Action>
<Input><![CDATA[{
  "scope" : [
    "scope1",
    "scope2"
  ]
}]]></Input>

Example

In the following example, the extension's getOauth2AccessToken action retrieves a token for use in requests to the Cloud Translation API.

<Action>getOauth2AccessToken</Action>
<Input><![CDATA[{
    "scope" : [
      "https://www.googleapis.com/auth/cloud-translation"
  ]
}]]></Input>

Request parameters

Parameter Description Type Default Required
scope An array of OAuth 2.0 scopes. For more about scopes, see OAuth 2.0 scopes for Google APIs. Array ["https://www.googleapis.com/auth/cloud-platform"], which grants access to all APIs for which the service account has access. No.

Response

An object containing the access token, its type, and its expiry date in the following form:

{
  "accessToken": "ewogICJ0eXB...C5jb20iCn0K",
  "token_type": "Bearer",
  "expiresInSec": 3600
}

Response properties

Parameter Description Default Required
accessToken OAuth 2.0 access token. None. Yes.
tokenType Token type. Bearer Yes.
expiresInSec Number of seconds until the token expires. 3600 Yes.

getJWTAccessToken

Gets a JSON web token (JWT) access token. You can use this token to authenticate with Google APIs if the API you want to call has a service definition published in the Google APIs GitHub repository.

With some Google APIs, you can make authorized API calls using a signed JWT directly as a bearer token, rather than an OAuth 2.0 access token. When this is possible, you can avoid having to make a network request to Google's authorization server before making an API call.

For more about authenticating with a JWT access token, see Using OAuth 2.0 for Server to Server Applications.

Syntax

<Action>getJWTAccessToken</Action>
<Input><![CDATA[{
    "audience" : "audience"
}]]></Input>

Example: Cloud Function URL

In the following example, the extension's getOauth2AccessToken action retrieves a token for use in requests to the Cloud Translation API.

<Action>getJWTAccessToken</Action>
<Input><![CDATA[{
  "audience" : "https://YOUR_REGION-YOUR_PROJECT_ID.cloudfunctions.net/FUNCTION_NAME"
}]]></Input>

Example: Cloud IAP-secured client ID

In the following example, the extension's getOauth2AccessToken action retrieves a token for use in requests to the Cloud Translation API.

<Action>getJWTAccessToken</Action>
<Input><![CDATA[{
  "audience" : "Cloud-IAP-secured-client-ID"
}]]></Input>

Request parameters

Parameter Description Default Required
audience Intended recipient of the token. This can include a Cloud IAP-secured client ID, a Cloud Functions URL, and so on. None. Yes.

Response

{
  "accessToken": "token",
  "tokenType": "Bearer",
  "expiresInSec": 3600
}

Response properties

Parameter Description Default Required
accessToken Access token. None. Yes.
tokenType Token type. Bearer Yes.
expiresInSec Expiry in seconds. 3600 Yes.

Configuration Reference

Use the following when you're configuring and deploying this extension for use in API proxies. For steps to configure an extension using the Apigee console, see Adding and configuring an extension.

Common extension properties

The following properties are present for every extension.

Property Description Default Required
name Name you're giving this configuration of the extension. None. Yes.
packageName Name of the extension package as given by Apigee Edge. None. Yes.
version Version number for the extension package from which you're configuring an extension. None. Yes.
configuration Configuration value specific to the extension you're adding. See Properties for this extension package None. Yes.

Properties for this extension package

Specify values for the following configuration properties specific to this extension.

Property Description Default Required
credentials When entered in the Apigee Edge console, this is the entire contents of your service account key JSON file. When sent via the management API, it is a base64-encoded value generated from the entire service account key JSON file. None. Yes.