4
votes

I am a head of studies and school administrator of our Google Apps for Education.

I used Google Apps Script for a lot of applications (control of absences, sending emails, automatic reporting, ScriptDb databases and more) using gas services. It's fantastic.

Basically I need to create a folder structure (years, courses, teachers, ...) within the Google Drive of students.

With Google Apps Script services I can do it easily but then the folders belong to the creator (administrator) and I think then users spend the administrator storage quota. This does not interest me. (Yes, I can make an application to be executed by the users and create the structure in its Google Drive, but I'd rather do it in an automated manner and without intervention)

To create this documents (and folders) in Google Drive users (teachers, students, ...) have adapted the code provided by Waqar Ahmad in this response [ Add an writer to a spreadsheet ... ]

That allows me to take possession of documents of other users to make updates using the Google Document List API (Google Apps administrative access to impersonate a user of the domain) and also have adapted to create folders and files on other Google Drive users. It works perfectly. I mention here:

How to add a Google Drive folder ...

But now, the version 3 of the Google Documents List AP, has been officially deprecated and encourage us to work with the Google API Drive.

I tried to do the same with this new Google API. Has anyone managed to do this? Is it possible? I have no idea where to start!

Thank you.

Sergi

Updated:

This is the code i'm working but I get an "invalid request" error:

(...)

  var user = e.parameter.TB_email // I get user from a TextBox

//https://developers.google.com/accounts/docs/OAuth2ServiceAccount
//{Base64url encoded header}.{Base64url encoded claim set}.{Base64url encoded signature}

//{Base64url encoded header}
 var header = '{"alg":"RS256","typ":"JWT"}' 
 var header_b64e = Utilities.base64Encode(header)

//{Base64url encoded claim set}
 var t_ara = Math.round((new Date().getTime())/1000) // now 
 var t_fins = t_ara + 3600                           // t + 3600 sec


 var claim_set = '{"iss":"[email protected]",'+
                 '"prn":"' + user + '",' +
                 '"scope":"https://www.googleapis.com/auth/prediction",'+
                 '"aud":"https://accounts.google.com/o/oauth2/token",'+
                 '"exp":'+t_fins+','+
                 '"iat":'+t_ara+'}'

   // where '1111111111-xxxxxxxxxxx... is my CLIENT-ID (API Access -> Service Account)                   


 var claim_set_b64e = Utilities.base64Encode(claim_set)
 claim_set_b64e = claim_set_b64e.replace(/=/g,'')


 var to_sign = header_b64e + '.' + claim_set_b64e

 // [signature bytes] ???  // password 'isnotasecret???'
 var key_secret = DocsList.getFileById('0Biiiiiiiiii-XXXXXXXXXXX').getBlob().getBytes()

    // where '0Biiiiiiiiii-XXXXXXXXXXX'... is my p12 file (key_secret) uploaded to GDRive
    // I don't know if this is correct !!!

 var sign = Utilities.base64Encode(Utilities.computeHmacSha256Signature(to_sign, key_secret))


 var JWT_signed = to_sign + '.' + sign
 JWT_signed = JWT_signed.replace(/=/g,'')

 // Token Request /////////////////////////////////////////////////////////////
 var url = 'https://accounts.google.com/o/oauth2/token'
   //var url = 'https%3A%2F%2Faccounts.google.com%2Fo%2Foauth2%2Ftoken' ???
   //var url = 'https:' + '%2F%2Faccounts.google.com%2Fo%2Foauth2%2Ftoken' ???

 var parameters = {
 "method" : "POST",
 "payload" : '"' + 'grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=' + JWT_signed + '"',
 "contentType" : "application/x-www-form-urlencoded"
 }

 var content = UrlFetchApp.fetch(url,parameters) //.getContentText()
 // Token Request end ////////////////////////////////////////////////////////

And I get an "Invalid Request" and not a JSON with the token

The 2 first parts ( header & claim set ) are OK. The result are equal to the result of Google OAuth page.

I don't know if the signature part are correct or if the error is in the token request.

1
On the same question you linked I gave an answer that explains that this is possible. The setup is somewhat the same as you did on the other question you linked. There's links to the relevant pages showing how to do it on my answer as well. And yes, I have managed to do this, it's a little more cumbersome than what you did already.Henrique G. Abreu
Thanks Henrique. I've read all these answers before. I see there are people who have done using java and referring pages (OAuth, API Drive) show examples with other languages​​, including JavaScript, but the question is: Can it be done using Google Apps Script? I guess the difficulty is in getting the credentials: "Developers are Strongly Encouraged to use an existing library ..." I understand that you have done all the steps in the page you mentioned (Using OAuth 2.0 for Server to Server Applications) to get the access_token-authorization, which allows you to send a POST using UrlFetchAppsergicurtu
Yes, it's indeed difficult and there's no Apps Script examples. But it is possible, I have done it. But I have not setup a library or any example code to help you. I'll do it when I have some time.Henrique G. Abreu
@henrique-abreu I updated my question with a code in which I am currently working but fails in the token request.sergicurtu

1 Answers

2
votes

The issue with your example above is that it it's computing the signature with hmacsha256. You need to use rsasha256. There are two service account libraries for apps script right now. One that I put together is: https://gist.github.com/Spencer-Easton/f8dad65932bff4c9efc1

The issue with both libraries is they are derived from jsrsa which runs very slow on the server side.