skip to Main Content

I want to interact with the Google’s Drive API from a Cloud Function for Firebase. For authentication / authorization, I am currently relying on getClient, which I believe uses the Service Account exposed in the Cloud Function environment:

import { google } from 'googleapis';

// Within the Cloud Function body:
const auth = await google.auth.getClient({
  scopes: [
    'https://www.googleapis.com/auth/drive.file',
  ],
});
const driveAPI = google.drive({ version: 'v3', auth });

// read files, create file etc. using `driveAPI`...

The above approach works, as long as target directories / files list the email address of the service account as an editor.

However, I’d like to interact with the Drive API on behalf of another user (which I control), so that this user becomes (for example) the owner of files being created. How can I achieve this?

2

Answers


  1. Chosen as BEST ANSWER

    I was able to achieve calling the Drive API on behalf of another user thanks to the suggestions made by @DalmTo.

    The first step is to configure domain-wide delegation of authority in Google Workspace for the default AppEngine Service Account.

    Next, the code in my question can be extended to receive a subject with the email of the user to impersonate via the clientOptions:

    import { google } from 'googleapis';
    
    // Within the Cloud Function body:
    const auth = await google.auth.getClient({
      scopes: [
        'https://www.googleapis.com/auth/drive.file',
      ],
      clientOptions: {
        subject: '[email protected]',
      },
      keyFile: './serviceAccountKey.json',
    });
    const driveAPI = google.drive({ version: 'v3', auth });
    
    // read files, create file etc. using `driveAPI`...
    

    Now, the truly odd thing is that this only works when also passing the service account key via the keyFile option in addition. I.e., relying on the key being automatically populated (as it is in Cloud Functions for Firebase) does NOT work when also trying to impersonate a request. There are ongoing discussions of this bug on GitHub, specifically see this comment.


    To make domain-wide delegation work without having to provide the keyFile option (which will likely require you to manage the sensitive key file in some way), another option is to sign a JWT and use it to obtain an Oauth token. The approach is outlined by Google, and I found this SO answer providing a code-example very helpful.


  2. To set the user you want to deligate as in your code just add a subject to the client, with user being the email of the user on your workspace domain.

    const client = await auth.getClient();
    client.subject = user;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search