0

I am using a service account and Google Calendar v3 API to invite domain internal guests to events. I am getting a Encountered 403 Forbidden with reason "quotaExceeded" error. But, from the console, no API limit is reached and the error disappears when I stop inviting guests.

The Google Cloud Platform project, which holds the service account, is well related to my domain according to settings available in Google Cloud Platform console, in the section: API & Services > Domain verification.

Besides, all my guests have G Suite accounts, related to my domain, and I have enabled G Suite domain-wide delegation in my service account's settings.

I thought this would be enough to prevent the API error due to guests invites. I am aware of the API limits listed here : https://support.google.com/a/answer/2905486?hl=en which I think should be fine, namely the one mentioning limit for inviting external guests, which is not my case.

But it appears I missed something in the settings, and my internal guests are still considered external, would you have any recommendation about how to proceed to fix this? What else should I check?

Here is the code I use to create events with the service account, in python:

SERVICE_ACCOUNT_FILE = 'path/to/service_account.json'
SCOPES = [
    'https://www.googleapis.com/auth/calendar.events',
    'https://www.googleapis.com/auth/spreadsheets'
]
credentials = service_account.Credentials.from_service_account_file(
        SERVICE_ACCOUNT_FILE,
        scopes=SCOPES
    )
service = discovery.build('calendar', 'v3', credentials=credentials)
service.events().insert(
    calendarId='my_calendar_id',
    body=event_body,
    sendUpdates="none").execute()
Adrien-A
  • 1
  • 2
  • whats the full error message? – Linda Lawton - DaImTo Feb 13 '20 at 09:39
  • The error message I found in my logs is : `Encountered 403 Forbidden with reason "quotaExceeded"` and that's it, not exactly what I mentioned in the description, I'm going to update it. – Adrien-A Feb 13 '20 at 10:55
  • It doesnt say exactly which quota you have hit? if you wait a few minutes does it work again or is this not working for the rest of the day? – Linda Lawton - DaImTo Feb 13 '20 at 11:07
  • Unfortunately I have nothing more detailed as an error :/ The error lasted for a bit less than one hour, from the first failure, until I removed the "attendees" parameter of the event insert request. – Adrien-A Feb 13 '20 at 11:16
  • Could you go to console.cloud.google.com -> Select the project associated with the service account -> APIs & Services -> Dashboard -> Select Google Calendar API from the list -> Check the traffic chart. If you drag-select a specific time area in the chart it'll zoom in, you can zoom in as close as 15 seconds interval. So you'll be able to see if you're hitting the 500 requests per 100 seconds default quota, which you can also edit to increase it. – Andres Duarte Feb 13 '20 at 15:13
  • If case you're not hitting the quota, could please impersonate a specific user and then make the requests with this credential? To check if this solves the issue. – Andres Duarte Feb 13 '20 at 15:13
  • Hi @AndresDuarte thanks, looking at the chart with a 15 seconds interval, there are no more than 30 requests per 100 seconds. And errors did not occur during the highest spike of requests per second. The error "quotaExceed" seems to be related to several limits, but the error message does not specify which one... My guess would be this one : "Send too many invitations to external guests" as the error is fixed when I remove attendees when inserting events. It's hardly reproducible as it requires high volumes, but I've set the attendees again to see what happens, I'll keep you updated! – Adrien-A Feb 18 '20 at 08:46
  • Do you have a business or enterprise G Suite account? – Andres Duarte Feb 19 '20 at 09:42
  • Yes, I have access to an enterprise G Suite account. I checked the advanced settings, and the service account client ID is well authorised with the following scope : https://www.googleapis.com/auth/calendar – Adrien-A Feb 19 '20 at 11:49
  • I suggest you to open a bug with G Suite support https://support.google.com/a/answer/1047213 – Andres Duarte Feb 20 '20 at 13:55

2 Answers2

0

403 Forbidden Usage Limit Exceeded

Is normally flood protection. When you make a request against a Google API a user can max make X number of requests per 100 seconds. A user is denoted by the ip address where the request is coming from. As you are using a service account its the server that your code is running on. You need to slow your code down and if you do get this error simply wait a few seconds and then make the same request again.

If you are preforming these actions on behalf of another user then you could try to add the QuotaUser parameter to all of your requests denoting that this is in fact a different user. This can help sometimes but its not fool proof I tried to send a random number to this all the time and eventually google caught on and i started getting that error.

Linda Lawton - DaImTo
  • 106,405
  • 32
  • 180
  • 449
  • Thanks, from the console quotas interface I can see that request per user per 100 seconds only spiked at 3.9 when the errors occured, it's a 2 hours average so it might hide a more local spike... I'm going to check – Adrien-A Feb 13 '20 at 11:01
  • Take the usage graph with a grain of salt. If you make a request and your request is run on a server with no one else on it. You can easily kick off 100 requests in 10 seconds. If they say you are hitting the flood quota your hitting it. – Linda Lawton - DaImTo Feb 13 '20 at 11:06
0

Well, it seems I was missing the user delegation part when using the service account. According to another thread, acting on behalf of a user is required when using domain wide delegation : Is it possible to call APIs from service account without acting on behalf of a user in domain-wide delegation?

I have updated my code with the following lines :

credentials = service_account.Credentials.from_service_account_file(
    SERVICE_ACCOUNT_FILE,
    scopes=CALENDAR_SCOPES
)
credentials = credentials.with_subject(DOMAIN_USER_EMAIL)
service = discovery.build('calendar', 'v3', credentials=credentials)

The limit preventing from inserting events with attendees is no longer hit. The service account, without user delegation, was not recognized as internal to my domain, despite domain verification and domain-wide delegation.

Adrien-A
  • 1
  • 2