Search code examples
google-apps-scriptgoogle-apigoogle-contacts-api

Authorization for Contacts API across domain access using Google Apps Script


I am working in a Google Apps Script web app using Contacts API v3, to access all user's contacts within the domain.

I have no problems so far with Contacts API requests, but I have no idea yet on how to get authorization across the domain to access any user's contacts (other than me).

I have tried OAuth domain key from cpanel - advanced tools, with no results so far. I got "Request failed for returned code 403 (Forbidden)" when trying with other users within the domain

Thanks in advance, Fausto

EDIT-1 (Mar.05) I'm closer now, but need a bit of help

I have combined 2LO (2-legged OAuth) with oauth_signature and signing request, but still getting Error 401 (Client Error)!!1. This is the sample code I am working with now.

function test_xOAuth() {
  // OAUTH_CONSUMER_SECRET from GApps: control panel > advanced tools > Manage OAuth domain key 
  var domain = Session.getEffectiveUser().getEmail().split("@")[1];
  var xuser = 'fausto@thexs.ca';
  var method = "GET";
  var baseUrl = "https://www.google.com/m8/feeds/groups/default/full";
  var timestamp = getTimestamp();
  var paramsJson = {
    oauth_consumer_key : domain,
    oauth_nonce : getNonce(timestamp),
    oauth_signature_method : "HMAC-SHA1",
    oauth_timestamp : timestamp,
    oauth_version : "1.0"
  };
  var paramsStringArray =  [];
  for (var k in paramsJson) paramsStringArray.push(k + '="' + paramsJson[k] + '"');
  var paramsString = paramsStringArray.join("&") + '&xoauth_requestor_id=' + xuser;
  var signatureBaseString = method +"&"+ encodeURIComponent(baseUrl) +"&"+ encodeURIComponent(paramsString);
  var signatureBytes = Utilities.computeHmacSha256Signature(signatureBaseString, OAUTH_CONSUMER_SECRET);
  var signature = Utilities.base64Encode(signatureBytes);
  var xoauthString = 'OAuth ' + paramsStringArray.join(",") + ',oauth_signature="' + signature + '"';
  var options = {
    method : method,
    headers : {"Authorization" : xoauthString}
  }
  var url = baseUrl + '?xoauth_requestor_id=' + 'fausto@thexs.ca';
  var response = UrlFetchApp.fetch(url, options);
  var responseHeader = response.getHeaders();
  var responseText = response.getContentText();
  return HtmlService.createHtmlOutput(responseText);
}

var getTimestamp = function(){
  return (Math.floor((new Date()).getTime() / 1000)).toString()
}

var getNonce = function(timestamp){
  return timestamp + Math.floor( Math.random() * 100000000)
}

Thanks in advance for any help !! Fausto


Solution

  • First, you should properly URL-encode all parameters before you calculate signature. Second, strip the quotes, you don't really need them, especially in the base string. Third, you should use signature method you're specifying i.e. HMAC-SHA1. And last but not least, despite you're not using OAuth token you still need to include '&' in the encryption key.

    Here's the code that works properly:

      var OAUTH_CONSUMER_SECRET = 'you secret goes here';
      var domain = 'domain.tld';
      var username = 'test.user';
      var xuser = encodeURIComponent(username+'@'+domain);
      var method = "GET";
      var baseUrl = "https://www.google.com/m8/feeds/groups/default/full";
      var timestamp = Math.round(new Date().getTime() / 1000);
      var paramsJson = {
        oauth_consumer_key : domain,
        oauth_nonce : timestamp,
        oauth_signature_method : "HMAC-SHA1",
        oauth_timestamp : timestamp,
        oauth_version : "1.0"
      };
      var paramsStringArray =  [];
      for (var k in paramsJson) paramsStringArray.push(k + '=' + encodeURIComponent(paramsJson[k]));
      var paramsString = paramsStringArray.join("&") + "&xoauth_requestor_id="+xuser;
      var signatureBaseString = method +"&"+ encodeURIComponent(baseUrl) +"&"+ encodeURIComponent(paramsString);
      var signatureBytes = Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_1, signatureBaseString, OAUTH_CONSUMER_SECRET+'&');
    
      var signature = encodeURIComponent(Utilities.base64Encode(signatureBytes));
      var xoauthString = 'OAuth ' + paramsStringArray.join(", ") + ', oauth_signature="' + signature + '"';
    
      var options = {
        method : method,
        headers : {authorization: xoauthString}
      }
      var url = baseUrl + '?xoauth_requestor_id=' + xuser;
      var response = UrlFetchApp.fetch(url, options);