Get user email without full permissions - google-apps-script

I need to get the email of the user accessing the web app. The web app is embedded in a google site.
I know how to do that with the following:
var email = Session.getActiveUser().getEmail();
However, that requires that the user grant permission to the script and the permission message is quite scary: it allows to send email on the user behalf, modify any of his/her google sheets, and so on.
Is there a way to avoid that wide range of permissions just to get the user email?
Update: my script also need to update a sheet, but does not have to be updated by the user. However, I need the user to run the app themself to get their email.

The permissions referred in the question
it allows to send email on the user behalf, modify any of his/her google sheets, and so on.
aren't related to
Session.getActiveUser().getEmail();
According to https://developers.google.com/apps-script/reference/base/session#getactiveuser the above method only requires
https://www.googleapis.com/auth/userinfo.email
If you want a less "scary" permissions you should have to remove the methods that require them or set the oAuth scopes manually in the manifest and/or th oAuth consent page of your project.

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")

How to get active user's email in apps script?

So I have a company website which has different permissions for different users. The authentication works by comparing the current users google login email to the ones on a google sheet, and that way gets the correct permissions for the website. The program works well, but can't detect the email from an user who isn't the editor of the script. I understand this is to prevent websites collecting email adresses, but is there a way to ask the user's permission to view his/hers login email adress name in order to get the correct permissions?
The code looks like this:
var user = Session.getActiveUser();
var email = user.getEmail();
var sheet = SpreadsheetApp.openByUrl('link to the google sheet I use').getActiveSheet();
...
//In a loop to go through sheet:
if(sheet.getRange(i,1).getValue() === email && email !== ""){
//Continue...
}
If i try this with other users, the email is blank. Any idea what I could do?
According to the Apps Script Web App documentation here:
The permissions for a web app differ depending how you choose to execute the app:
Execute the app as me — In this case, the script always executes as you, the owner of the script, no matter who accesses the web app.
Execute the app as user accessing the web app — In this case, the script runs under the identity of the active user using the web app. This permission approach causes the web app to show the email of the script owner when the user authorizes access.
Therefore, in order to retrieve the email of the current user you will have to change the permission to Execute the app as user accessing the web app.
Reference
Apps Script Web Apps.

How to change email signature via google form with data from google directory

I am using a Google Apps Script to change the signature of each user with personal data which is accessed via Directory API. Therefore I have a Service account with Domain Wide Delegation, which impersonates with an admin account to get all the users and their data and then impersonates which each and every user to change the signature via GmailAPI.
However now in addition I want to provide a Google Form for each user where the user can add additional information to its signature and set it. The script will need the users information from the Directory but I was wondering if the same approach with impersonating is needed.
With The Apps Script advanced Gmail Service it is possible to set the signature but I did not find a way to access the users data in the Google Directory of the specific user which is sending the form.
If I a service account is needed for that I was wondering where to store the access credentials for that? I don't want is be accessible by every user.

(How) can I publish a Google Sheet and associated Google Apps Script organization-wide and avoid or suppress authorization prompts?

Our organization uses Google Apps for Work. We have a Google Sheet "form" for employees/users to complete. After entering information, users are expected to use email as attachment/PDF. Finally, users click a "button" near the bottom of the sheet that triggers a script to clear user data. The first time a user clicks the button, an "Authorization Required" prompt appears, informing the user "the application" (script) "needs authorization to run." If approved, the prompt goes on to request View and manage your spreadsheets in Google Drive permissions for the script.
Is it possible to digitally sign or otherwise pre-approve a Google Apps Script for all users in a Google Apps organization so this prompt doesn't appear? We can/will include instructions for users, to head off questions / allay fear, but many of our users will either ignore or not understand the instructions and be perplexed.
I'm open to (and exploring) other options for tackling this (Google Forms/Sheets?), but prefer to stay in the (native) Google Apps environment as much as possible.
I couldn't find this question elsewhere and as best as I can tell, it isn't answered in Google Apps Script documentation.
I have found no way to pre-approve an organization/group/individual without manually doing it for each account.
You CAN deploy the script using a service account and have it run as that account. Then you are authorizing that account and the end user's accounts do not come into play. The drawback is that if you want the emails to go out using the end user's email, it won't happen. Plus the sending of the email would have to be from code in the app. That means all emails would go out using the service account's email address. (Although I am now wondering if it is possible to initiate the email without sending it. Basically pop it up as if a mailto link was clicked.)
You also will not be able to get the end user's name, etc. If these items are not important, or you can trust them to fill out their name where it may be needed (you could change the From name to what they key in) then running as the service account may work for you.
Karl

Provisioning new accounts with template data across accounts

When a new user accepts an invitation for a new account to use my program by clicking a URL I have to accomplish in script:
copy data from a template spreadsheet to a new spreadsheet for the new user
There are several conditions to work around:
- the template spreadsheet to copy resides in the administrative account
- the web app for the user is configured to log with the user's account, not my administrative account
I am struggling with how to read and copy the template spreadsheet data while logged into the user's account? As Google Apps has no scriptable interface for accessing a spreadsheet from a different account..even though the user will have read privilege to the template spreadsheet.
I have contemplated different ideas but am not sure..can I chain web apps together and pass data between web apps accessed from different accounts? Or, do I have to script a totally new data store other than spreadsheets and Google Drive? The new data store would have to be accessible from both the administrative account and a user's account.
If you program is a GAS WebApp, then deploy it from your admin account with settings:
Execute the app as: me (admin.account#yourdomain.com)
Who has access to the app: Anyone
This way the server-side code of your app will run under admin account, and will have access to your template spreadsheet, and signed-in users will be able to interface with the client-side of your app. You may have to implement some user authorization in your app, so only specific users who received an invitation are allowed to access it. For example, you can store users' email addresses in a sheet in your admin template spreadsheet, and check if current use is in the list before creating an account for the user. Session.getActiveUser().getEmail() will give you current active user's email address. Similarly you can check if an active user already has an account created.
If your program is not a GAS WebApp - please edit your question to add more pertinent details.