Force asking permission with Apps Script? - google-apps-script

I'm developing an Apps Script that has a sidebar and a dialog, each need differing levels of permissions to ask the user to be granted.
The application needs access to Read/Write the user's Google Drive API, Google Picker, access to Web Cam and Microphone, Web Speech API, and Google Docs API.
How can I get prompt the user once for all permissions needed, instead of having to force the user to launch open the sidebar and dialog once separatelu, each via the add-on menu?

You can add naked API app calls in the host script to prompt any scopes you will subsequently need. e.g.
var cal = CalendarApp,
Drv = DriveApp,
…
etc.
This will prompt for permission for access to users calendars
The webcam is a different beast however and will depend on a users browser settings and indeed which browser they are using. Chrom, for example, has an option to always prompt for permission to use the webcam.

Related

User access request when GAS run as the user

In a GAS published as webapp bound to a spreadsheet in a public (free) Gmail account, I'm compiling information from many unrelated users into that spreadsheet, where any Gmail user account can access the webapp.
But when script is run as the user, the user can access the app (after user grants permissions to the app), but it stops at point where script accesses the spreadsheet. The user is told to request access. I have to "share" the spreadsheet to the user for the app to function when run as that user, but that is problematic--too many potential users.
If another version of the script is run instead under my account, then user has access to the webapp, but the script cannot access the user's Gmail address. Big problem because the webapp must have the user's Gmail address for security/application access controls.
(The webapp is in development and Google "approval" has not yet been sought.)
How do I have a webapp (a) that modifies content in a central spreadsheet, (b) that any Gmail user can access, (c) where the script has access to Session.getActiveUser().getEmail(), and (d) the user does not need to have edit permissions for that central spreadsheet? The only user-account information that the script needs is the user Gmail address--again for application access control and security. (Since Google provides me a link that gives anyone full access to the spreadsheet (if they also have its URL), can't I give the bound script access to the spreadsheet when run under any Gmail account, where the integrity of the spreadsheet content is managed through the app's functions and internal access controls?)
If there is no solution except to run the webapp under the user's Gmail account and give that user edit rights to the spreadsheet, would that create significant risk (where I don't intentionally/overtly disclose the spreadsheet's URL) that a user could access and alter the spreadsheet beyond the insert/edit functions performed by the webapp? If that risk is low, is there a function I could use in the webapp to automatically grant spreadsheet edit rights to a Gmail account when its Gmail address is pre-registered in the user list for the webapp?
Thank you!
Let me start with c): there is no way to make that Session.getActiveUser().getEmail() works for free Google accounts (i.e. gmail.com accounts) other than for the container / script owner.
Regarding a) b) and d) you might use the Google Sheets API making the calls to it by using UrlFetch Service and a service account instead of the Spreadsheet Service or the Advanced Sheets Service.
Regarding allowing anyone to edit a central spreadsheet, once they open it either by using the Google Sheets apps or by means a web app, they will be able to find the spreadsheet in Google Drive > Shared with me among other places... IMHO the risk in terms of how likely is to have issues is big but in terms of the the impact depends on several factors, i.e. some changes might be reverted by using the version history but spreadsheet might become corrupted. If you have not used Google Sheets version history intensively the best is to get deeply familiar with it before relying on it as a backup / disaster recovery main tool .
From https://developers.google.com/apps-script/reference/base/session#getactiveuser
getActiveUser()
Gets information about the current user. If security policies do not allow access to the user's identity, User.getEmail() returns a blank string. The circumstances in which the email address is available vary: for example, the user's email address is not available in any context that allows a script to run without that user's authorization, like a simple onOpen(e) or onEdit(e) trigger, a custom function in Google Sheets, or a web app deployed to "execute as me" (that is, authorized by the developer instead of the user). However, these restrictions generally do not apply if the developer runs the script themselves or belongs to the same Google Workspace domain as the user.
Related
Use Apps Script URLFetchApp to access Google Datastore Data
Google Service Accounts / API - I keep getting the Error: Access not granted or expired. (line 454, file "Service")

Authenticate in Sheets Add-on to App Using Google OAuth

I am creating a Sheets add-on that works with our app. Our app uses Google OAuth for authentication.
I have the add-on working with manually configured credentials, but obviously that's not a real life solution. Now I need to have the add-on user authenticate to our app within the add-on itself, so we know whose account to work with.
User has data in Sheets -> user uses add-on to authenticate to app -> add-on uses app's API to push/pull data between Sheets and app for that user
I have tried using our API's login URL to get the HTTPResponse from Google using fetch() and loading it into a sidebar, but aside from it being ugly, it doesn't give me the expected option of choosing the Google account I want, but rather logging in from scratch, and when I enter my Google account, it doesn't do anything other than continue giving me errors about the frame being sandboxed. The threads here and here don't seem to address the issues as they're talking about iframe within the app, whereas I'm trying to use the sidebar in Sheets itself.
The app and the add-on are using the same GCP Project ID.
I need to get the same BearerToken that the app uses to use in the add-on.

Is there a way to build an Google Apps Script application that uses BigQuery Service as a service account instead as a user?

What I trying to do here is an application that connects to bigquery, executes some query and writes a spreadsheet in current user's Google Drive.
I know that I can change the "Execute app as" option when deploying the app. But when I do this, and the user try to use the app, Google asks for permission to access the BigQuery.
I do not want to give permission to each user to access BigQuery.
We have about 50 ~ 100 users who will use (and this number can increase)
Some images:
When access the application's url: http://i.imgur.com/kGzJ3ps.png.
When the user clicks in the "continue" button:
http://i.imgur.com/4cRmhZ6.png
Hope I've been clear.
You would probably need an App, that had people sign in with their Google account using oAuth2
Google Accounts Authentication and Authorization
I think that this link gives an overview of what your options are:
Permissions and Types of Scripts
I guess you would need to have an App, that ran as User at the keyboard, so that the spreadsheet saved to their Google Drive. If you wanted the user to be able to download a file to their computer drive, that's a little different.
Just use HTML Service. It's basically just building a website. You just don't have a domain name. But the spreadsheet you are distributing doesn't have a domain name.
HTML Service Google Documentation
From an Apps Script HTML Service, you can write to Spreadsheets, Documents, and run HTTP Requests (urlFetch).
URL Fetch Service
The permissions in the Apps Script App can be set to run the Apps Script file as yourself, with access to anyone, even anonymous. That way, the user will never be asked for permission for any files that you own. You will need to authorize it once, the first time any script that needs access to your files is run.
Because anyone could run your Apps Script App, you might want to have a log in system to authenticate users.
You would need to use the Big Query API with Apps Script urlFetch to access Big Query.
So, with the HTML Service, you can do most everything you could do with HTML, CSS, and Javascript on a regular website. You can create custom input forms, have different pages and display data in tables. Plus it's served over HTTPS.
One solution that you can use if you don't want all your users to enable BigQuery is to use a webapp deployed as a service running as "you" and that will respond to an urlFetch coming from each user through the script they run as "themselves".
This service will be deployed as any other webapp using a doGet main function and return its data using contentService
Yes, that is possible. Check out this answer here: Using Advanced Google Services with Service Account and also check this awesome library: https://github.com/googlesamples/apps-script-oauth2

Share a Google App Script to other users - permission requested & authorize script

I've created a spreadsheet with some GAS behind it that opens a form with some inputs, and now I need to deploy the webapp and share it to some other users. The problem is that when the other users try to open the spreadsheet (shared in Google Drive), they get this error message:
I've already tried to:
Share the spreadsheet to the user/s (Adding the user/s email address with permission Can edit)
Deploy the webapp settings with the following settings:
As you can see, the setting screen reports "You need to authorize the script before distributing the URL".
How can I authorize the script? I can't find a way to do that. Do you know if there's another way to share and let other users run the script?
Since you selected to execute the app as you, you need to authorize this script first.
Just select method doGet and press run in the editor, you will get the chance to authorize.
The problem is you are mixing web app with ui dialog on a sheet.
The webapp is accesed from the webapp url (given when you publish the webapp).
The ui dialog is a window shown on top of the spreadsheet.
You want to use webapp, follow the tutorial for that. Publish it to be accesed from the domain if all users are in the same gapps domain. Else use public anonymous.
Run doGet before publish to authorize. Its also possible to do the other ui-on-sheet but you need more steps for each user to authorize.
You need to manually verify that your script has access to the document.
Add a function to your script that accesses the document:
function doInstall() {
var mysheet = SpreadsheetApp.openById('x4535khxxhidh...');
}
In script-editor select: Run->doInstall (Or what ever you call your function) when you should be asked to verify that the script is authorized to access the document.
The following worked for me:
Go to «Publish»
Click on «Deploy as web app»
Click on «Disable web app» (in case you have published it already)
Execute the Script clicking on «Run»
Authorize the Script and grant permissions with your account
Again, go to «Publish» and click on «Deploy as web app»
Add another «Project version» (in case you have published it already)
Change «Who has access to the app:» to «Anyone, even anonymous» as needed

Delay the Authorization Dialog with GAS Ui Service

Is there a way to delay the Authorization Dialog in a stand alone Google Apps Script?
I have a public script that needs to be granted several permissions from the active Google user. I want to tell the user how the script works before asking for all those permissions.
It is not obvious why I need access to all the services, so this dialog looks scary :
https://developers.google.com/apps-script/scripts_google_accounts#grantingAccess
My script is a "web app' with the UI Service so the first thing to be displayed comes from doGet(), but the permission dialog opens first. Isn't there a way to delay the dialog until the permission is actually needed ?
One possible way would be to call the script from a dedicated website I suppose, but that's not simple.
One workaround is to have two web apps:
The first is an 'intro' web app that runs using your account, so it doesn't prompt the user.
Then, you redirect them to a second web app that runs using their account, which will prompt them.