How to Validate Specific Users on a Web App in Google Apps Scripts

validate users to access a web app with Google Apps Script

You’ve created an awesome Google Apps Script web app for your secret society within your Google Workspace organisation or …dom! dom! DOM! … the world. The problem is that you only want to share your web app with the worthy. Those selected few. 🐐🛐🛐🛐

How do you do this? How to prevent this most coveted of apps from reaching the wrong hands?

It’s actually surprisingly simple.

In this tutorial, we will explore how to validate selected users to provide access to your web app. For our example, we validate users based on whether or not they have edit access to a Google Drive file ( a common occurrence). In the discussion, we will also look at alternative ways of validating emails.

One of the bonuses of the approach we will go through is that it can also be easily adapted for use in Google Workspace Add-ons, and Editor Add-ons like sidebars and dialogue boxes.

We’ll start off with an example and then move to a quick-use guide for those of you who just want to get in and apply the code to your own project. Then for those who want to know how it all works, I’ll dive into the details.

Let’s get started!

The Example

We’ll keep our example short and clean here. Let’s say we have shared a bunch of editors on a sacred secret document that we have called ‘Patters of the Goat’. It’s a detailed guide on displaying the best method, etiquette, and reverence when petting your favourite goat.

validated users in a webapp apps script share document
Click to Expand!

In our web app, we will have two HTML files. One for valid users who are edit members of the shared file that displays ‘You are worthy!’ The other for when the user is not valid and does not have edit membership to the file that displays ‘You are not worthy!’.

validated and invalidated HTML

We will deploy our web app to execute as ‘User accessing the web app’ and deploy to either ‘Anyone with Google Account’ or if you just want to run it in your Google Workspace organisation, ‘Anyone within Your Domain.

validated users in a webapp apps script deployment parameters
Click to Expand!

It doesn’t matter if a user had been given edit permissions with their individual email or as part of a group. Likewise, if a new editor is added or one is removed, this will be taken into account each time the user attempts to access the web app.

The Code

The code below contains a small example of how to apply it to run the HTML file ‘Index.html’ when the user is valid or ‘NonUser.html’ when the user should not have access to the web app. These file names can be updated and, of course, the contents of the HTML files adapted to your needs.

Go ahead and copy and paste these files into your own project and deploy them to try it out. Make sure you change the FILE_ID to your own file and share one or two people/accounts. Then test it out on an account that has no access or view/comment access and see what happens.

webApp.gs

Index.html

NonUser.html

 

Quick Use

If you haven’t yet created a web app project you can run the sample above and use the guide below if you get stuck:

Google Apps Script: How to create a basic interactive interface with Web Apps

This tutorial can be quickly adapted to your own project by copying the validate() function into your code and then updating a few lines in your doGet() function that will initialise your web app.

Update the doGet() function

At the beginning of your doGet()function, add the following:

Line 3 will call the getActiveUser() method of the Google Apps Script Session class. We then call the getEmail() method to grab the active user. By active user, I mean the user who is running the script.

Line 4 is your file id to the file you have shared your editors on.

Line 6 then calls the validate() function taking the user email and file ID you gathered earlier as arguments. The validate() function returns true if the user is permitted to use the web app or false if they are not.

Finally, line 7 runs a ternary operator that checks if the isValid variable is true then it will assign the 'Index' to the htmlfile variable. Otherwise, it will assign the 'NonUser' file. You can, of course, update these file names to your own file names and modify the HTML files to fit your needs.

Adding the validate() function

Next, it is a simple case of adding the validate() function to your code.

Making some minor changes

You can make some quick changes to the validate() function to change from checking permissions a file to a folder and checking different types of permissions. Have a look at the three examples below.

Get list by editors of a folder instead of a file

In your doGet() function update your FileID variable to FolderID and replace it in the validate() second argument.

Within the emailList method inside validate(), change the getFileById() method of the DriveApp class with getFolderById().

You could also find and replace all the instances where it says ‘file’ with ‘folder’ if you want to tidy things up too.

Get users with ‘view’ access to file instead of editors

Here we can alter the validate() function again so that we only allow users to our web app who have ‘view’ access. Back in the email list method, change the .getEditors() method with .getViewers().

 

Get all users who have access to a file

If any user does not have any type of access to the file then when the DriveApp.getFileById() method is called it will report an error. This means that if we want to give access to our web app to anyone who can access the file, then we can simply use the first part of the emailList method exclusively.

 

IF you are keen to learn more about how the validate() function works. Read on, ya big legend!

Looking to learn more about Google Apps Scripts in a more structured format? Udemy has some great courses that can get you from the basics to a real Google Apps Script pro!

Got a more specific problem you need help with, but don’t have the time to develop the skills? Make an enquiry on my ‘Hire me!’ page. I occasionally pick up projects. Alternatively, Fiverr’s your best bet to find a skilled Google Apps Script developer to solve your problem quickly and professionally. *

*The above affiliate links have been carefully researched to get you to what you specifically need. If you decide to click on one of these links it will cost you just the same as going to the site. If you decide to sign up, I just get a little pocket money to help pay for the costs of running this website.

The video

Code Breakdown

In this section, we will take a quick look at the validate function.

The validate() function is set up as, I guess, a pseudo-class or closure with two private methods emailList() and groupEmailList(). This is just to keep things a little contained so we don’t have to worry as much about any naming conflicts with your own project.

Set user validity

First, we set user validity with our isValid variable. This is first set to false indicating that the user does not have access. This variable will be updated if the code finds that the user has access.

emailList()

The emailList variable contains either the list of editors in the list or group emails with edit permissions. We will wrap it all up in an Immediately Invoked Function Expression (IIFE) so that it is all nice and ready. Notice the extra outer bracket in the arrow function that finished with an empty bracket to create our IIFE – (function)().

First, we create the file variable to store our file constructor data that we will get from the DriveApp Google Apps Script Class (line 8). We will use a Javascript try…catch statement to catch the instance when the user has no access to the file. We attempt to call the getFileById() method from the DriveApp class using our fileID as the argument.

If we are successful, then this will store the constructor data for the selected file that we can extract our emails from in a minute. If we are not successful (catch), we will return false.

Lines 16-18, we use the file constructor to return the getEditors() method. This will provide us with an array of all the editor’s information for the file. Now we can use the Javascript map() method to iterate through this array calling the getEmail() sub-method for each editor.

Once outside of the emailList variable we check if it is false. If so, we update the isValid variable to false and return it to indicate that the user does not have access to the file.

However, we can’t simply stop here. It is often good practice for organisations to manage their permissions by groups. This means an owner of a document might be giving edit permissions to a group email rather than an individual’s email. The getEditors() method will only grab the email addresses assigned to the document or folder, whether they be a group email address or an individual one. We will need to check the users in a group in our next task.

an alternative approach (…ish)

You can also check the file permissions of a user by using the getAccess() method. Something like this:

While a little shorter and ostensibly faster, this approach suffers from the same problem that it does not check a user who is a part of a group with edit permissions (The user’s file access will result in ‘NONE’). Plus it doesn’t give us a convenient list of editor emails that we can use in a moment to check if the current active user is a member of an editor group.

groupEmailList()

For our groupEmailList variable we need to check if our emailList variable contains any groups, and if they do, check each group to see if our current active user is a member.

On line 8, we first create an isMemberOfGroup variable and set it to false. Later, if we do find the currently active user is a member of a group in the emailList, this variable will be updated to true.

We can now use the Google Apps Script GroupsApp class to get all the groups the active user is a member of. To do this we call the getGroups() method which will return an array of all the groups as objects. From this, we can use the JavaScript map() method to create an array or each group’s email address with getEmail(). Lines 10-11

Next, we can iterate through each one of these group emails with the JavaScript forEach() method. On each iteration, we can check the emailList to see if it contains one of the active user’s groups with JS includes(). If the includes method finds a match, then we update and return isMemberOfGroup to true.

Checking if the active user is an editor

Finally, we check the emailList for a match of the active user’s email with JS includes(). If they exist, then we update isValid to true. Otherwise, we check to see if the groupEmailList returned true. If it did, we set isValid to true.

Lastly, we return the isValid results back to the doGet() web app initialisation function so it can be used to determine which HTML file to present to the user.

Discussion

The benefit of setting a validator before the HtmlService is initialised is that there is not awkward back and forth between Apps Script and web app front end once the file is loaded. Validation is done as soon as the user opens the web app, making it a pretty secure approach.

This approach also opens itself up to alternate validation methods. Here are a couple of other variation approaches you could consider:

  • A list of emails in a Google Sheet.
  • A separate server with stored emails with Google Apps Script’s UrlFetchApp.
  • From your script PropertiesService. This could be updated or cross-checked against a separate file regularly using a time trigger.

Likewise, you might want to create different web-app displays depending on the user’s task requirement. For example, imagine you have a slightly different web app for editors, commenters and viewers of a document.

So do you think you would use this approach in your own web app, sidebar or dialogue box? How would you modify it or improve on it? I always love to hear how people apply their knowledge to projects and your ideas could inspire the next reader.

If you like the tutorial, please consider a donation to keep the site running or shout me a coffee to keep me going. You can find links to PayPal or cryptocurrencies on my Cointree page here. You can even send me a message, for you know… the warm and fuzzies.

~Yagi 🐐

Leave a Reply