1

I have an authorization problem, but I can't figure it out.

  • I have 50+ spreadsheets each for a separate user in our company.
  • Each user spreadsheet has a container-bound script that accesses a standalone library called "Library" where all my code is hosted.
  • The user bound scripts all have installable triggers (onEdit and onOpen) on them so that the library code is run as the admin user, not the individual users.
  • Therefore each user is given google drive access to their own spreadsheet, but not the library or other spreadsheets that the library accesses.
  • This makes it easy to update the code for all users, and so that the individual users do not need direct access to the central resources.

This setup has worked great for us for years, but now I'm trying to implement dynamic forms using html dialogues.

The problem I'm having is that google.script.run is working great for the admin user that is the owner of all the resources, but not for the individual users who only have access to their own spreadsheets.

Here's the file structure with simplified code:

User's container-bound script "Codes.gs" contains:

function userOnEdit(event) {
  var range = event.range;
  if (range.getValue() === true && range.getSheet().getName() == "Mileage Form" && range.getA1Notation() == "F1"){
    Library.testHTML();
  }
}

function getData(){
  return Library["getData"].apply(this, arguments);
}

The Library's "Codes.gs" contains:

function testHTML(){
  var html = HtmlService.createTemplateFromFile('testDialogue').evaluate()
  SpreadsheetApp.getUi().showModalDialog(html, 'Test Submittal');
}

function getData(){
  return "myData";
}

The Library's "testDialogue.html" contains:

<!DOCTYPE html>
<html>
<head>
    <base target="_top">
</head>
<body>
    <div class="container">
        <label for="response" class="form-label" id="response_Label">Loading...</label>
    </div>
</body>
<script>
  function dataLoaded(data){
    document.getElementById("response_Label").innerHTML = data;
  }
  function onFailure(error){
    document.getElementById("response_Label").innerHTML = "ERROR: " + error.message;
  }
    function afterDialogueLoads(){
    google.script.run.withSuccessHandler(function(data){dataLoaded(data)}).withFailureHandler(onFailure).getData();
  }
  document.addEventListener('DOMContentLoaded', afterDialogueLoads);
</script>
</html>

Within the user spreadsheet, I am using a checkbox in the cell 'Mileage Form'!F1. When that checkbox is marked TRUE, the userOnEdit is triggered and run using the admin's credentials since it's an installable trigger created by the admin. If the admin has the user's spreadsheet open and triggers the checkbox, then the html modal dialogue pops up with "Loading..." and after about 5 seconds it changes to "myData", which is exactly the expected behavior based on this code.

However, when the user (not the admin) has the spreadsheet open and checks that checkbox, the html modal dialogue pops up with "Loading..." but then the withFailureHandler triggers and results in this error: "ERROR: Authorization is required to perform that action."

And I can't figure out how to grant authorization for google.script.run as the admin via the installable trigger. Usually this is requested when the trigger is installed, but when I remove the trigger and add it back, it doesn't request an additional authorizations. Here's my oathScopes: "oauthScopes": ["https://www.googleapis.com/auth/script.projects", "https://www.googleapis.com/auth/script.container.ui", "https://www.googleapis.com/auth/script.external_request", "https://www.googleapis.com/auth/spreadsheets", "https://www.googleapis.com/auth/drive", "https://www.googleapis.com/auth/gmail.send", "https://www.googleapis.com/auth/gmail.compose", "https://www.googleapis.com/auth/gmail.modify", "https://www.googleapis.com/auth/script.scriptapp"]

Please help!

1 Answer 1

1

Library permissions:

Script users (spreadsheet owners/editors) should have edit or view access to the library in order to be able to execute the library code.

Effective user:

Make your script able to detect if the google.script.run effective user is the same as the active user and when they were different, suggest your users to

  • create and use an specific web browser profile for the account to be used
  • access the spreadsheet using the incognito / private mode and only sign-in in a single Google account

You also could share the library and the related files with anyone with the link instead of only with some users.

NOTES:

The effective user that interacts with the client-side code of a dialog/sidebar will be the "active user" not the user who created the installable trigger. The "active user" could even be different than the active user in the Google Sheets UI as it will be the default user according to the Google multi-account sign-in feature. This is an issue that have being reported to Google several years ago.

If you don't want to give permissions to the spreadsheet users to run the library code, then instead of using google.script.run you should use another way to call the server side code. One way is to deploy a web app and call it by doing a post http request by using the URL Fetch service.

Related

Libraries permissions

Multiple signed-in accounts

Sign up to request clarification or add additional context in comments.

8 Comments

Hi Rubén, thanks for the response. I've had 50+ users using this library and have never had to share it with them for it to work on their spreadsheet. It's just installed as a library resource on each of the user's bound scripts, and they've been able to use it just fine (via the installed triggers which actually run as the admin user that owns the library even though another user triggered it). Anyway, to be sure I shared the library with a user and tested the above script again as that user and got the same error.
@AlexLibengood Edited my answer. P.S: this question is about google.script.run not about installable triggers
I think that you are assuming that the effective user for google.script.run is the same as the effective user of the installable trigger, but that isn't. I added a note trying to clarify this.
I've confirmed that google.script.run is trying to run the server side code as the active user, not the authorized user who installed the trigger. For that I would need to get the active user to authorize the Oauth scopes that the library has, & give them access to all the resources that the library accesses. Unfortunately this is not an option for my use-case. I'm intrigued by your note about finding another way to call the server side code. A web app may work, but exposes resources to outside actors. Is there another way to run server-side code from the client environment as authorized user?
@AlexLibengood I suggest you to post a new question including the limitations/restrictions that you / your solution are facing.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.