Hide

Add-on Authorization Lifecycle

Two properties of add-ons make them especially easy to share and use:

  • Once you get an add-on from the store, you see it in the Add-ons menu for every document you open or create. Collaborators on those documents won't see the add-on except in documents where you actually use it.
  • Once you use an add-on in a document, your collaborators also see it in the Add-ons menu, but just for that document (unless they use it themselves).

We hope this sharing model feels natural for users. However, because an add-on automatically runs its onOpen(e) function to add menu items when a document opens, the behavior above adds some complexity to Apps Script's authorization rules. After all, users wouldn't be comfortable with an add-on accessing personal data every time they open a document. This guide should help you understand what your code can do and when.

Installed versus enabled

If you see an add-on in the menu, it's in one (or both) of two states: installed and enabled. An add-on is installed for a particular user after he or she chooses the add-on in the store and authorizes it to access their Google data. By contrast, an add-on is enabled in a given document when anyone uses it there. If two people collaborate on a document, and one of them uses an add-on, it is installed for the one user and enabled for the document.

The table below summarizes the two states. Note that when testing a script as an add-on you can choose to run the test in either or both of these states.

Installed Enabled
Applies to User Document
Caused by Getting an add-on from the store Getting an add-on from the store while using that document
Using a previously installed add-on in that document
Menu visible to Only that user, in all documents they open or create All collaborators on that document
onOpen(e) runs in AuthMode.NONE (unless also enabled, in which case AuthMode.LIMITED) AuthMode.LIMITED

Authorization modes

An add-on automatically runs its onOpen(e) function to add menu items when a document opens — but to protect users' data, Apps Script restricts what the onOpen(e) function can do. If the add-on hasn't been used in the current document, these restrictions become more severe.

Specifically, the installed and enabled states determine which authorization mode the onOpen(e) function runs in. Apps Script passes the authorization mode as the authMode property of the event parameter, e; the value of e.authMode corresponds to a constant in the ScriptApp.AuthMode enum.

If an add-on is installed for a user but not enabled in the current document, onOpen(e) runs in AuthMode.NONE; if the add-on is enabled in the current document, onOpen(e) runs in AuthMode.LIMITED. If the add-on is both installed and enabled, the enabled state takes precedence, since LIMITED allows access to more Apps Script services.

Note that only published add-ons can be in AuthMode.NONE; scripts that are bound to a document, including add-ons in development, always run onOpen(e) in AuthMode.LIMITED. You can, however, test as script as an add-on to verify that an add-on under development will behave as intended in either AuthMode.

The concept of authorization modes applies to all Apps Script executions — such as running from the script editor, from a menu item, or from a google.script.run call — although the e.authMode property can only be inspected if the script runs as the result of a trigger like onOpen(e), onEdit(e) or onInstall(e). Custom functions in Google Sheets use their own authorization mode, AuthMode.CUSTOM_FUNCTION, which is similar to LIMITED but has slightly different restrictions. The rest of the time, scripts run in AuthMode.FULL, as detailed in the table below.

NONE LIMITED CUSTOM_FUNCTION FULL
Occurs for onOpen(e) (if the user has installed an add-on but not enabled it in the document) onOpen(e) (all other times)
onEdit(e) (only in Sheets)
Custom functions All other times, including:
installable triggers
onInstall(e)
google.script.run
Access to user data Locale only Locale only Locale only Yes
Access to document No Yes Yes — read-only Yes
Access to user interface Add menu items Add menu items
Show sidebar
No Yes
Access to Properties No Yes Yes Yes
Access to Jdbc, UrlFetch No No Yes Yes
Other services Logger
Utilities
Any services that don’t access user data Any services that don’t access user data All services

The complete lifecycle

If an add-on is either installed for the current user or enabled in the current document, the add-on is loaded in the document, which causes it to appear in the Add-ons menu and start listening for the simple triggers onInstall(e), onOpen(e), and onEdit(e). If a user clicks one of the add-on’s menu items, it runs.

Installing

When an add-on is installed from the store, its onInstall(e) function runs in AuthMode.FULL. This allows the add-on to run a complex setup routine, but it’s important to also use onInstall(e) to create menu items, since the document is already open and thus your onOpen(e) function hasn’t run. For convenience, you can just call onOpen(e) from onInstall(e), as shown in this sample:

function onInstall(e) {
  onOpen(e);
  // Perform additional setup as needed.
}

Opening

When a document opens, it loads every add-on that the current user has installed or that any collaborator has enabled in the document, and calls each of their onOpen(e) functions. The authorization mode that onOpen(e) runs in depends on whether an add-on is installed or enabled, as explained above.

If an add-on only creates a basic menu, the mode doesn’t matter. This sample shows what a simple onOpen(e) might look like:

function onOpen(e) {
  SpreadsheetApp.getUi().createAddonMenu() // Or DocumentApp.
      .addItem('Insert chart', 'insertChart')
      .addItem('Update charts', 'updateCharts')
      .addToUi();
}

However, if you want to add dynamic menu items based on stored properties, read the contents of the current document, or perform other advanced tasks, you need to detect the authorization mode and handle it appropriately. This sample shows what an advanced onOpen(e) function might look like, changing its behavior based on the authorization mode:

function onOpen(e) {
  var menu = SpreadsheetApp.getUi().createAddonMenu(); // Or DocumentApp.
  if (e && e.authMode == ScriptApp.AuthMode.NONE) {
    // Add a normal menu item (works in all authorization modes).
    menu.addItem('Start workflow', 'startWorkflow');
  } else {
    // Add a menu item based on properties (doesn't work in AuthMode.NONE).
    var properties = PropertiesService.getDocumentProperties();
    var workflowStarted = properties.getProperty('workflowStarted');
    if (workflowStarted) {
      menu.addItem('Check workflow status', 'checkWorkflow');
    } else {
      menu.addItem('Start workflow', 'startWorkflow');
    }
  }
  menu.addToUi();
}

An add-on's onOpen(e) function can also open a sidebar if it executes in AuthMode.LIMITED. However, if any collaborator on the document has not yet installed the add-on, the sidebar's google.script.run calls will fail for that user, since google.script.run executes in AuthMode.FULL and the user hasn't granted authorization. In this case, you should handle the failure and direct the user to install your add-on by clicking on a menu item. (Also, see the UI style guide's restrictions on automatically showing a sidebar.)

Running

When someone clicks one of an add-on's menu items, Apps Script first checks to see whether the user has installed the add-on, and prompts them to do so if not. If the user has authorized the add-on, the script runs the function that corresponds to the menu item in AuthMode.FULL. The add-on also becomes enabled in the document if it wasn’t already.

Send feedback about...

Apps Script