0

PROBLEM

Unautorized 401 error when posting a request to Google App Script webapp, from my Google Cloud Console function with a service account.

OVERVIEW

Google App Script Webapp deployed with

  • Execute as: "user acessing the webapp"
  • Who has access: "anyone with a google account" (The option "anyone" is only available if Execute as = myself)

Let's assume a dummy doPost(e) function that returns "hello world!"

function doPost(e) {
  return ContentService.createTextOutput("Hello world");
}

Google Cloud Console - Function

const axios = require('axios');
const { GoogleAuth } = require('google-auth-library');

exports.calendarWebhook = async (req, res) => {
  try {
    const webAppUrl = process.env.WEB_APP_URL; // Make sure this env var is set correctly
    const auth = new GoogleAuth({
      credentials: JSON.parse(process.env.SERVICE_ACCOUNT_KEY), // Ensure this is set correctly
      scopes: ['https://www.googleapis.com/auth/script.projects'],
    });
    const client = await auth.getClient();
    const accessToken = await client.getAccessToken();

    const requestBody = {
      channelId: req.header('X-Goog-Channel-ID'),
      resourceId: req.header('X-Goog-Resource-ID'),
      resourceState: req.header('X-Goog-Resource-State'),
      userToken: req.header('X-Goog-Channel-Token'),
      secret: process.env.WEB_APP_SECRET,
    };

    const response = await axios.post(webAppUrl, requestBody, {
      headers: {
        Authorization: `Bearer ${accessToken.token}`,
        'Content-Type': 'application/json',
      },
    });

    console.log('Response from web app:', response.data);
    res.status(200).send('Notification processed');

  } catch (error) {
    console.error('Error in Cloud Function:', error);
    if (error.response) {
      console.error('Web app response:', error.response.data);
      console.error('Web app status:', error.response.status);
    }
    res.status(500).send('Internal Server Error');
  }
};

Logs:

  • Error in Cloud Function: AxiosError: Request failed with status code 401 at settle
  • Web app response:
<HTML> <HEAD> <TITLE>Unauthorized</TITLE> </HEAD> <BODY BGCOLOR="#FFFFFF" TEXT="#000000"> <!-- GSE Default Error --> <H1>Unauthorized</H1> <H2>Error 401</H2> </BODY> </HTML>

If I deploy my webapp with (Execute as: Me ; Who has access: anyone) the post request works (without any token nor anything). But I can't deploy the webapp like this.

How can I autorize the Google Cloud console to post to my webapp?!?!?

Thanks community


EDIT

- Outcome: improvement but not there yet!

- Summary: calling webapp through Postman post request: working with a token of a logged-in user, but still not working with the token of the service account.

TESTS

1. Service account adjustment

  • Added scopes (..../auth/drive) when requesting token
  • Shared the Google App Script (edit rights)
  • Result: Error 500 (see picture below)

2. Test with Logged-in user token

  • User has edit access to the script
  • Got the token access for the logged in user
  • Called my webapp via Postman
  • Result: SUCCESS!! (<< This wasn't working before, seems that adding the "...auth/drive" scope fixed it)

3. Service Account full scope request

  • Added all the scope required in mywebapp to the service account as well (not just the "...auth/drive") when requesting the token.
  • Result: Error 500 (see picture below)

4. Webapp deployed with (Execute as Me + who has access = anyone). Tested with service account:

  • Result: SUCCESS!! (but I can't deploy the webapp like this, as initially stated)

HYPOTHESIS:

  • #2 & #4 => indicates there are no error in the Cloud function nor the doPost().

  • #2 & #3 => as a hypothesis... a service account is NOT considered "Anyone with a google account" (the "who has access" config when deploying the webapp), and so, cannot call the webapp. This still sounds weird to me... I tried to compare both access token via "https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=XXX". Here's what I got... not sure what's making them behave differently. ANY TIPS?!?!?!

Service Account

{
issued_to: "some long number X",
audience: "same long number X",
user_id: "same long number X",
scope: //same as logged in user, except it's missing "https://www.google.com/calendar/feeds" which i don't thing makes any impact for calling the webapp....
expires_in: 3395,
email: "[email protected]",
verified_email: true,
access_type: "online"
}

Logged in user

{
issued_to: "KeyXYZ.apps.googleusercontent.com",
audience: "KeyXYZ.apps.googleusercontent.com",
user_id: "some long number Y",
scope: same as Service account, except it includes "https://www.google.com/calendar/feeds"
expires_in: 3575,
email: "[email protected]",
verified_email: true,
access_type: "offline"
}

500 response Error 500 response

6
  • can you try changing your scope scopes = ["https://www.googleapis.com/auth/drive"] Commented Feb 13 at 21:42
  • 2
    Read Taking advantage of Web Apps with Google Apps Script by Tanaike. It covers everything you need to know. Commented Feb 13 at 22:23
  • Have you found the solution from the article that @TheAddonDepot provided? Commented Feb 14 at 18:24
  • Still can't solve it! x_X. Post updated (see EDIT section) with 4 tests I ran; I can now call webapp with user token, but still not with service account token :(. Any tip here??? super thanks for the help people, appreciate it. cc: @TheAddonDepot? (+JatsPGG/PatrickdC) Commented Feb 15 at 18:43
  • 1
    After additional research, I found out that the scenario I’m trying to build won’t work… medium.com/google-cloud/… Commented Feb 20 at 12:21

1 Answer 1

1

After additional research, I concluded that the scenario I’m trying to build won’t work. Resource: https://medium.com/google-cloud/executing-google-apps-script-with-service-account-3752f4e3df8c

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

Comments

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.