Bearer Tokens

A Bearer Token is set in the Authorization header of every Inline Action HTTP Request. For example:

POST /rsvp?eventId=123 HTTP/1.1
Host: events-organizer.com
Authorization: Bearer AbCdEf123456
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/1.0 (KHTML, like Gecko; Gmail Actions)

rsvpStatus=YES

The string "AbCdEf123456" in the example above is the bearer authorization token. This is a cryptographic token produced by Google. All bearer tokens sent with actions have the issuee field as gmail@system.gserviceaccount.com, with the audience field specifying the sender domain as a URL of the form https://. For example, if the email is from noreply@example.com, the audience is https://example.com.

If using bearer tokens, verify that the request is coming from Google and is intended for the the sender domain. If the token doesn't verify, the service should respond to the request with an HTTP response code 401 (Unauthorized).

Bearer Tokens are part of the OAuth V2 standard and widely adopted by Google APIs.

Verifying Bearer Tokens

Services are encouraged to use the open source Google API Client library to verify Bearer tokens:

Java

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Collections;

import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;
import com.google.api.client.http.apache.ApacheHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson.JacksonFactory;

public class TokenVerifier {
  // Bearer Tokens from Gmail Actions will always specify this issuee.
  static String GMAIL_ISSUEE = "gmail@system.gserviceaccount.com";

  // Intended audience of the token, based on the sender's domain
  static String AUDIENCE = "https://example.com";

  // Get this value from the request's Authorization HTTP header.
  // For example, for "Authorization: Bearer AbCdEf123456" use "AbCdEf123456"
  static String BEARER_TOKEN = "AbCdEf123456";

  public static void main(String[] args) throws GeneralSecurityException, IOException {
    JsonFactory factory = new JacksonFactory();
    GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier(
    // Http Transport is needed to fetch Google's latest public key
        new ApacheHttpTransport(), factory);
    GoogleIdToken idToken = GoogleIdToken.parse(factory, BEARER_TOKEN);
    if (idToken == null) {
      System.out.println("Token cannot be parsed");
      System.exit(-1);
    }

    System.out.println("Token details:");
    System.out.println(idToken.getPayload().toPrettyString());

    // Verify valid token, signed by google.com, intended for a third party.
    if (!verifier.verify(idToken)
        || !idToken.verifyAudience(Collections.singletonList(AUDIENCE))
        || !idToken.getPayload().getAuthorizedParty().equals(GMAIL_ISSUEE)) {
      System.out.println("Invalid token");
      System.exit(-1);
    }

    // Token originates from Google and is targeted to a specific client.
    System.out.println("The token is valid");
  }
}

Python

import sys

from oauth2client import client

# Bearer Tokens from Gmail Actions will always specify this issuee.
GMAIL_ISSUEE = 'gmail@system.gserviceaccount.com'

# Intended audience of the token, based on the sender's domain
AUDIENCE = 'https://example.com'

# Get this value from the request's Authorization HTTP header.
# For example, for "Authorization: Bearer AbCdEf123456" use "AbCdEf123456"
BEARER_TOKEN = 'AbCdEf123456'

try:
  # Verify valid token, signed by google.com, intended for a third party.
  token = client.verify_id_token(BEARER_TOKEN, AUDIENCE)
  print 'Token details: %s' % token

  if token['azp'] != GMAIL_ISSUEE:
    sys.exit('Invalid issuee')
except:
  sys.exit('Invalid token')

# Token originates from Google and is targeted to a specific client.
print 'The token is valid'

Send feedback about...

Email Markup
Email Markup