1

So a bit of background on the issue. I have a local application that is using both the google calendar api and the google admin sdk for managing both user calendars and resource calendars.

Here are the steps i've taken in the setup

  • Created the service account and given it domain wide access
  • Added and enabled both the Google Calendar Api and the Admin SDK in the developer console
  • Added the client id and scopes to the Manage API client access section of the Gsuit admin console

I build the credentials here (for testing purposes i have them stored locally in a json file)

val JSON_FACTORY: JsonFactory = JacksonFactory.getDefaultInstance()
var HTTP_TRANSPORT: HttpTransport = GoogleNetHttpTransport.newTrustedTransport()
var SCOPES = DirectoryScopes.all()

val cred = new GoogleCredential.Builder()
  .setTransport(HTTP_TRANSPORT)
  .setJsonFactory(JSON_FACTORY)
  .setServiceAccountId(CLIENTID)
  .setServiceAccountScopes(SCOPES)
  .setServiceAccountUser(USER)
  .setServiceAccountPrivateKey(serviceAccountCredJson.getServiceAccountPrivateKey)
  .setServiceAccountPrivateKeyId(serviceAccountCredJson.getServiceAccountPrivateKeyId)
  .build()

cred.refreshToken()

And the first issue i run into is if I remove the line

.setServiceAccountUser(USER)

Then cred.refreshToken() == true however I get this error when i try to get a list of the resources for my_customer

404 Not Found
{
  "code" : 404,
  "errors" : [ {
    "domain" : "global",
    "message" : "Domain not found.",
    "reason" : "notFound"
  } ],
  "message" : "Domain not found."
}
com.google.api.client.googleapis.json.GoogleJsonResponseException: 404 Not Found

If I impersonate a user I get this error which is caused by cred.refreshToken()

401 Unauthorized
com.google.api.client.auth.oauth2.TokenResponseException: 401 Unauthorized
at com.google.api.client.auth.oauth2.TokenResponseException.from(TokenResponseException.java:105)
at com.google.api.client.auth.oauth2.TokenRequest.executeUnparsed(TokenRequest.java:287)
at com.google.api.client.auth.oauth2.TokenRequest.execute(TokenRequest.java:307)
at com.google.api.client.googleapis.auth.oauth2.GoogleCredential.executeRefreshToken(GoogleCredential.java:384)
at com.google.api.client.auth.oauth2.Credential.refreshToken(Credential.java:489)
at com.iofficeconnect.reservation.google.GoogleDirectoryClient$.getCredsAsUser(GoogleDirectoryClient.scala:96)

I understand that in order to operate the Admin SDK you must be impersonating a user with admin credentials however even when i do this i get the same result.


The client connecting to the Admin SDK is built in these lines

def getClientAsUser(user:String):Directory={
    new Directory.Builder(HTTP_TRANSPORT, JSON_FACTORY, testCredJsonAsTestUser(user))
      .setApplicationName(APPLICATION_NAME)
      .build()
}

The final call to the Admin SDK is executed in these lines

var client = getClientAsUser(admin@domain.com)
var calendarList = client.resources().calendars().list("my_customer").execute()

Any help would be greatly appreciated

1 Answers1

0

Try impersonating an admin that has access to Directory API. According to the document:

Only users with access to the Admin APIs can access the Admin SDK Directory API, therefore your service account needs to impersonate one of those users to access the Admin SDK Directory API.

Also, check these related SO post - admin users get list of google calendar resources and TokenResponseException: 401 Unauthorized Exception when trying to access Admin SDK Google API. The first related SO post stated that accessing Calendar Resource requires a Super Admin and the second post stated that TokenResponseException: 401 Unauthorized occurs when having an invalid client ID, client secret or scopes. But it could also be due to refresh token overuse.

Hope this helps.

Community
  • 1
  • 1
Mr.Rebot
  • 6,703
  • 2
  • 16
  • 91