Goa is a library to support OAuth2 for Apps Script connecting to a variety of services, using a variety of Authentication flows and processes. There are plenty of other articles on Goa on this site, see Apps Script Oauth2 – a Goa Library refresher to remind you how Goa works. If you’re new to Goa, it’s worth a read before getting started here.
OAuth2 can be tricky to troubleshoot. Goa has some little features that might help. You’ll need the cGoa library for this – see the end of the article for reference details.
Goa supports various scenarios such as Service accounts and JWT, but this article will mainly deal with 3 legged OAuth – when you want to get consent for access to private resources, whilst delegating the authentication to the OAuth2 service protecting an API you want to use.
Goa setup and operations revolve around a package of credentials and status (called a Goa) which are added to a property store by you, and maintained by Goa.
Setting up the credentials in Apps Script
This is a once off operation to store the credentials you’ve created in the dashboard of the developers console of the service you want to access. We’ll use the Twitter v2 API OAuth service as an example. For a complete example of setting up the Twitter API in the Twitter console (most APIS hava a silimar console and work in much the same way) see Apps Script Oauth2 – a Goa Library refresher
Create and run a once off script
- the clientid and secret from the twitter developer console (they are sometime called consumer key and secret and various other things by different API providers
- some name you’ll use to refer to this credential set later
- scopes that will authorize access to the twitter resources you need to access. I’m going to use this to do twitter queries, so these are the scopes I need. You’ll find all the twitter API scopes here.
Run the script – you won’t need it again so when you’re finished testing, delete it from your script so as not to accidentially expose these credentials.
Most of the content of this package was provided by you in your one off script. The id and revised properties are maintained by Goa. The serviceName matches one of Goa’s supported services. Each service has a slightly different flow and different endpoints. It’s Goa’s job to deal with all of that.
These flows are supported at time of writing. Nowadays the google and firebase services are easier via the Apps Script manifest, but you can use Goa if you want. Goa also supports custom services – ones provide the parameters for yourself – see Goa services and customization. If you do create a custom flow, then please let me know and I’ll add it to the supported services so others can use it too.
I can normally add new services to Goa by just adding 3 or 4 endpoint urls, and creating a service name – so don’t be shy in pinging me to add them.
Normally you wouldn’t need to do this, but you can find the endpoints and definition of these services like this, which might help if you are creating a custom service
More complicated flows
Some OAuth2 providers, like twitter, have more complex patterns, but the complications are handled by Goa service definitions.
Which Property store?
Deciding which property store to use is important and depends on how your Script is going to be used.
Here’s a guide on which property service to use.
- If the script is to run as you – ie. access a resource belonging to you, and only you will be running the script, then use UserProperties – you’ll give access to your resource the first time you run it.
- If the script is to run as you – ie. access a resource belonging to you, but others will be running the script accessing your resources then use ScriptProperties – you’ll give access to your resource the first time you run it.
- If the scipt is to run as the user accessing the script – then it’s a little more complex as the credentials will need to be cloned to each new user for them to login into and give access to their resource the first time they use it while keeping individual tokens private to them. To support this scenario, initialize goa once off in ScriptProperties, and make the code below the first thing you do in your script. Goa will clone the credentials to the user’s property store the first time it sees them, will force an authentication and thereafter will maintain a separate thread of access/refresh tokens for each user.
If you share a script as a viewer with someone they won’t be able to see your Script properties services, but if they have full rights to the project they’ll be able to see your client credentials if they access your Properties Store. Always use the ‘least visible’ Properties Service that will work – so UserProperties is usually the best choice.
Listing package contents
If you’ve used the script property store, you can use the Project settings to see the package store entry contents. However you’ll need a script to view the UserProperty store, and of course you won’t be (and shouldn’t be) able to see the contents of other User’s property stores. To view the contents of a package, you can use a script like this
Before you can get an access token, the user (or you) needs to give consent for the script to access the requested resources. Goa automatically creates a webapp and asks for consent if it needs it. This usually open happens once, as Goa will use the refresh token mechanism that most providers support to silently refresh access tokens whenever necessary. Once consent has been established, Goa maintains an access token, a refresh token and an expiry time in the package, which now looks like this.
Getting a token
- goa.hasToken() – will return true if a token already exists in the package that can be used (hasn’t expired)
- goa.getToken() – will return an access token. If the one in the package will expire shortly or has expired, it will get a new one via the refresh mechanism
Most of the time, there is no external access required to get a token. If Goa knows about an access token that hasn’t expired, it’ll give you that.
Forcing a refresh
You may want to force a refresh, especially if you are testing a customized flow you’ve made or just troubleshooting. Yo can do this my simply modifying the expiry date in the package in the and issuing a goa.getToken()
You may want to force a re-consent dialog. You can do this either by hacking the package
or better, use the kill method
In either case the goa will need to go through the consent process again, but the credentials will be retained – so no need to go through all that again
Remove a package
If you want to completely remove a package, including the credential, you can use the remove() method
In this case you’ll need to run the one off initialization again to re-enable Goa for this service
Copying a Goa
You’ll probably want to do this if you want to have different flows for different scopes. You can of course just create a new oneoff script with a different goa name and run that.
For example, you could create ‘twitter search’ and ‘twitter post’ Goa packages with different scope requests. Another way, to avoid having credentials in your script code, is to copy an existing one, but with modified scopes.
In this case, it’s important to ensure you specify the packageName (otherwise it’ll overwrite the old one), and to set the access to null (to provoke a new consent dialog)
Changing scopes in existing Goa
The scopes defines which of the APIs resources you’d like to access, and access tokens that are issued reflect that authorization. If you want to change the scope, you can
- Create a new one off script to replace the current credentials and scope
- Clone an existing Goa (as previously described)
- Modify the existing Goa and provoke a new consent dialog – see below
fetchPackage versus getPackage
You’ll notice I’ve used both fetch and get to retrieve packages. There’s a subtle difference
This retrieves the current package being used by Goa. It should normally only be used for reading.
This returns a copy of the current package. You can use this copy if you need to modify anything, and then use updatePackage() to replace and register your changes
I often include my test scripts as they make a handy crib sheet for how to do things and what to expect. Here are the tests for this article, plus some skeleton useful functions. You’ll need the Simple but powerful Apps Script Unit Test library to run them.
cGoa library 1v_l4xN3ICa0lAW315NQEzAHPSoNiFdWHsMEwj2qA5t9cgZ5VWci2Qxv2
Using multiple service accounts to work across projects and lock down permissions with Apps Script and Goa