Execute web app with Gmail access as user who executes the script - google-apps-script

I started quite recently experimenting with web apps, and I am now busy getting them to run across accounts within my organization.
I need to update labels to Gmail emails across these accounts, as well as update a shared spreadsheet. I trigger my scripts via a get request triggered from the client details spreadsheet, which identifies the email threads in the associated accounts and applies them a label.
For this to work without having to create a web app per account executed as the owner of the account, I imagined that a deployment executed as the user who executes the trigger would just do it. However, doing so results in an html response that seems to be an authorization screen from Google.
I am not very familiar with the required authentification concept in this case, as I had no issue since a year than I work with Google scripts. I guess Google should show the authentification prompt like they always do, but in this case it's not showing up.
It works fine when the app is run as myself, but I’d hate to have to replicate and maintain the project on each account, even though that is a way to achieve the result.
I read a number of articles, but many did not apply to my situation, and others were beyond my current skill to try them all out. I also tried a few things in the cloud console but I am too noob to get my head around it fully.
I use the required oAuth scopes and don't see what can be missing. I tried putting "Authorization": "Bearer " + ScriptApp.getOAuthToken() in my request's headers but this makes no difference.
Thanks in advance for your help!

Related

Some users get an error and weird URL when trying to access my Google Script. Debug Tips Welcome

I wrote two small Google Scripts that present simple forms to fill in. Most of my user community has no trouble using them. A small minority of users can never open the forms, instead they get "Sorry, unable to open the file at this time" error page for both forms. I can't find any common thread for why only some users fail. I've tested on multiple browsers on multiple machines, even on android devices, it never fails for me.
A couple of things I've noted:
when it fails for them the URL is re-written. The proper url starts with https://script.google.com/macros/s/... but for broken users when they paste that in they instead get https://script.google.com/macros/u/3/s/... (notice the "u/3" at the end)
There is no execution log created when they try to access the site, so I have no way to debug what's going on.
The app is permissioned so "Anyone" can access it, and it runs as my account
Sorry, I realize this problem description is impossibly vague. Any debug suggestions would be extremely welcome. I'm not a regular Google App Script developer, so I'm kinda stumbling in the dark with this one. Thanks in advance.
/u/3 means that the user have signed-in into multiple Google accounts, the number correspond to the zero-based index of the account in the order that the user followed to sign-in, 0 is for the default account, 1 is to de second account, 2 is for the thirds account and so on.
So, on your test include this use case, a user signed-in into multiple Google accounts.
NOTE: It's known that the HTML Service do not handle as expected this use case.
Related
AuthMode gets confused w/ multiple logged in users
We're sorry, a server error occurred while reading from storage. Error code PERMISSION_DENIED
Why is my script pushing an incorrect URL? [/u/2 inserted into script URL] (possible duplicate)

In Google Apps Script, avoid second 'Review Permissions' prompt, possibly by using approval_prompt

I have searched StackOverflow, etc. for a solution to this problem, and several answers 'point me in a direction' (mentioning approval_prompt = auto not approval_prompt = force), but none are applicable (as far as I can tell) to my situation.
I have a Web Application hosted at www.mjpanel.com that expects to use a Google Apps Script that I 'own', but the Javascript at www.mjpanel.com calls the Google Apps Script (deployed as a Web App with doGet()) as a Web Service. It expects the web service call to return various JSON objects.
If the user has not yet authorized my application, the call to the Google Apps Script Web App / Web Service will not return a JSON object, causing www.mjpanel.com Javascript code to fail saying "Invalid Request" (because it isn't a JSON object as my code expects).
To prevent this from happening, www.mjpanel.com uses gapi.auth2.init to get the permissions/scopes it needs. I'm developing everything now, so if/whenever the Google Apps Script evolve to use something (like sending GMail emails as the user) that is new, I have been figuring out the scope to request, adding it to the list of scopes in the gapi.auth2.init call, and everything is fine. The next time a user uses the app., they get initially prompted for the newly added scope, then everything proceeds fine.
However, now sometimes one of my test users has a Web Service call fail because Google Apps Script is returning another request for permissions for a 'new permission' of 'Have Offline Access'.
There's nothing about my script that would warrant the user needing to grant this permission.
When I research, a lot of stuff (mostly about requesting OAuth2 stuff in a 'structure' different than the way my app. is set up) says it has to do with submitting a 'approval_prompt=force' in my request URL.
However, the way I have my app set up, all the URLs I would use (aside from my 'custom stuff' in the query string) are dictated by Google Apps Script. And I can't find any place where any URL I use has an approval_prompt in it.
I can't figure out where I would need to configure that approval_prompt to be auto (as is recommended in the 'successful answers' I find).
Of if the idea of approval_prompt is 'on the wrong track', any information in general to help me solve this problem would be greatly appreciated.
Thanks in advance for any help you can give me.
Unfortunately the Google Apps Script native OAuth flow includes approval_prompt=force. This causes the following conditions:
If cookie exists in browser and has permission for this application the consent screen will not be displayed.
If cookie exists in browser but does not have permission for this application: consent screen will be displayed
If cookie does not exist in browser and the application has permissions: application will request 'Have offline access'.
The easiest way around this is to manage your own OAuth flow and use the Execution API. The following link will take you to the javascript quick start.
https://developers.google.com/apps-script/guides/rest/quickstart/target-script

Google Apps Script - Access to different account (contact-api) via OAuth2-authentication

Retrieve/Update Google-Contacts from Apps Script (Spreadsheet)
Environment Desc:
We have a shared spreadsheet belonging to a domain-account "PrimContact" where we also manage our contacts.
The spreadsheet is shared with selected users in the domain with r/w-access.
Workflow so far: after making changes to the spreadsheet persist those changes through script-call.
This api-call was authorized via clientAuth and as of a few days that won't work anymore.
Through clientAuth we were able to allow all the users to manipulate the sheet and finally update
the contacts of the targeted contact (PrimContact).
Problem:
Reading up about deprecation of clientAuth I tried, and somewhat succeeded, to change
authentication to OAuth2. As I understand things there are two ways I can authenticate a
user. Through a clientAccount or via serviceAccount.
SideNote: The following two pages helped a lot in getting it done, especially for serviceAcc.
[1]client account with: https://github.com/googlesamples/apps-script-oauth2
[2]service account auth with: https://github.com/mcdanielgilbert/gas-oauth2-gae
For that to work I added a project to PrimContact-user and created both a web-account and a
service account. Using aforementioned scripts as a starting point authentication works too, but
in the end it's not what I am trying to accomplish.
Client Account: the script is calling the api (contact-api) with an access token for the currently
logged in client although I provided the clientId of the PrimContact-user. Now I COULD run the script as PrimContact-user beforehand and store the token
in the document. If the access-token has not expired yet the other users can work with this
token just fine and therefore "operate" on the PrimContact-data. But as soon as the token
expires I would have to call the script as PrimContact-user again, which is not to very comfortable.
Service Account: got it working with gas-oauth2-gae, but the contact-list is empty. The call
itself is successfull though. I guess this is due to the service account not being tied to
the PrimContact-user although the project is associated with this user?
Goal:
Making an api-call (contacts) inside google-apps-script(spreadsheet) used by different users and
manipulate contact-data of a different account, i.e. the account who originally shared the spreadsheet.
Maybe I'm getting the whole idea of OAuth2 completely wrong, so far my understanding of the
clientAccount-thing is that the currently logged in user allows the project (which belongs to the
PrimContact-user) to manipulate the data of the currently logged in user.
What data the service-account-authenticated call is manipulating.. I'm not quite sure..
If it helps I can add the code-snippets, but as everythings "working" & still not doing what
I really need it to do I'm not sure if it's helpful.

Apps Script HTML Service Post request / sheet append limits

We have a chrome extension that posts data back to a Google Apps Script app and I'd like to know if I'm going to hit any limits at Google.
The Apps Script app has a doPost function that takes the information that was passed across and uses appendRow to add the content to different sheets. Very similar to how forms works but allows us to deploy to users (via the chrome extension) and have a better looking UI.
We're wanting to push this out to potentially thousands of users and we expect a few form submissions a day from each of them. Should I be expecting to hit any set limits with this?
I've already taken a look at https://script.google.com/a/netpremacy.com/dashboard but don't see anything that would indicate any limits.
Let me know if you need more info.
There are no published limits at this time. However, the key thing to ask with apps deployed as web apps is that is the App running as you (the developer) OR the users accessing the web app?
If its running as the users, then you are going to be ok with the volume. The quota is fully debited to the end user.
If its running as you, then you need to worry about other quota first - does it send out lots of emails, does it create a lot of documents, etc.
The only exception to quotas is ScritptDb that always consumes the script developers quota.

Google script quota

I am running an online free computer science education course website. I use Google scripts to evaluate the student quizzes (I use the MCQ script). Yesterday, there was a spike in visitors to my site. I noticed that the quiz scoring script is no longer sending results to students. I checked the failure notification, and it says "Service invoked too many times for one day:"
Is it because of a quota? If there is a quota, then is there any way to increase it?
My class has more than 800 students, so it is likely that they will submit their homework on the very day I post it online. So, I badly need to increase the email quota. If there is any workaround, that will also be very useful to know.
Thanks in advance.
If you deploy the app to run as the user executing, not as you, then it will run with their quota. However, they will have to click to authorize sending mail, and it will appear to have come from their own account to themselves.
The quotas are shown on the dashboard that can be also accessed through a link in the side panel of the documentation page. I'm afraid you hit quotas for email service.
...
EDIT : Ah, didn't see Corey's answer... smart suggestion of course ;-)
Try using an external API (i.e. Mandrill). Mandrill (it's by Mailchimp, so it's pretty robust) has an easy external API with much larger limits (in the order of thousands).
You can even set the from address so that it wouldn't look spammy (or, really, any different than the normal Google Apps Script send email).
Take a look at Use Mandrill API in Google Apps Script.