Search code examples
google-apigoogle-contacts-apigoogle-people-api

Google contacts are not showing by using Google People API


Since Google is deprecating Google contacts API and instead advising us to use Google People API to add/create/delete contacts. I was able to create, get Google contacts, Sample code is below:

const { google } = require("googleapis")
const path = require("path")

const keyFile = path.join(__dirname, "serviceAccCredentials.json")
const scopes = [
  "https://www.googleapis.com/auth/contacts",
  "https://www.googleapis.com/auth/contacts.readonly"
]

function log(arg) {
  console.log(JSON.stringify(arg, null, 4))
}

const run = async () => {
  try {

    const { people, contactGroups } = google.people({
      version: "v1",
      auth: await google.auth.getClient({
        keyFile,
        scopes
      })
    })

    const createContact = await people.createContact(
        {
        requestBody: {
          names: [
            {
              givenName: "Yacov 3",
              familyName: "110$"
            }
          ],
          "memberships": [
            {
              "contactGroupMembership": {
                contactGroupId: 'myContacts'
                // "contactGroupResourceName": "contactGroups/myContacts"
              }
            }
          ]
        }
      }
    )
    log(createContact.data)

    const afterResponse = await people.connections.list({
      resourceName: "people/me",
      personFields: "names",
    })
    log(afterResponse.data)

  } catch (e) {
    console.log(e)
  }
}

run()

Problem is that i don't see the contacts created with the service account under the Google contacts. Normally the service account is created for the G-suit user, under the G-suit domain wide delegation settings, i added the project id with scope as well. Also People API is enabled in the service account.

Further, In the playground area of Google's official documentation when i tried to create the a Google contact, it worked. The request from there API explorer / playground looks like this

     const createContact = await people.createContact({
        "personFields": "names",
        "sources": [
          "READ_SOURCE_TYPE_CONTACT"
        ],
        "prettyPrint": true,
        "alt": "json",
        "resource": {
          "names": [
            {
              "givenName": "test 2",
              "familyName": "playground"
            }
          ],
          "memberships": [
            {
              "contactGroupMembership": {
                "contactGroupResourceName": "contactGroups/myContacts"
              }
            }
          ]
        }
      })

Strangely, all these properties like contactGroupResourceName, personFields, sources, alt, prettyPrint doesn't exists.

can anyone really tell me what is going on. PS: i can not and don't want to use OAuth2 since the application is going to be server to server communication, wouldn't involve any human consent. Thanks


Solution

  • Issue:

    You might have enabled domain-wide delegation for your service account, but you are not using it to impersonate a regular user.

    The purpose of domain-wide delegation is for the service account to act on behalf of any user in the domain, but in order to do that, you have to specify which user you want the service account to impersonate.

    Otherwise, the service account will access its own resources (its Contacts, its Drive, its Calendar, etc.) not the resources of a regular account. Therefore, you'll not see the created contacts if you access Contacts UI with a regular account, since contacts were not created for this account.

    Solution:

    You need to impersonate the account for which you want to create contacts.

    In order to do that, since you're using Node's getClient(), you should specify the email address of the account you want to impersonate, as shown here:

    auth.subject = "email-address-to-impersonate";
    

    Update:

    In this case, you could do the following:

    let auth = await google.auth.getClient({
      keyFile,
      scopes
    });
    auth.subject = "email-address-to-impersonate";
    const { people, contactGroups } = google.people({
      version: "v1",
      auth: auth
    })
    

    Reference: