Search code examples
google-apigoogle-admin-sdkgoogle-workspace

Accessing Google API from aws lambda : Invalid OAuth scope


I am still struggling with Google's terminology of apis and services but my goal is to have automated functions via aws lambda which act on a G Suite Account (domain?) or more specific on users of this domain.

For now I just want to list all users of that domain. I run this code locally for testing.

What I have done:

This is the implementation:

const { google } = require("googleapis");

const auth = new google.auth.GoogleAuth({
keyFile: "credentials.json",
scopes:
  "https://www.googleapis.com/auth/drive.readonly,https://www.googleapis.com/admin/directory/v1, https://www.googleapis.com/auth/admin.directory.group, https://www.googleapis.com/auth/admin.directory.user",
 });

const service = google.admin({ version: "directory_v1", auth });
service.users.list(
{
  domain: "my.domain.com",
  maxResults: 10,
  orderBy: "email",
},
(err, res) => {
  if (err) return console.error("The API returned an error:", err.message);

  const users = res.data.users;
  if (users.length) {
    console.log("Users:");
    users.forEach((user) => {
      console.log(`${user.primaryEmail} (${user.name.fullName})`);
    });
  } else {
    console.log("No users found.");
  }
}
);

I am not sure why I have to add the scopes in the GoogleAuth object but I took this from the google documentation.

When I run this I get the following error:

The API returned an error: invalid_scope: Invalid OAuth scope or ID token audience provided.


Solution

    • The Directory API can only be used by admins
    • A Service account is not an admin
    • If the service account shall act on behalf on the admin, you need to
      • enable G Suite Domain-wide Delegation (as you already did)
      • impersonate the service account as the admin by setting the user to be impersonated

    In general, when you are using a service account you need to build the authentication flow, as explained in the documentation, that is you need to create JSON Web Token (JWT) specifying the user to impersonate.

    A sample code snippet for Javascript:

            const jwtClient = new google.auth.JWT(
                privatekey.client_email,
                null,
                privatekey.private_key,
                scopes,
                user // User who will be impersonated (needs to be an admin)
            );
    
            await jwtClient.authorize();
    
            return jwtClient;