Search code examples
google-contacts-apigoogle-apps-marketplaceservice-accounts

How to access contacts API with Service Account


I am in the process of upgrading my Marketplace applications to support the new marketplace api and OAUTH 2.

I have managed to migrate most APIs but am stuck on the contacts api. With the the previous marketplace version we used 2LO and client key/client secret to authenticate across the Google Apps domain. My understanding is that the only way to do this in current version is with Service Accounts and OAuth 2.

Based on the V3 calendar API I'm assuming something like this (although the contacts API does not support it from what I can see) -

        ServiceAccountCredential credential = new ServiceAccountCredential(
           new ServiceAccountCredential.Initializer(serviceAccountEmail)
           {
               Scopes = new[] { "https://www.google.com/m8/feeds" },
               User = "[email protected]"
           }.FromCertificate(certificate));

        var service = new ContactsService(new BaseClientService.Initializer()
        {
            HttpClientInitializer = credential,
            ApplicationName = "Contact API Sample",
        });

If anybody has done this, your advice will be appreciated!


Solution

  • Well I got no response anywhere on this so I can only assume that the standard client libraries don't have support for this.

    I have come up with a workaround based on the following post for email access.

    http://www.limilabs.com/blog/oauth2-gmail-imap-service-account

    You will need to follow his post and note the following:

    • this must use the DotNetOpenAuth version that he specifies. The latest version will not work.
    • You will only need his AssertionFlowClient classes which can be added to the below code I have provided here:

          X509Certificate2 certificate = new X509Certificate2(
              serviceAccountCertPath,
              serviceAccountCertPassword,
              X509KeyStorageFlags.Exportable);
      
          AuthorizationServerDescription server = new AuthorizationServerDescription
          {
              AuthorizationEndpoint = new Uri("https://accounts.google.com/o/oauth2/auth"),
              TokenEndpoint = new Uri("https://accounts.google.com/o/oauth2/token"),
              ProtocolVersion = ProtocolVersion.V20,
          };
      
          AssertionFlowClient provider = new AssertionFlowClient(server, certificate)
          {
              ServiceAccountId = serviceAccountEmail,
              Scope = string.Join(" ", new[] { "https://mail.google.com/", "https://www.google.com/m8/feeds/" }),
              ServiceAccountUser = userEmail,
          };
      
          IAuthorizationState grantedAccess = AssertionFlowClient.GetState(provider);
      
          RequestSettings rs = new RequestSettings("iLink");
          rs.OAuth2Parameters = new OAuth2Parameters();
          rs.OAuth2Parameters.AccessToken = grantedAccess.AccessToken;
          rs.OAuth2Parameters.RefreshToken = null;
          rs.OAuth2Parameters.ClientId = null;
          rs.OAuth2Parameters.ClientSecret = null;
          rs.OAuth2Parameters.RedirectUri = null;
      
          ContactsRequest cr = new ContactsRequest(rs);
          Feed<Contact> f = cr.GetContacts();
          foreach (var c in f.Entries)
          {   
              Response.Write(c.Name.FullName);
          }