Hitching a ride on Goa's property store

Apps Script / Oauth2 (Intermediate level) posted on 21st October 2018

Goa is a library to simplify Oauth2 with both Google services and other Oauth2 providers, many of which are natively supported. It takes care of dealing with HTML dialogs, refreshing tokens, getting service account data and generating JWTs as required.  Recently, Apps script has been improved so you can customize scopes with your manifest, but it's possible that you need to connect to multiple projects (other than your apps script one), or you may need to connect to non-Google services. 

There are plenty of examples in OAuth2 for Apps Script in a few lines of code, and the Goa library is available with this key, and on github 
   MZx5DzNPsYjVyZaR67xXJQai_d-phDA33

Brevity

I've tried to make Goa as invisible as possible. There are 2 steps
  • Create a one off function which writes credential information to a given property store (reading it from drive if necessary).
  • Ask Goa to get a token when you need to access the service. It will go through a user consent dialog if required, use a refresh token or use an existing access token as required in a process that is fairly invisible to you. 

Using goa's property store

Often there are parameters other than those specifically needed for authentication that are nonetheless associated with a given service. You can of course manage all these yourself, but since Goa is managing the credentials for a given service, it may as well manage the other parameters too.  

Example

In this example we're using 2 different service accounts to access BigQuery using it's API (as opposed to the Apps Script Advanced service). Each of the service accounts are for different cloud projects with different IAM role and scopes, which is why we need two different credential flows. I also have various parameters that apply to each service that we'll use  Goa to manage.

One off function

Goa needs a one time setup. You create this function, run it, then you can delete it if you like - you won't need it again. I've already downloaded my service account JSON credentials for my 2 projects to Google Drive, and picked up their drive fileid (these files are only needed for the one off authentication too).

  // used by all using this script var propertyStore = PropertiesService.getScriptProperties(); // DriveApp.createFile(blob)
// service account for project 1 cGoa.GoaApp.setPackage (propertyStore , cGoa.GoaApp.createServiceAccount (DriveApp , { packageName: 'bigqueryA', fileId:'...fileid for service account A...', scopes : cGoa.GoaApp.scopesGoogleExpand (['bigquery','devstorage.read_only']), service:'google_service', apiKey:'.. and api key for service account A...', datsetId: 'projecta:dsa', }));
// service account for cloud vision cGoa.GoaApp.setPackage (propertyStore , cGoa.GoaApp.createServiceAccount (DriveApp , { packageName: 'bigqueryB', fileId:'...fileid for service account B...', scopes : cGoa.GoaApp.scopesGoogleExpand (['bigquery','cloud-platform']), service:'google_service', apiKey:'.. and api key for service account B...', datsetId: 'projectb:dsb' }));

Note that there are two properties unrelated to authentication (apiKey , and datasetId). You can add as many as you like. Goa will maintain these but ignore them. Once you've run this, you're good to go and you can delete it from your script if you want. It won't be needed again.

To use

When I use the BigQuery API, I'll need the projectID, an access token, the apiKey and the datasetid, all of which can be accessed from a given goa. 
    // get service account to use for service A 
    const goa = cGoa.make ('bigquerya',PropertiesService.getScriptProperties());

    // now init the API 
    BQ.init ({
      apiKey:goa.getProperty("apiKey"),
      token:goa.getToken(),
      projectId: goa.getProperty("project_id")
    });

goa.getProperty() extracts any custom property from goa (the ones you set during initialization as well as various others that are available from the service account import such as project_id). This gives a handy way of managing multiple service related parameters without the need to create special property store entries. 



For more like this, see Google Apps Scripts snippets. Why not join our forumfollow the blog or follow me on twitter to ensure you get updates when they are available. 





Comments