Editor Add-on authorization

In most cases, you must authorize an add-on before you can use it. For many Apps Script projects such as web apps, authorization is straightforward—the script project asks for any missing permissions it needs when you attempt to use it. Once authorized, you can use the script project freely. Everyone using the script project authorizes it separately.

The authorization model for Editor Add-ons is more complex. Because these add-ons function on files residing in Google Drive—files that can be shared with others—you must build Editor Add-ons with the different authorization modes in mind. The Google Docs editors also provide an Add-ons menu in their UIs which is populated by the add-ons you've installed—even if you haven't authorized those add-ons yet. This adds some additional complexity to the authorization model.

Authorization model

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

  • Once you get an Editor Add-on from the store, you see it in the add-ons menu for every document, form, presentation, or spreadsheet that you open or create. Collaborators won't see the add-on except in documents, forms, presentations, or spreadsheets where you actually use it.
  • Once you use an Editor Add-on in a document, form, presentation, or spreadsheet, your collaborators also see it in the add-ons menu, but just for that file (unless they have also installed that add-on).

This sharing model feels natural for most users. However, because an Editor Add-on automatically runs its onOpen(e) function to add menu items when a Google Docs editor 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, form, presentation, or spreadsheet. This guide should help you understand what your code can do and when.

Installed versus enabled

If you see an Editor Add-on in the menu, it's in one (or both) of two states: installed and enabled. An Editor Add-on is installed for a particular user after they choose the add-on in the store and authorize it to access their Google data. By contrast, an add-on is enabled in a given document, form, presentation, or spreadsheet when anyone uses it there. If two people collaborate and one of them uses an add-on, it's installed for the one user and enabled for the file.

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, form, presentation, or spreadsheet
Caused by Getting an add-on from the store Getting an add-on from the store while using that document, form, presentation, or spreadsheet, or
Using a previously installed add-on in that document, form, presentation, or spreadsheet
Menu visible to Only that user, in all documents, forms, presentations, or spreadsheets they open or create All collaborators on that document, form, presentation, or spreadsheet
onOpen(e) runs in AuthMode.NONE (unless also enabled, in which case AuthMode.LIMITED) AuthMode.LIMITED

Authorization modes

An Editor Add-on automatically runs its onOpen(e) function to add menu items when a document, form, presentation, or spreadsheet 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, form, presentation, or spreadsheet, 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 Apps Script event parameter, e; the value of e.authMode corresponds to a constant in the Apps Script ScriptApp.AuthMode enum.

If an Editor Add-on is enabled in the current document, form, presentation, or spreadsheet, onOpen(e) runs in AuthMode.LIMITED. If the add-on isn't enabled and is only installed, onOpen(e) runs in AuthMode.NONE.

The concept of authorization modes applies to all Apps Script executions—such as running from the script editor, from a menu item, or from an Apps Script 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, form, presentation, or spreadsheet) 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, form, presentation, or spreadsheet No Yes Yes — read-only Yes
Access to user interface Add menu items Add menu items 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 file, the add-on is loaded in the document, form, presentation, or spreadsheet, 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 Editor 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, form, presentation, or spreadsheet 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, form, presentation, or spreadsheet opens, it loads every Editor Add-on that the current user has installed or that any collaborator has enabled in the file, 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.

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 Apps Script properties, read the contents of the current document, form, presentation, or spreadsheet, 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();
}

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, form, presentation, or spreadsheet if it wasn’t already.