Usecase
I am designing a web app that acts as a frontend around a Google Form. I have set up a service account that will perform API calls to collect form responses, and manage form responses. However, some functionality is missing in the Google Forms API, (e.g. managing form responses), so as a workaround, I would like to do it through Apps Script.
Ideal Authentication Flow
- I have users share the Google Form to the service account email (
service-account@XXX.iam.gserviceaccount.com
) - I can now access their Google Form with the Google Forms API.
- I can also access their Google Form through App Script
Potential Solution #1
In Apps Script, you can share the project with a service account, and even assign it as the owner.
However, I want to execute the Web App in the context of the service account. I am not sure how to do this.
Is it possible to deploy an Apps Script under a service account? It is not possible programmatically as far as I can tell. If this is not possible, is it possible to run certain commands in Apps Script as a service account?
Here is a snippet of what I want to run:
function doPost(e) {
// This line requires access to the Google Form
const form = FormApp.openById(e.parameter['urlId']);
// This action is only possible in Apps Script, not through the Google Forms API
const FormResponse = form.createResponse();
const res = FormResponse.submit();
const link = res.getEditResponseUrl();
}
The end goal is to be able to perform actions through Apps Script without user interaction. This would look like a POST
request to the web app, doing the action I need.
Potential Solution #2
A comment here suggests this is possible:
the access token of the service account can be used for the authorization of Web Apps
So I tried setting the Apps Script to "Execute as User", and passing in the accessToken of my service account in the Bearer
section. This returned a popup, which I cannot get past.
My service account was initialized like this:
const authProvider = new auth.GoogleAuth({
keyFilename: filePath,
scopes: [
'https://www.googleapis.com/auth/forms',
'https://www.googleapis.com/auth/drive',
// ...
],
});
const authClient = await authProvider.getClient();
const url = 'https://script.google.com/macros/s/.../exec'
const accessToken = (await authClient.getAccessToken()).token;
const res = await fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${accessToken}`,
},
});
And the Apps Script only requires these two scopes:
"oauthScopes": [
"https://www.googleapis.com/auth/forms",
"https://www.googleapis.com/auth/drive"
]
Is there some way to grant the Apps Script permission to the Service Account?