Chrome Device Token API Samples

Stay organized with collections Save and categorize content based on your preferences.

Python

import jwt
import json
import requests
import sys
import time
import codecs

SERVICE_ACCOUNT_FILE = './service_account_key.json'

JWT_AUDIENCE = 'https://oauth2.googleapis.com/token'
JWT_SCOPE = 'https://www.googleapis.com/auth/chromeosdevicetoken'
TOKEN_REQUEST_URL = 'https://oauth2.googleapis.com/token'
INVALIDATE_TOKEN_API_URL = 'https://chromedevicetoken.googleapis.com/v1/users:invalidateToken'

def get_access_token_for_user(service_account_email, private_key_id, private_key, user_email):
    '''
    See instructions for getting a signed JWT here
    https://developers.google.com/identity/protocols/oauth2/service-account#jwt-auth
    '''
    iat = time.time()
    exp = iat + 3600
    payload = {'iss': service_account_email,
               'sub': user_email,
               'aud': JWT_AUDIENCE,
               'scope': JWT_SCOPE,
               'iat': iat,
               'exp': exp
               }
    additional_headers = {'kid': private_key_id}
    signed_jwt = jwt.encode(payload, private_key, headers=additional_headers,
                            algorithm='RS256')

    grant_type = codecs.decode(
        'urn:ietf:params:oauth:grant-type:jwt-bearer', 'unicode_escape')
    payload = 'grant_type=' + str(grant_type) + '&assertion=' + signed_jwt
    headers = {'Content-Type': 'application/x-www-form-urlencoded'}

    response = requests.post(TOKEN_REQUEST_URL, data=payload, headers=headers)

    print(f'Response HTTP status code: {response.status_code}')
    print(json.dumps(response.json(), indent=2))

    return response.json()['access_token']

def invalidate_token(user_email):
    print(f'invalidate token for user {user_email}')

    with open(SERVICE_ACCOUNT_FILE, 'r') as service_account_key_json_file:
        service_account_key = json.load(service_account_key_json_file)

        service_account_email = service_account_key['client_email']
        private_key_id = service_account_key['private_key_id']
        private_key = service_account_key['private_key']
        print(f'using service account {service_account_email}')
        print(f'using private key id {private_key_id}')

        access_token = get_access_token_for_user(service_account_email, private_key_id,
                               private_key, user_email)

        response = requests.post(
            INVALIDATE_TOKEN_API_URL,
            headers={
                'Authorization': 'Bearer ' + access_token,
                'Content-Type': 'application/json'
            },
            json={
                'token_type': 'SAML_PASSWORD'
            })

        # Successful call should have HTTP status code 200 and an empty response body.
        print(f'Response HTTP status code: {response.status_code}')
        print(json.dumps(response.json(), indent=2))

if __name__ == '__main__':
    invalidate_token(sys.argv[1])

C#

private async Task<string> InvalidatePasswordTokenForUser(string userAccessToken)
{
    const string tokenRequestURI = "https://chromedevicetoken.googleapis.com/v1/users:invalidateToken";

    var jsSerializer = new JavaScriptSerializer();
    var body = new Dictionary<string, object>();
    body["token_type"] = "SAML_PASSWORD";
    string jsonString = jsSerializer.Serialize(body);

    HttpWebRequest tokenRequest = (HttpWebRequest)WebRequest.Create(tokenRequestURI);
    tokenRequest.Method = "POST";
    tokenRequest.Headers.Add(string.Format("Authorization: Bearer {0}", userAccessToken));
    tokenRequest.ContentType = "application/json";
    tokenRequest.Accept = "Accept=text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
    byte[] _byteVersion = Encoding.ASCII.GetBytes(jsonString);
    tokenRequest.ContentLength = _byteVersion.Length;
    Stream stream = tokenRequest.GetRequestStream();
    await stream.WriteAsync(_byteVersion, 0, _byteVersion.Length);
    stream.Close();

    WebResponse tokenResponse = await tokenRequest.GetResponseAsync();
    using (StreamReader reader = new StreamReader(tokenResponse.GetResponseStream()))
    {
        string responseText = await reader.ReadToEndAsync();

        if (responseText != null && responseText.Length > 0)
        {
            return responseText;
        }
        throw new FormatException("Unexpected response format: " + responseText);
    }
}

Appscript

function runInvalidateToken() {
  var url = 'https://chromedevicetoken.googleapis.com/v1/users:invalidateToken';
  var userToImpersonate = '...@....';
  var service = getOAuth2Service(userToImpersonate, 'https://www.googleapis.com/auth/chromeosdevicetoken');

  if (service.hasAccess()) {
    var param = {
      method: 'post',
      contentType: 'application/json',
      headers: {
        Authorization: 'Bearer ' + service.getAccessToken()
      },
      payload : JSON.stringify({
        token_type : 'SAML_PASSWORD'
      }),
      muteHttpExceptions: true
    };

    var req = UrlFetchApp.getRequest(url, param);
    Logger.log('Request : ');
    Logger.log(req);

    var response = UrlFetchApp.fetch(url, param);
    Logger.log('ResponseCode : ' + response.getResponseCode());
    Logger.log('ResponseBody : ' + response.getContentText());
  } else {
    Logger.log(service.getLastError());
  }
}

/*
 * This sample demonstrates how to configure the library for Google APIs, using
 * domain-wide delegation (Service Account flow).
 * https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority
 */

// Private key and client email of the service account.
var PRIVATE_KEY = '-----BEGIN PRIVATE KEY-----\n....\n-----END PRIVATE KEY-----\n';
var CLIENT_EMAIL = '....iam.gserviceaccount.com';

/**
 * Reset the authorization state, so that it can be re-tested.
 */
function reset() {
  getService().reset();
}

/**
 * Configures the service.
 */
function getOAuth2Service(user, scopes) {
  return OAuth2.createService('ChromeDeviceTokens:' + user)
      // Set the endpoint URL.
      .setTokenUrl('https://oauth2.googleapis.com/token')

      // Set the private key and issuer.
      .setPrivateKey(PRIVATE_KEY)
      .setIssuer(CLIENT_EMAIL)

      // Set the name of the user to impersonate. This will only work for
      // Google Apps for Work/EDU accounts whose admin has setup domain-wide
      // delegation:
      // https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority
      .setSubject(user)

      // Set the property store where authorized tokens should be persisted.
      .setPropertyStore(PropertiesService.getScriptProperties())

      // Set the scope. This must match one of the scopes configured during the
      // setup of domain-wide delegation.
      .setScope(scopes);
}