How to prompt user of container-bound script to "review permissions" - google-apps-script

As far as I've read google app script is supposed to show you a prompt to review permissions automatically if you have not authorized your app yet. However this is not happening and I also cannot find a way to manually trigger such a prompt that can be used within onOpen(e).
What I would like to achieve is my app prompting users to review permissions when they have not authorized the app yet.
What I have tried:
Letting GAS automatically detect used scopes.
Manually setting scopes using the appscript.json file.
Using Ui.showModalDialog() and ScriptApp.getAuthorizationInfo().getAuthorizationUrl() to manually guide the user to permissions. However, this results in the error:
Google Apps Script: Exception: You do not have permission to call Ui.showModalDialog.
Required permissions: https://www.googleapis.com/auth/script.container.ui

Issue:
You are using a simple trigger (onOpen). Simple triggers cannot access services that require authorization.
Solution:
Install your trigger, either manually, following these steps, or programmatically, executing this:
function installTrigger() {
ScriptApp.newTrigger("yourOnOpenFunction") // Don't call it onOpen
.forSpreadsheet(SpreadsheetApp.getActive())
.onOpen()
.create();
}
The authorization is given when installing the trigger.
Note:
The installed trigger will run under the account who installed it. Therefore, this is not a good approach if the actions made by the trigger depend on who is executing it, and I'd suggest displaying the dialog through other means, like clicking a button, or similar.
Reference:
Simple triggers: Restrictions

Related

Google Apps Script AddOn: onChange trigger programatically with misleading permission scope text

By Google documentation, an onChange trigger for a Spreadsheet addon has to be created programmatically via ScriptApp.newTrigger(...)....
newtrigger requires the scope :
https://www.googleapis.com/auth/script.scriptapp
When the user is asked for granting permissions, the text presented is:
Allow this application to run when you are not present
I understand this function can create time based trigger, but for a simple onChange in a Spreadsheet, I would understand if the user declines it due to that text.
Is there a way to have an onChange trigger without this scope for changes (not onEdit) in spreadsheets?
Answer:
The only way to create a trigger on behalf of a user programmatically is using ScriptApp.newTrigger(), and this method requires the https://www.googleapis.com/auth/script.scriptapp scope. No other scope will allow this to run.
You can however set up an onChange() trigger for the Spreadsheet, which will run regardless of who makes the change to the sheet.
More Information:
When you set up a trigger, you are allowing an app/script/function to run, on behalf of you, without you manually running the function. Asking a user to create a trigger will require them to authorise that they consent to the script doing something on their behalf.
You can however, set up the trigger yourself. As long as the function that will run on the trigger doesn't violate any of the installable trigger restrictions then this will run on the Sheet as long as it has been authorised to run by you.
Remember though, that if you set up the trigger yourself, the script will always execute as you, not as the user. So if the function, for example, sends an email, then the email will be sent on behalf of you - as you were the one that authorised the script.
Setting up an Installable Trigger manually:
If setting up the trigger to run as you is an acceptable solution, you can do so by following these steps:
Save the script with the save icon, press the run button (►), and confirm the authentication of running the script.
From here, following the Edit > Current project's triggers menu item, you will have a new page open in the G Suite Developer Hub. Click the + Add Trigger button in the bottom right and set up the trigger settings as follows:
Choose which function to run: <your-function-name>
Choose which deployment should run: Head
Select event source: From Spreadsheet
Select event type: On change
And press save.
This will now run on all changes made to the sheet - regardless of who made the change. Just remember that as far as execution goes, you're the script runner.
References:
Class ScriptApp | Apps Script - .newTrigger(functionName) method
Installable Triggers | Apps Script - Restrictions
Event Objects | Apps Script - Google Sheets events: Change

Who is the "caller" when calling Form Submit installable trigger?

I have recently published a Google Forms add-on that access a Classroom Course roster right after the Form is submitted.
I manually installed the onSubmit trigger in my script and it worked fine. I copied the code to another Form and worked too, with GSuite and non-GSuite accounts.
The problem is that now that the add-on was published, I tested it and it doesn't work. Searching the GCP, in the Logs viewer I found a "The caller does not have permission at onSubmit(Code:40)" error from the API when calling the classroom method.
So, the trigger is working, but for some reason the permissions fail. I checked the scopes and they correctly request the appropriate permissions for the classroom method the onSubmit function calls. I'm wondering if the problem is that I manually installed the trigger and I should have it programmatically installed within the script.
Thoughts?
It turns out the answer depends on whether the trigger was manually installed or programmatically installed. If it's the former, then the "caller" is whoever installed the trigger (typically the developer) and if it's the later, then the "caller" is the user who installs the add-on (which was my intention).
Thanks Alan!

You do not have permission to call "UrlFetchApp.fetch"

I am sending http request from script editor in google spreadsheets, but I keep getting the following error message:
`Google Apps Script: You do not have permission to call UrlFetchApp.fetch. Required permissions: https://www.googleapis.com/auth/script.external_request`
I am using onEdit function:
function onEdit(e){
var ui = SpreadsheetApp.getUi();
var response = UrlFetchApp.fetch('http://www.eur-api.idomoo.com/');
Logger.log(response.getContentText());
}
I don't know Why am I getting this error? and I also gave permission to script.external_request scope, Any help would be appreciated.
onEdit is invoked by a Simple Trigger when a user changes a value in a spreadsheet.
However, simple triggers cannot access services that require authorization, such as UrlFetchApp.fetch. See the Google Apps Script guide
What you can do is to simply rename the function onEdit to something else, such as atEdit, so as to remove the simple trigger. Then follow the Current project's triggers menu...
and add a trigger to be called in the event of On edit.
And when creating the trigger, you will follow the Wizard to grant your apps script permission to connect to an external service.
There are two ways to solve this
I. Update your manifest and add the line "https://www.googleapis.com/auth/script.external_request" to oauthScopes
{
"timeZone": "Europe/Moscow",
"oauthScopes": [
...
"https://www.googleapis.com/auth/script.external_request"
],
"dependencies": {
...
},
"exceptionLogging": "STACKDRIVER"
}
II. Or remove oauthScopes key from your manifest totally
You can find how to edit the manifest here Manifests
I know its an old thread, but I find it weird of having to rename the method to something else, e.g. from onEdit to onEditHandler just to make it work. It turns out that I can make it work by:
Remove the trigger.
Re-add the trigger.
This is possible probably due to previously the handler doesn't have the fetch url, therefore it doesn't have to ask for authorization to access external request. Once it is re-added, then it has the proper authorization because you are asked to re-authorize the handler.
You'll need to authorize your script to access the external_request service. If you're the owner of the project, you should be able to grant access by running and confirming with the oauth page.
Read more about authentification here: https://developers.google.com/apps-script/guides/services/authorization
I experienced this error after adding the onEdit function without also explicitly adding a trigger. This was resolved by adding an onEdit trigger that calls the function. Triggers -> Add Trigger, On edit event type.
Try changing the link https.
Looking at their api documentation:
API Endpoints
Idomoo’s API 2.0 has several endpoints all starting from one of several roots, depending on the territory in which you want your data sent to and processed:
USA https://usa-api.idomoo.com/api/v2
EU https://eur-api.idomoo.com/api/v2
You should
Remove Current triggers
and then
create new trigger by selecting event "OnEdit"

Script does not have permission to perform that action after authorization granted CalendarApp

I've been executing a gscript for a couple years now, but just today I started seeing the following when I try to execute it:
The script does not have permission to perform that action. Required
permissions: (https://www.googleapis.com/auth/calendar ||
https://www.googleapis.com/auth/calendar.readonly ||
https://www.google.com/calendar/feeds)
I went ahead and deauthorized my script from my Account permissions page and re-ran the script to force re-auth, but I'm still seeing the error.
The line in question is simply trying to do:
CalendarApp.getDefaultCalendar()
Any idea on how to resolve this issue?
From what error you've encountered, it indicates that the script lacking the authorization needed to run. When a script is run in the Script Editor or from a custom menu item an authorization dialog is presented to the user. However, when a script is run from a trigger, embedded with a Google Sites page, or run as a service, the dialog cannot be presented and this error is shown.
If the script contains new unauthorized services, you must re-authorize the script. Here's a documentation on how to troubleshoot this type of error in Google Apps Script.
If a trigger continues to fire and cause this error, you can access your triggers by doing the following:
Select Edit > All your triggers in the Apps Script editor. The resulting dialog shows all active triggers running on your account.
Find the offending trigger in the list.
Click the clear icon next to the trigger name to remove it.
Click Save to record the deletion.
You can also remove problematic add-on triggers by uninstalling the add-on.

Creating time-based trigger from WebApp

I am trying to create a time-based trigger from a Google Apps Script published as a WebApp.
Update: this WebApp shall be run as the user accessing it, not as the Apps Script owner.
Whenver I even try to access the ScriptApp services, I get an error in the frontend:
Authorization is required to perform that action.
Sample code to reproduce this would be:
function doGet(request) {
ScriptApp.newTrigger('test');
return ContentService.createTextOutput("OK");
};
function test() {
// noop
}
Is this something that is not possible? Is it possible to somehow automatically add a trigger that runs a method based on time with the user giving the authorization?
Under what credentials is your web app run ? As the user running the app or as yourself.
From the error, it looks like it is run under the author's credentials.
In this case, you should authorize the application explicitly before you can distribute the URL. To do so, open the script editor and choose any function and try to run the function using the little 'play' button in the script editor. You'll be asked to provide permissions after which you can use the Ui App