This is my team's first foray into implementing functionality with Google Cloud and GSuite. After searching issues and the community I have not yet found what seems to be the proper path forward, or at least have not managed to get the desired functionality.
Background
We have a device/display that shows calendar and event information for a given/specific GSuite Room resource.
As part of displaying information regarding a specific event, we want to display attendee/invitee names.
Implementation
We are successfully calling the Calendar API using a service account. But, when the event information comes back, the attendee information only includes the attendee e-mail address.
The implementation is using the .NET Client libraries for Google.
We found a post directing that we then need to make follow up calls to get more attendee information to the People API.
When querying the People API utilizing the same service account we receive the error Must be a G Suite domain user
.
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.6.1",
"title": "An error occured while processing your request.",
"status": 500,
"detail": "Google.Apis.Requests.RequestError\nMust be a G Suite domain user. [400]\nErrors [\n\tMessage[Must be a G Suite domain user.] Location[ - ] Reason[failedPrecondition] Domain[global]\n]\n",
"traceId": "|6007b977-42e9ca34c40a6cb0."
}
Below is the current hacked together code simply trying to make a successful query against the People Service API
public async Task<IList<Person>> GetAttendees(string tenant, string spaceEmail)
{
var serviceAccount = _redisCache.GoogleTenantCredentials.StringGet(tenant).ToString();
var svcDto = JsonConvert.DeserializeObject<ServiceAccountDto>(serviceAccount);
if (!string.IsNullOrEmpty(serviceAccount))
{
var credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(svcDto.ClientEmail)
{
Scopes = new[] { PeopleServiceService.Scope.DirectoryReadonly }
}.FromPrivateKey(svcDto.PrivateKey));
var svc = new PeopleServiceService(new BaseClientService.Initializer { HttpClientInitializer = credential });
var request = svc.People.ListDirectoryPeople();
request.ReadMask = "names,emailAddresses";
request.Sources = PeopleResource.ListDirectoryPeopleRequest.SourcesEnum
.DIRECTORYSOURCETYPEDOMAINPROFILE;
var result = await request.ExecuteAsync();
return result.People;
}
return null;
}
Researching the error, we found references to allowing a service account domain-wide delegation. Attempting to follow the documentation we have the setup below.
We spent some time with Google Support today and they directed us to Stack Overflow with the tag below.
Not sure where we are going wrong. Since this is a test/sandbox Google environment, one thing that has been our minds is if the GSuite domain is properly linked to the Cloud side, but we have been novices in attempting to verify that is correct as well.
You need to set up domain wide delegation to the service account this is the best documentation i am aware of. Perform G Suite Domain-Wide Delegation of Authority
Beyond that make sure you have delegated to a user.
var gsuiteUser = "user@YourDomain.com";
var credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(svcDto.ClientEmail)
{
User = gsuiteUser,
Scopes = new[] { PeopleServiceService.Scope.DirectoryReadonly }
}.FromPrivateKey(svcDto.PrivateKey));
To read from the people api you need a person whos data you are reading or you are just going to be reading the service accounts data of which it doesnt have any.