1

I am trying to access the google reseller api using the nodejs library, which has very shi..., I mean spotty documentation. I tried following the example here, but I fail at step 3 with this error:

  code: 403,
  errors: [
    {
      domain: 'global',
      reason: 'insufficientPermissions',
      message: 'Authenticated user is not authorized to perform this action.'
    }
  ]

My configuration looks like this:

    const OAUTH2_SCOPES = [
      "https://www.googleapis.com/auth/admin.directory.user",
      "https://www.googleapis.com/auth/apps.order",
      "https://www.googleapis.com/auth/siteverification",
      "https://www.googleapis.com/auth/cloud-platform",
    ];

   const authJWT = new google.auth.JWT({
      keyFile: JSON_PRIVATE_KEY_FILE,
      scopes: OAUTH2_SCOPES,
      subject: RESELLER_ADMIN_USER,
      email: "gsuite-reseller@some-cool-name-because-why-not.iam.gserviceaccount.com",
    });

Using basic google fu, I found this thread, which suggested that my problem has to do with impersonation. So I exchanged the email in the subject property, with my account email, which has the owner rights specified. I also gave the service account owner rights, because at that point I am pretty clueless. This unfortunately only changed the error message to:

status: 401,
statusText: 'Unauthorized'

Does anybody have an idea what goes wrong? The 401 suggests that there are credentials missing. Would I have to also specify my private emails credentials in addition to the ones of the service account? If yes, then where? I did not find any property on the google.auth.JWT.options object which sounded promising.

Gh05d
  • 7,923
  • 7
  • 33
  • 64
  • 1
    Did you give the service account the necessary scopes in the Admin console->Security > API Controls as explaine [here](https://developers.google.com/identity/protocols/oauth2/service-account#delegatingauthority)? Did you enbale domain-wide delegation for the service account you created? Are the scopes in your code sufficient for the request you are trying to implement? Would be helpful to see your code! – ziganotschka Jul 13 '20 at 14:24
  • I posted the scopes here in the variable `OAUTH2_SCOPES`. I have added the domain wide scopes. There is not much more to my code right now. I only try to call the api via `google.reseller({ version: "v1", auth: authJWT });`. – Gh05d Jul 13 '20 at 14:35
  • 1
    If you want to use a service account that impersonates a user, you HAVE TO enable domain-wide delegation. As for the scopes, make sure you authorize them in the Admin console in addition to pasting them into the code. Why do you want to use the service account at all? – ziganotschka Jul 13 '20 at 14:41
  • I have not activated Domain-wide Delegation as I don't want every created user to have to go through manual authorization. – Gh05d Jul 13 '20 at 14:42
  • I checked and the scopes are in the admin console. I want to use the service account as we want to resell gsuite using our backend and so the requests will be server to server. I thought that this was the exact use case. – Gh05d Jul 13 '20 at 14:43

1 Answers1

2

Why do you need domain-wide delegation?

  • When you use a service account and enable domain-wide delegation, it means that you allow the service account to impesonate the user and act on his behalf
  • If you use a service account without impersonation - the service account can only perform operations to which it is autherized - e.g. it can access files on your Drive or access your Calendar - but only if you explicitly shared those with the service account!
  • To perform requests for which the service account is not authorized, you need to make the service account impersonate a domain user that has the necessary authorization - that is you need to impersonate the user
  • However to impersonate the user, you need to explicitly give the service account the permission to act on behalf of a user - this is called domain-wide delegation
  • Enabling domain-wide delegation will not make "every created user to have to go through manual authorization" or affect any other non-service account related behavior
  • the only thing domain-wide delegation does is to allow a service account to represent a user
  • Without enabling domain-wide delegation the impersonaiton of a user will not be authorized and setting a subject will throw you an error

References:

ziganotschka
  • 25,866
  • 2
  • 16
  • 33
  • This looks good for production. But is there also a way to do this in a development environment? Because right now, the script is running locally on my machine and not on a server running under the authorized domain. – Gh05d Jul 13 '20 at 15:36
  • 1
    I don't see why you cannot test the code in development environment, as long as you downloaded a copy of theJSON_PRIVATE_KEY_FILE and stored it at the path that you specified in your code. – ziganotschka Jul 13 '20 at 15:48
  • Well, I tried it with the authorized domain and domain wide delegation, but I still get a 401 error. I checked the keyfile and the id is correct. The entered email also has owner privileges. – Gh05d Jul 13 '20 at 15:53
  • 1
    Sorry for asking again, but did you provide the necessary scopes [here](https://drive.google.com/file/d/1ld4gC3v8S1AEQeEmDiRhwduCzaWanYRV/view?usp=sharing)? And also enable the API in the cloud console? Google says about the [401 error](https://developers.google.com/calendar/v3/errors#401_invalid_credentials): If you are seeing this for a service account, check that you have successfully completed all the steps in the service account page. Please make sure foolowed all [those](https://developers.google.com/identity/protocols/oauth2/service-account) steps correctly. – ziganotschka Jul 13 '20 at 16:03
  • The more you ask, the better :-) I activated all the neccessary apis via https://console.developers.google.com/apis and there is also the service account listed as having access. I followed all the steps in that document, except assigning a user to the service account. Couldn't find it using edit, so maybe I have to create a new Service Account. – Gh05d Jul 14 '20 at 09:26
  • 1
    Seems like creating the new account and adding my user to it did the trick. Thanks again for your help. You are awesome :-) – Gh05d Jul 14 '20 at 09:32