Automatic UI support for OAUTH2 Goa dialogs

There's always a little bit of work needed if you are planning to do an OAUTH2 flow that might need some user interaction. Goa now is able to create its own UI to manage the consent process if there is one available. There are a few scenarios, all of which are supported by GOA and are also described  elsewhere in this site in more detail, but let's look at them again.
  1. Borrowing the Apps Script generated token. This is by far the most straightforward way and can be used in cases where Apps Script has generated the scopes your API needs (For example mentioning DriveApp in your code will generate a token that allows you to use the Drive API directly).
  2. Using a Service Account. This is the most straightforward since there is no user dialog required. However, not all APIS support Service account flow, and in any case, any script that requires access to user resources should use a flow that explicitly requests them.
  3. A script that is only going to access resources belonging to its owner. In this case, only 1 initial dialog is required, and thereafter access tokens will be refreshed automatically. This initial dialog needs a UI to ask for permission of course, but it's not required after that.
  4. A script that is going to be used by multiple users to access their resources. In this case, you'll need a permanent UI so that new users can give consent.

UI Types

  1. A webapp will already have a doGet() function that can be used for a consent dialog. 
  2. A standalone script not using a spreadsheet, form, slide or doc will need a doGet() function to host a dialog.
  3. A script that has access to any of these documents can host a dialog in either a sidebar or a dialog, so it can use the document's UI.

Property Stores

Goa protects credentials and token information by storing them in a property store. It's up to you which property stores you want to use, but this guide might be helpful.
  1. Service accounts should use the ScriptProperties store, or the UserProperties if the owner is the only one who will run it.
  2. Scripts that will only be run by the script owner with access to their resources should use the UserProperties
  3. Scripts that will be used by multiple users should store the initial credentials in the ScriptProperties store and use Goa to Clone those properties into the UserProperties store. This will allow you to have one master set of credentials, but each user will have their own token maintenance infrastructure. Changing any credentials in the script Properties will automatically provoke a re-consent request.

One off initialization Scripts

The recommended way to keep credentials safe is to use goa to write them to the selected properties store, and then delete that function. Goa is able to optionally read credentials from a Drive file so there's no need to have credentials exposed in a script file's code.

Services supported by Goa

A number of  providers are supported by Goa - selected by the service property in the credentials. As of today, these are as follows. If you would like any added, please contact me on the community.

    "google_service": 
    "google": 
    "linkedin": 
    "soundcloud": 
    "podio": 
    "shoeboxed": 
    "github": ,  
    "reddit":,
    "asana": ,
    "live": 
    "paypal_sandbox": 
    "paypal_live": ,
    "firebase": 

What's new in Goa


Let's look at modifying the pattern used by Martin Hawksey to use various Youtube APIS as described in this post to take advantage of Goa's automatic UI capability. First though - using the method in his post.
  • Write the credentials using a one off function, then delete it once run.
    cGoa.GoaApp.setPackage ( propertyStore,{
      packageName: 'yt-client',
      clientId: '4.......b.apps.googleusercontent.com',
      clientSecret:'5.........w',
      scopes : cGoa.GoaApp.scopesGoogleExpand (
        ["youtube",
         "youtube.force-ssl",
         "youtubepartner",
         "youtubepartner-channel-audit",
         "yt-analytics-monetary.readonly",
         "yt-analytics.readonly"]),
      service:'google'
    });  
 
  • Use ScriptProperties, since he's the only one that will be running this script
  • Create a temporary doGet() and publish the app to be able to provoke a dialog.
This is the UI that needs to be published, run once to provoke the authentication dialog, and then  deleted. However, if your app is a webapp, goa.done() can be replaced by returning the code of your app as an HTML service and the rest of the code can be left in place.


function doGet(e) {

  // create a goa using the client
  // info stored in script properties
  var goa = cGoa.GoaApp.createGoa(
    'yt-client',
    PropertiesService.getScriptProperties())
  
  // this builds it - the (e) is important...
  .execute(e);
  
  return goa.needsConsent() ? goa.getConsent() : goa.done();

}

The App main code gets its token like this
function spreadsheetAnalytics() {


  var goa = cGoa.make('yt-client',PropertiesService.getScriptProperties());

  // when this re-enters
  if (!goa.hasToken()) throw 'something went wrong- didnt get token';
  
  YouTube.setTokenService( function() { 
    return goa.getToken(); 
  });
  
  YouTubeAnalytics.setTokenService(function() { 
    return goa.getToken(); 
  });

etc....

Since this particular App is running with access to a spreadsheet, we might as well use the Spreadsheet UI rather than bothering with a doGet() function. Goa can take care of that automatically using this pattern. 

function main (e) {
  
  // create a goa using the client
  // info stored in script properties
  var goa = cGoa.GoaApp.createGoa(
    'yt-client',
    PropertiesService.getScriptProperties())
  
  // this builds it
  .execute(e);
  
 
  // this gets consent in a sidebar if its necessary
  if (goa.needsConsent()) {
    return goa.getConsentUi (SpreadsheetApp.getUi(), {
      type:"SIDEBAR"
    });
  }

  // do the work
  spreadsheetAnalytics();

  return goa.done();
}

That creates a consent dialog like this in the sidebar but only if it's needed. Note that you can just run this function normally. There's no need to publish anything. Goa is able to take care of the UI if you pass the UI to use to it as in 
goa.getConsentUi (SpreadsheetApp.getUi(), {
      type:"SIDEBAR"
    });




You may prefer to provoke the consent dialog as a dialog box - especially if you are already using the sidebar for something else. In this case, you can do this. Everything else in the pattern is the same.
  if (goa.needsConsent()) {
    return goa.getConsentUi (SpreadsheetApp.getUi(), {
      type:"DIALOG",
      modal:true,
      height:600,
      width:400,
      title:"authentication with modal"
    });
  }
and you'll get this

Behavior

By default, if the consent dialog is required, you'll end up with something like this, which requires you to then close the window


In addition you'll notice that the default consent screen shows the Redirect URI which is very handy if you are the developer and need to update the cloud console, but not necessary if being used by multiple users. 

A slight change to the pattern allows you to modify this behavior, using the .setUiBehavior method. This changes what goa.done() does. Closing everything when it's all over is achieved as below.
  var goa = cGoa.GoaApp.createGoa(
    'yt-client',
    PropertiesService.getScriptProperties())
  
    // add any special UI requirements
  .setUiBehavior ({
    close:true,                 // whether to close the UI after dialog
    closeConsent:true,            // whether to close the UI after consent dialog
    showRedirect:false            // whether to show the redirect URL (for the developer's use)
  })
  
  // this builds it
  .execute(e);

Without the redirect URI the default consent screen looks like this



The library, cGoa, is available under this project key.

MZx5DzNPsYjVyZaR67xXJQai_d-phDA33


 

For more like this, see OAuth2 for Apps Script in a few lines of code Why not join our forumfollow the blog or follow me on twitter to ensure you get updates when they are available. 

You want to learn Google Apps Script?

Learning Apps Script, (and transitioning from VBA) are covered comprehensively in my my book, Going Gas - from VBA to Apps script, All formats are available from O'ReillyAmazon and all good bookshops. You can also read a preview on O'Reilly

If you prefer Video style learning I also have two courses available. also published by O'Reilly.
Google Apps Script for Developers and Google Apps Script for Beginners.


Comments