Home > Back-end >  Authorizing a non admin user to run Admin SDK in Google Apps Script
Authorizing a non admin user to run Admin SDK in Google Apps Script

Time:10-28

I'd like to allow a non admin user in our domain to be able to use a Google Sheet which is running code to:

  • List some groups in our organisation
  • Delete/Add users

This requires admin rights, so the following code will not run in a non-admin account... How is it possibile to authorise the non admin user to run admin code?

var RatatoskSheet = SpreadsheetApp.getActiveSpreadsheet();

// -- ADD USER TO GROUP -- Set trigger to onedit -- //
function addUsertoGroup(e) {

   var sheet = e.source.getActiveSheet();
   if (sheet.getName() === 'AddUser') { //Hinders edits on other sheets

      var userData = SpreadsheetApp.getActive().getSheetByName('AddUser');
      var userEmail = userData.getRange(2, 1).getValue(); //Gets data from AddUser.A2
      var groupId = userData.getRange(2, 2).getValue(); //Gets data from cell B2

      var newMember = {
         email: userEmail,
         role: "MEMBER"
      };


      AdminDirectory.Members.insert(newMember, groupId); // Adds new member to a Google group
      var groupData = SpreadsheetApp.getActive().getSheetByName('GroupAddress');
      var groupTwo = [userEmail, groupId]
      groupData.appendRow(groupTwo); //Add member and group to GroupAddress
      var header = ['UserEmail', 'GroupID'];
      userData.clear(); //Reset AddUser (Delete all)
      userData.appendRow(header).setFrozenRows(1);



   }
}

// -- REMOVE USER FROM GROUP -- Set trigger of this function to onedit -- //
function deleteGroupMember(e) {

   var sheet = e.source.getActiveSheet();
   if (sheet.getName() === 'RemoveUser') { //Hinders edits on other sheets

      var RemoveUserData = SpreadsheetApp.getActive().getSheetByName('RemoveUser');
      var groupData = SpreadsheetApp.getActive().getSheetByName('GroupAddress');

      var userEmail = RemoveUserData.getRange(2, 1).getValue(); //Gets data from RemoveUser.A2
      var groupId = RemoveUserData.getRange(2, 2).getValue(); //Gets data from  RemoveUser.B2

      AdminDirectory.Members.remove(groupId, userEmail); //Removes member from a Google group

      var removeDataValues = RemoveUserData.getDataRange().getValues();
      var groupDataValues = groupData.getDataRange().getValues();
      var resultArray = [];
      for (var n in groupDataValues) { //
         var keep = true
         for (var p in removeDataValues) {
            if (groupDataValues[n][0] == removeDataValues[p][0] && groupDataValues[n][1] == removeDataValues[p][1]) {
               keep = false;
               break;
            }
         }
         if (keep) {
            resultArray.push(groupDataValues[n])
         };
      }


      var start = 2; //Starts from Row 2          //
      var killTheRows = groupData.getLastRow() - start   1; //                           // These lines deletes all rows in GroupAddress
      groupData.deleteRows(start, killTheRows); //Delete all rows with values//

      groupData.getRange(2, 1, resultArray.length, resultArray[0].length).setValues(resultArray); //Repopulate the rows in GroupAddress

      var header = ['UserEmail', 'GroupID'];
      RemoveUserData.clear();
      RemoveUserData.appendRow(header).setFrozenRows(1);



   }
}

// -- LISTS ALL GROUPS AND USERS WITHIN THEM -- Set this as a timed trigger to error correct once a day -- //
function listAllGroups() {
   var grouprows = [];
   var pageToken;

   var page;
   do {
      page = AdminDirectory.Groups.list({
         domain: 'THEDOMAIN',
         maxResults: 200,
         pageToken: pageToken
      });
      var groups = page.groups;
      if (groups) {
         for (var i = 0; i < groups.length; i  ) {
            var group = groups[i];
            if (group.email.substring(0, 5) === "staff") {
               grouprows.push(group.email);
            }
         }
      }
      pageToken = page.nextPageToken;
   } while (pageToken);

   var rows = [];
   var pageToken, page2;
   for (var j = 0; j < grouprows.length; j  ) {
      do {
         page2 = AdminDirectory.Members.list(grouprows[j], {
            domainName: 'YOURDOMAIN',
            maxResults: 500,
            pageToken: pageToken,
         });
         var members = page2.members;
         if (members) {
            for (var i = 0; i < members.length; i  ) {
               var member = members[i];
               var row = [member.email, grouprows[j]];
               rows.push(row);
            }
         }
         pageToken = page2.nextPageToken;
      } while (pageToken);
      if (rows.length > 1) {
         var groupData = RatatoskSheet.getSheetByName("GroupAddress");
         var header = ['UserEmail', 'GroupID'];
         groupData.clear();
         groupData.appendRow(header).setFrozenRows(1);
         groupData.getRange(2, 1, rows.length, header.length).setValues(rows);

      }

   }
   groupData.deleteRow(2); //NB! Removes first group([email protected]) Make this whole line a comment if unsure. 



} 

CodePudding user response:

A way to achieve this is by creating a service account and using domain wide delegation of authority.

After that, since you want to continue on using Apps Script, you will have to get the access token for this service account and make the request using UrlFetchApp since you cannot pass an access token while making a request using Admin SDK Directory advanced service.

Therefore, the requests will end up looking something similar to:

var options = {
    method: "GET",
    contentType: "application/json",
    muteHttpExceptions: true,
};

var response = UrlFetchApp.fetch('https://admin.googleapis.com/admin/directory/v1/groups/{groupKey}/members', {
    headers: {
      Authorization: 'Bearer '   token
    }
  });

However, this approach might depend on the restrictions you have set in place for your account.

Another option is to deploy your script as a web app

For deploying a web app, the script should contain a doGet(e) or a doPost(e) and return a HTML service HtmlOutput object or a Content service TextOutput object.

After doing this, you should deploy the web app with the following settings:

  • Execute as: Me

  • Who has access: Anyone within domain

Reference

  • Related