I have a script using Google's OAuth2 library, which recently started to fail with the error
You have exceeded the property storage quota. Please remove some properties and try again.
I inspected the properties and did not find any unexpected differences from my original configuration. The full stringified text length of my properties is around 5000 characters, which is well below the 500kB/property store quota and the longest individual property ~2500 characters (below the 9kB/value quota).
I've discovered that this error only occurs when I use Google's OAuth2 library with a service account. However, if I include the library dist directly in my project, the error disappears.
Why is there a difference in how the properties service behaves between the library and the local copy if they appear to be the same versions?
(In other scripts where I use the OAuth2 library with a standard authorization code grant flow, I have no issues.)
This script will replicate the error, but requires that you create a service account and set the correct script properties as defined in getAdminDirectory_(). (Using Rhino interpreter.)
/**
* Get a GSuite User.
*/
function getUser() {
var email = "name@exampledomain.com";
var user = AdminDirectory_getUser_(email);
Logger.log(user);
}
/**
* Gets a user from the GSuite organization by their email address.
* @returns {User} - https://developers.google.com/admin-sdk/directory/v1/reference/users#resource
*/
function AdminDirectory_getUser_(email) {
var service = getAdminDirectory_();
if (service.hasAccess()) {
var url = "https://www.googleapis.com/admin/directory/v1/users/" + email;
var options = {
method: "get",
headers: {
Authorization: "Bearer " + service.getAccessToken()
}
};
var response = UrlFetchApp.fetch(url, options);
var result = JSON.parse(response.getContentText());
return result;
} else {
throw service.getLastError();
}
}
/**
* Configures the service.
*/
function getAdminDirectory_() {
// Get service account from properties
var scriptProperties = PropertiesService.getScriptProperties();
var serviceAccount = JSON.parse(scriptProperties.getProperty("service_account"));
// Email address of the user to impersonate.
var user_email = scriptProperties.getProperty("service_account_user");
return OAuth2.createService("AdminDirectory:" + user_email)
// Set the endpoint URL.
.setTokenUrl("https://oauth2.googleapis.com/token")
// Set the private key and issuer.
.setPrivateKey(serviceAccount.private_key)
.setIssuer(serviceAccount.client_email)
// Set the name of the user to impersonate. This will only work for
// Google Apps for Work/EDU accounts whose admin has setup domain-wide
// delegation:
// https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority
.setSubject(user_email)
// Set the property store where authorized tokens should be persisted.
.setPropertyStore(scriptProperties)
// Set the scope. This must match one of the scopes configured during the
// setup of domain-wide delegation.
.setScope("https://www.googleapis.com/auth/admin.directory.user");
}