2

I am using Gmail API and I am trying to fetch emails from all users under company. But when I run code such as:

function runAPI(auth) {
  var gmail = google.gmail('v1');
  gmail.users.threads.list({auth: auth, userId: '108800016305523828361'},'',function(err, response){
    if (err) {
      console.log("The API returned an error: " + err);
      return;
    }
    var threads = response.threads;
    console.log(threads);
  })
}

I get error:

The API returned an error: Error: Delegation denied for xxxx@xxxxx.com

In admin console I did this:

enter image description here

As client name I used id from the client_secret.json file. And for scope, I gave it all permissions.

How do I properly setup domain wide delegation for Gmail API ?

Kunok
  • 8,089
  • 8
  • 48
  • 89

2 Answers2

1

The setup is fine, however in your code you're doing it wrong.

This code:

gmail.users.threads.list({auth: auth, userId: '108800016305523828361'},'',function(err, response)

specifically.

userId should be "me" however before you can call the Gmail API you need to use the service account "JWT flow" in your code to retrieve an oauth2 credential for the Gmail user you want to access as described in the Preparing to make an authorized API call service account domain-wide delegation doc.

Specifically this uses your service account's private key to request to get a credential for the user you desire (set the user's email in your domain that you want to access in the setServiceAccountUser(user@example.com) function in the request). Then you can use that GoogleCredential in your call to the Gmail API.

Eric D
  • 6,901
  • 1
  • 15
  • 26
  • Is there any documentation related to this? – Kunok Sep 02 '16 at 17:14
  • 1
    Only the `Preparing to make an authorized API call` link I provided above. – Eric D Sep 02 '16 at 17:16
  • Method `setServiceAccountUser(user@example.com)` not supported for Node.js ? – Kunok Sep 08 '16 at 14:02
  • 1
    Updated answer to make it clear how to get a credential for any Gmail user in your domain. Then you can pass that to a gmail API call (with userId="me" to use the user from the credential) and act as THAT user. Hope that makes sense. – Eric D Sep 08 '16 at 19:35
  • I can't find node.js `setServiceAccountUser` method. There are only Java and Python examples. And I read somewhere that node.js is in beta and that is why does not yet support this class. – Kunok Sep 08 '16 at 19:37
  • Sometimes method is named slightly differently. Try looking in source or searching for it (e.g. "node.js google api domain delegation set user"). If that doesn't work try asking about it on the node.js tag ("google-api-nodejs-client") or perhaps one of them will answer here... – Eric D Sep 08 '16 at 19:46
  • I will search for it in the source. I did tag question as node.js, I hope somebody notices – Kunok Sep 08 '16 at 19:48
  • It seems that JWT for node.js is not a proper way to do this as said in the comments (also by Google developer) https://github.com/google/google-api-nodejs-client/issues/347 `Ah, right. You cannot authorize Gmail API requests with JWT, you must use OAuth 2.0 because it needs to be auth'd to a specific user. Or else you'd be able to do some really shady things like send messages impersonating someone else.` – Kunok Sep 09 '16 at 14:44
  • 1
    I think that person is confused. As documented, you use JWT as your service account to request an oauth2 token, which token can be used by Gmail API in the standard way for the requested user (for up to an hour I believe). – Eric D Sep 09 '16 at 16:20
0

For the question How do I properly setup domain wide delegation for Gmail API?

I think this documentation from Google can help you with this, just follow this steps to delegate domain-wide authority.

  1. Go to your Google Apps domain’s Admin console.

  2. Select Security from the list of controls. If you don't see Security listed, select More controls from the gray bar at the bottom of the page, then select Security from the list of controls. If you can't see the controls, make sure you're signed in as an administrator for the domain.

  3. Select Show more and then Advanced settings from the list of options.

  4. Select Manage API client access in the Authentication section.

  5. In the Client Name field enter the service account's Client ID. You can find your service account's client ID in the Service accounts page.

  6. In the One or More API Scopes field enter the list of scopes that your application should be granted access to. For example, if your application needs domain-wide access to the Google Drive API and the Google Calendar API, enter: https://www.googleapis.com/auth/drive, https://www.googleapis.com/auth/calendar.

    In your case, use this scope for Gmail API.

  7. Click Authorize.

For more information about the error 403 or Delegation denied for <user email>,check this related SO question:

Community
  • 1
  • 1
KENdi
  • 7,576
  • 2
  • 16
  • 31
  • So basically, are you suggesting that I am using wrong client id? – Kunok Aug 29 '16 at 09:27
  • 1
    just double check that process if you do it properly. I also suggest you to check the linked SO question, because it might also give you an idea about that problem :) – KENdi Aug 29 '16 at 09:29
  • After creating service account for the project and using the client id from it in admin console, I still get same error. `Delegation denied for k****uno@ul*****vel.com`. I checked QA you linked but these answers didn't fit my case. Since error says it denies my email rather than my app, is it possible to setup that my email can be authorized to access all data inside our company google apps? – Kunok Aug 30 '16 at 15:09