GersonLobos
GersonLobos

Reputation: 25

How to use an Service Account Oauth token to make REST call in appscript

I am using the GAS_Service_Account library.

I was able to do all the .p12 key decoding. But now I have:

myJwt.generateJWT().requestToken();
var token=myJwt.getToken();

Now I would like to know a simple way to use it to make an API call with the service account to an api like drive to get a specific user's files.

Upvotes: 1

Views: 2281

Answers (1)

Spencer Easton
Spencer Easton

Reputation: 5782

Service accounts are powerful tools. The library GersonLobos mentions is: MJ5317VIFJyKpi9HCkXOfS0MLm9v2IJHf

Lets give some back ground. See the first half of this video on how to set up a service account in your domain: https://www.youtube.com/watch?v=EDmEzZEGSts

With the library enabled in your project you can generate the token with the following:

 // If userEmail is null the service account's token is returned   
function tokenService(userEmail){
  var userEmail = userEmail || ""
  var jsonKey = JSON.parse(PropertiesService.getScriptProperties().getProperty("jsonKey"));  
  var privateKey = jsonKey.private_key;
  var serviceAccountEmail = jsonKey.client_email; 
  if(!userEmail){userEmail = serviceAccountEmail};
  var sa = GSApp.init(privateKey, ['https://www.googleapis.com/auth/drive'], serviceAccountEmail).addUser(userEmail);
  var tokenObj  = JSON.parse(PropertiesService.getScriptProperties().getProperty(userEmail)) || {};

  return function(){
    var nowTime = parseInt((Date.now()/1000).toString().substr(0,10));
    if(!("token" in tokenObj) ||  tokenObj.expire < nowTime){
      var newToken = sa.requestToken().getToken(userEmail);
      PropertiesService.getScriptProperties().setProperty(userEmail, JSON.stringify(newToken));
      tokenObj.token = newToken.token;
      tokenObj.expire = newToken.expire;
    }
    return tokenObj.token;
  }
}

Good now you have your token. I even show how to cache it as the requests take several seconds. Now you can make some calls. As requested by Gerson here are some drive calls:

 function transferFileToUser(fileId, transferToEmail, token){
      var url = "https://www.googleapis.com/drive/v2/files/"+fileId+"/permissions?sendNotificationEmails=false";

      var payload = {"role":"owner","value":transferToEmail,"type":"user"}; 
      var params ={method:"POST",
                   contentType:'application/json',
                   headers:{Authorization: "Bearer " + token},
                   payload:JSON.stringify(payload),
                   muteHttpExceptions:true
                  };

      var results = UrlFetchApp.fetch(url, params);
      return JSON.parse(results.getContentText());

    }


function getAllFolders(token){
 var query = "mimeType = 'application/vnd.google-apps.folder'";
 return driveList(query, token);
}




function getFilesInFolder(folderId, token){
 var query = "'"+folderId+"' in parents and mimeType != 'application/vnd.google-apps.folder'";
 return driveList(query, token);
}


// genereic call to drive just pass the query
function driveList(query, token){

var filesArray = [];
  var pageToken = "";
  var query = encodeURIComponent(query);
  var params = {method:"GET",
                contentType:'application/json',
                headers:{Authorization:"Bearer "+token},
                muteHttpExceptions:true
               };

  var url = "https://www.googleapis.com/drive/v2/files?q="+query;

  do{
    var results = UrlFetchApp.fetch(url,params); 
    if(results.getResponseCode() != 200){
      Logger.log(results);
      break;
    }

    var files = JSON.parse(results.getContentText());
    url = "https://www.googleapis.com/drive/v2/files?q="+query;  

    for(var i in files.items){
      filesArray.push({"name":files.items[i].title, "id":files.items[i].id})
    }

    pageToken = files.nextPageToken;
    url += "&pageToken="+encodeURIComponent(pageToken);
  }while(pageToken != undefined)

  var filesObj = {};
  filesObj["fileObjs"] = filesArray;

 return filesObj;

}

Upvotes: 3

Related Questions