Authorization for many Apps Script-based apps is straightforward because the script project asks for any missing permissions it needs when someone attempts to use it.
The authorization model for Editor add-ons is more complex for several reasons:
When a user creates a file, all the add-ons the user installs are listed in the Extensions menu, even if the user hasn't authorized those add-ons yet.
These add-ons work on files in Google Drive that can be shared with collaborators. Collaborators who don't have the Editor add-on installed see it in documents where the file creator used it.
Editor add-ons automatically run their
onOpen()
functions when a document opens.
To protect user data, authorization modes are applied that make some services
unavailable to onOpen()
. This guide can help you understand what your code
can do and when.
Authorization model
The authorization mode of an Editor add-on depends on its state, which depends on who is using it: the user who installed the add-on or a collaborator.
Editor add-on states
Editor add-ons in the Extensions menu are installed, enabled, or both.
- An add-on is installed for a particular user after they or their administrator get it from the Google Workspace Marketplace and authorize it to access their Google data.
- An add-on is enabled in a document, form, presentation, or spreadsheet when anyone uses it there.
- When people collaborate on a file and one of them uses an add-on, it's installed for the one user, and enabled for the file.
The following table summarizes the differences between installed and enabled. Note that when you test a script as an add-on you can 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 |
Authorization mode for onOpen() |
AuthMode.NONE (unless it's also enabled, in which case AuthMode.LIMITED) |
AuthMode.LIMITED |
Authorization modes
The onOpen()
function of an Editor add-on runs
automatically when a user opens a document, form, presentation, or spreadsheet.
To protect users' data, Apps Script restricts what the
onOpen()
function can do. The Editor add-on state
determines which authorization mode the onOpen()
function runs in.
If an Editor add-on is enabled in the file,
form, presentation, or spreadsheet, onOpen()
runs in
AuthMode.LIMITED
. If the add-on isn't enabled and is
only installed, onOpen()
runs in AuthMode.NONE
.
In AuthMode.NONE
, an add-on can't run certain
services until the user interacts with the add-on by
clicking or running custom functions. If your
add-on tries to use these services in onOpen()
,
onInstall()
, or global scope, permissions fail and other calls, such as
filling in menus, stop. Help is the only supported option.
To run restricted service calls, you must use the AuthMode.FULL
authorization
mode. User interaction functions, such as clicking a menu option,
run only in this mode. After the code is run in AuthMode.FULL
mode, the
add-on can use all the scopes that the user authorized.
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.
Authorization modes apply to all Apps Script execution methods,
including running from the script editor, from a menu item, or from an Apps Script
google.script.run
call. However,
the e.authMode
property can only be inspected if the script runs as the result
of a trigger such as onOpen()
, onEdit()
or onInstall()
. Custom functions
in Google Sheets use their own authorization mode, AuthMode.CUSTOM_FUNCTION
,
which is similar to LIMITED
but has slightly different restrictions. For all
other cases, scripts run in AuthMode.FULL
, as described in the following
table.
NONE |
LIMITED |
CUSTOM_FUNCTION |
FULL |
|
---|---|---|---|---|
Occurs for | onOpen() (if the user has installed an
add-on but not enabled it in the document, form,
presentation, or spreadsheet) |
onOpen() (all other times)onEdit() (only in Sheets) |
Custom functions | All other times, including: installable triggers onInstall() 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 |
Authorization lifecycle of an Editor add-on
When an add-on is installed for the current user
or enabled in the current file, the
add-on is loaded for the document, form, presentation,
or spreadsheet when that file is opened. The add-on is
listed in the Extensions menu and starts listening for the
simple triggers onInstall()
,
onOpen()
, and onEdit()
. If a user clicks an
Extensions menu item, it runs.
The Editor add-on is installed
When an Editor add-on is installed from the store, its
onInstall()
function runs in AuthMode.FULL
. In this authorization mode, the
add-on can run a complex setup routine. You should also
use onInstall()
to create menu items, since the document, form, presentation,
or spreadsheet is already open and your onOpen()
function hasn't run.
The following sample shows how to call the onOpen()
function
from the onInstall()
function:
function onInstall(e) {
onOpen(e);
// Perform additional setup as needed.
}
The Editor add-on is opened
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()
functions. The authorization mode that onOpen()
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. The following sample shows a basic onOpen()
function:
function onOpen(e) {
SpreadsheetApp.getUi().createAddonMenu() // Or DocumentApp.
.addItem('Insert chart', 'insertChart')
.addItem('Update charts', 'updateCharts')
.addToUi();
}
To add dynamic menu items based on stored Apps Script properties, to read the contents of the current file, or to perform other advanced tasks, you must identify the authorization mode and handle it appropriately.
The following sample shows an advanced onOpen()
function that changes its
action 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();
}
Note that add-ons can't open sidebars or dialogs while executing in
AuthMode.LIMITED
. You can use menu items
to open sidebars and dialogs since these run in AuthMode.FULL
.
A user runs the Editor add-on
When a user clicks an Extensions menu item,
Apps Script first checks 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 is enabled in the document, form,
presentation, or spreadsheet if it wasn't already.
Troubleshoot add-on menus not rendering
Your add-on menu might not render if your code doesn't manage the authorization modes correctly. For example:
An add-on tries to run an Apps Script service that isn't supported by the current authorization mode.
An add-on tries to run a service call before a user interacts with it.
To remove or rearrange a service call that's causing permission errors in
AuthMode.NONE
, try the following actions:
- Open the Apps Script project for your add-on and locate
the
onOpen()
function. - Search the
onOpen()
function for mentions of Apps Script services or objects associated with them, such asPropertiesService
,SpreadsheetApp
orGmailApp
. - If a service is used for anything other than creating the UI elements,
remove it or wrap it in a comment block.
Leave only these methods:
.getUi()
,.createMenu()
,.addItem()
, and.addToUi()
. Also find and remove any service that is outside a function. - Identify functions that could contain the lines of code commented or removed in the previous step, particularly those that use the information they produce, and move the service calls to the functions that need them. Rearrange or rewrite your codebase to accommodate the changes made in the previous steps.
Save the code and create a test deployment.
When you create a test deployment, make sure that the Config field is Installed for current user and that the text below the Config box says Test in
AuthMode.None
Launch the test deployment and open the Extensions menu.
If all menu items are displayed, the problem is fixed. If you only see the Help menu, go back to step 1. You might have missed a service call.