2
votes

I made an application to insert, show and delete contacts from my Google account. It was properly functioning until 2 weeks ago, but after Google discontinued the support for client login (user/password access), forcing to use the OAuth2 to get acces by token, it is being a huge problem here (I'm not professional in software development).

With extensive searching after the update, I've adapted my code to the logic below:

Const service_id = "My_Service_ID.apps.googleusercontent.com"
Const service_email = "[email protected]"
Const nome_aplicacao = "My_Application_Name"
Const user_id = service_email

1.Create Token with credential obtained from p12 key and return a contactsRequest with that token:

Private Function CriaContactRequest() As ContactsRequest
    Try
        Dim certificate As New X509Certificate2(Server.MapPath("/chave/key.p12"), "notasecret", X509KeyStorageFlags.Exportable)
        Dim credential As New ServiceAccountCredential(New ServiceAccountCredential.Initializer(service_email) With { _
             .Scopes = New String() {"https://www.google.com/m8/feeds https://www.google.com/m8/feeds/groups/default/full"}
        }.FromCertificate(certificate))
        credential.RequestAccessTokenAsync(System.Threading.CancellationToken.None).Wait()
        Dim rs = New RequestSettings(nome_aplicacao) With { _
                .OAuth2Parameters = New OAuth2Parameters() With { _
                    .AccessToken = credential.Token.AccessToken, .RefreshToken = "6000" _
                } _
            }
        Dim cr As New ContactsRequest(rs)
        Return cr
    Catch ex As Exception
        Throw ex
    End Try
End Function

2.To show all contacts:

Public Sub ExibeContatos()
    Try
        Dim f As Feed(Of Contact) = CriaContactRequest().GetContacts()
        If f.Entries.Count > 0 Then
            ' Loop to show contacts here....
        Else
            Response.Write("Não existem contatos.")
        End If
    Catch ex As HttpException
        Response.Write("Erro Exibe Contatos: " & ex.Message)
    End Try
End Sub

3.To insert contacts:

Public Sub InsereContatoGoogle(oContato As Contact)
    Try
        Dim feedUri As New Uri(ContactsQuery.CreateContactsUri(user_id))
        InserenNoGrupoPrincipal(oContato)
        CriaContactRequest().Insert(feedUri, oContato)
    Catch ex As Exception
        Response.Write("Erro Insere Contato Google: " & ex.Message)
    End Try
End Sub

4.Before insert contact, assign to "My Contacs" (1st group on feed all groups):

Private Function InserenNoGrupoPrincipal(oContato As Contact) As Contact
    Try            
        Dim f As Feed(Of Group) = CriaContactRequest().GetGroups(user_id)
        Dim GrupoPrincipal As New GroupMembership
        GrupoPrincipal.HRef = f.Entries.ElementAt(0).Id
        oContato.GroupMembership.Add(GrupoPrincipal)
    Catch ex As Exception
        Response.Write("Erro Insere Grupo Principal: " & ex.Message)
    End Try
    Return oContato
End Function

5.Code to delete contact based on a vector populated with emails:

Public Sub ApagaContato(emailToExclude As String())
    Dim query As ContactsQuery = New ContactsQuery(ContactsQuery.CreateContactsUri(user_id))
    query.BaseAddress = emailToExclude(0)
    Dim feed As Feed(Of Contact)
    Try
        Dim cr As ContactsRequest = CriaContactRequest()
        feed = cr.GetContacts()
        For Each c As Contact In feed.Entries
            For x As Integer = 0 To c.Emails.Count - 1
                For y As Integer = 0 To emailToExclude.Length - 1
                    If c.Emails.Item(x).Address = emailToExclude(y) Then
                        cr.Delete(c)
                    End If
                Next
            Next
        Next
    Catch ex As Exception
        Response.Write("Erro Apaga Contato: " & ex.Message)
    End Try
End Sub

This functions are working, but not as expected: I can insert new entries, delete and view the entries normally, but in my Google account "[email protected]" nothing is happening. After some search in foruns, I suspect they are in service account "[email protected]", so that's the problem:

Someone can appoint what is wrong in scope, credential or other part of this code and how I can make the service account access save alterations in my "[email protected]" contacts?

2

2 Answers

0
votes

I don't think you are going to be able to use a service account for this. A service account is its own SUDO user, it has a drive account a Google calendar account and probably a contacts account as well just like any other user.

That being said it does not have access to your personal Google Contacts unless you give it access and as far as I can see there is no way to grant another person access to your contacts. What you have been doing is inserting users into the service accounts Google Contacts account.

I suggest you look into using Oauth2, authenticate your code once using your Google Account, then store the refresh token. The next time it runs your code can use refresh token to get you a new access token. You will have to go though the authentication process the first time.

0
votes

Resolved with this scope:

Private Function CriaContactRequest(Optional scope As String = "https://www.google.com/m8/feeds https://www.google.com/m8/feeds/groups/default/full") As ContactsRequest
    Try
        Dim rs = New RequestSettings(nome_aplicacao) With { _
                        .OAuth2Parameters = New OAuth2Parameters() With { _
                        .AccessToken = refresh_token, _
                        .RefreshToken = refresh_token, _
                        .ClientId = client_id, _
                        .ClientSecret = client_secret, _
                        .RedirectUri = redirect_uri, _
                        .Scope = scope _
                    } _
                }
        Dim cr As New ContactsRequest(rs)
        Return cr
    Catch ex As Exception
        Throw ex
    End Try
End Function

I mistakenly thought the refresh_token property was to be used to indicate the token refresh time, not that it was a code that could be stored.