Home > Software design >  How to really use Google Workspace Admin SDK?
How to really use Google Workspace Admin SDK?

Time:08-06

I trying to implement an Server Node App which access the groups from Google Workspace to make some stuff.

I read some articles, Google doc and read some stack overflow questions but I still don't understand how this works

What I've done so far:

1 - I followed the instructions to give wide domain delegation to my service account

2 - I used service account information to generate google auth credentials

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

const auth = new google.auth.JWT(
    'serviceacount@email',
    null,
    '-----BEGIN PRIVATE KEY-----...',
    'https://www.googleapis.com/auth/admin.directory.groups',
    'myemail'
    );

3 - With these auth, I'm trying to read the groups

async function main() {
    const admin = await google.admin({
        version: 'directory_v1',
        auth,
    });
    console.log(await admin.groups.list({customer: 'XXXXX'}));
}

main();

But I get this error Error: invalid_grant: Invalid email or User ID

I don't understand what I'm getting wrong. Someone could help what can possibly be the cause of this problem? Because I setup everything as Wide Domain Tutorial and still get this error

Could be anything more ?

CodePudding user response:

With the code snippets you have shared I can see you are declaring the service account, but it is not clear whether you are impersonating an Admin of your domain or not. Only using the service account is not enough to make an authorized call. According to Google documentation the user impersonation should be declared like this:

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson.JacksonFactory;
import com.google.api.services.admin.directory.Directory;
import com.google.api.services.admin.directory.DirectoryScopes;
...

/** Email of the Service Account */
private static final String SERVICE_ACCOUNT_EMAIL = "<some-id>@developer.gserviceaccount.com";

/** Path to the Service Account's Private Key file */
private static final String SERVICE_ACCOUNT_PKCS12_FILE_PATH = "/path/to/<public_key_fingerprint>-privatekey.p12";

/**
 * Build and returns a Directory service object authorized with the service accounts
 * that act on behalf of the given user.
 *
 * @param userEmail The email of the user. Needs permissions to access the Admin APIs.
 * @return Directory service object that is ready to make requests.
 */
public static Directory getDirectoryService(String userEmail) throws GeneralSecurityException,
    IOException, URISyntaxException {
  HttpTransport httpTransport = new NetHttpTransport();
  JacksonFactory jsonFactory = new JacksonFactory();
  GoogleCredential credential = new GoogleCredential.Builder()
      .setTransport(httpTransport)
      .setJsonFactory(jsonFactory)
      .setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
      .setServiceAccountScopes(DirectoryScopes.ADMIN_DIRECTORY_USERS)
      .setServiceAccountUser(userEmail)
      .setServiceAccountPrivateKeyFromP12File(
          new java.io.File(SERVICE_ACCOUNT_PKCS12_FILE_PATH))
      .build();
  Directory service = new Directory.Builder(httpTransport, jsonFactory, null)
      .setHttpRequestInitializer(credential).build();
  return service;
} 

References:

-Domain-wide Delegation /Impersonation Example

CodePudding user response:

I added the key id in the auth builder and it worked

I dind't understand how the constructor does not give any other error like "required parameter" but now it is working

The credentials should be builded like this:

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

const auth = new google.auth.JWT(
    'serviceacount@email',
    null,
    '-----BEGIN PRIVATE KEY-----...',
    'https://www.googleapis.com/auth/admin.directory.groups',
    'myemail',
    'keyid'
    );

This key id comes in the same file where you reach the PRIVATE KEY

But I would appreciate if someone has an accurate doc for using this googleapis =)

  • Related