Search code examples
vb.netoauth-2.0google-contacts-api

Authenticating Google Contacts v3 (can't I use my Google Calendar token)?


I have seen a few topics on this issue but maybe I am overlooking something.

This is my current VB code to authticate for my calendar:

Private Function DoAuthentication(ByRef rStrToken As String) As Boolean
    Dim credential As UserCredential
    Dim Secrets = New ClientSecrets()
    Secrets.ClientId = m_strClientID
    Secrets.ClientSecret = m_strClientSecret
    m_Scopes.Add(CalendarService.Scope.Calendar)

    Try
        credential = GoogleWebAuthorizationBroker.AuthorizeAsync(Secrets, m_Scopes,
                                                                 "user", CancellationToken.None,
                                                                 New FileDataStore("xxxxx.Calendar.Application")).Result()

        ' Create the calendar service using an initializer instance
        Dim initializer As New BaseClientService.Initializer()
        initializer.HttpClientInitializer = credential
        initializer.ApplicationName = "Public Talks And Meeting Schedule Assistant Calendar"
        m_Service = New CalendarService(initializer)

        rStrToken = credential.Token.AccessToken.ToString()
    Catch ex As Exception
        ' We encountered some kind of problem, perhaps they have not yet authenticated?
        ' Can we isolate that as the exception?
        Return False
    End Try

    Return True
End Function

I now also want to work with the Google Contact data. So I modified the above method to include this scope:

m_Scopes.Add("https://www.google.com/m8/feeds/")

Then I tried to use it:

If (DoAuthentication(strToken)) Then
    Dim settings As New RequestSettings("xx", strToken)
    settings.AutoPaging = True
    iResult = RESULT_SUCCESS_OAUTH
    m_ContactsRequest = New ContactsRequest(settings)
    Dim f As Feed(Of Contact) = m_ContactsRequest.GetContacts()

    For Each oContact As Contact In f.Entries
        Console.WriteLine(oContact.Name.ToString)
    Next
Else
    Return RESULT_FAILED_OAUTH
End If

But it raises an exception: 401 Unauthorized.

What am I doing wrong? Thank you.

UPDATE

I found this webpage: http://www.daimto.com/google-contacts-with-c/

So I tried to implement some of it:

Private Function DoAuthentication(ByRef rStrToken As String, ByRef rParameters As OAuth2Parameters) As Boolean Dim credential As UserCredential Dim Secrets = New ClientSecrets() Secrets.ClientId = m_strClientID Secrets.ClientSecret = m_strClientSecret m_Scopes.Add(CalendarService.Scope.Calendar) m_Scopes.Add("https://www.google.com/m8/feeds/")

Try
    credential = GoogleWebAuthorizationBroker.AuthorizeAsync(Secrets, m_Scopes,
                                                             "user", CancellationToken.None,
                                                             New FileDataStore("xx.Calendar.Application")).Result()

    ' Create the calendar service using an initializer instance
    Dim initializer As New BaseClientService.Initializer()
    initializer.HttpClientInitializer = credential
    initializer.ApplicationName = "Public Talks And Meeting Schedule Assistant Calendar"
    m_Service = New CalendarService(initializer)

    rStrToken = credential.Token.AccessToken.ToString()
    rParameters.AccessToken = credential.Token.AccessToken
    rParameters.RefreshToken = credential.Token.RefreshToken
Catch ex As Exception
    ' We encountered some kind of problem, perhaps they have not yet authenticated?
    ' Can we isolate that as the exception?
    Return False
End Try

And the code:

   Dim parameters As New OAuth2Parameters
    If (DoAuthentication(strToken, parameters)) Then
        Dim settings As New RequestSettings("GoogleCalIF", parameters)
        settings.AutoPaging = True
        iResult = RESULT_SUCCESS_OAUTH
        m_ContactsRequest = New ContactsRequest(settings)
        Dim f As Feed(Of Contact) = m_ContactsRequest.GetContacts()

        For Each oContact As Contact In f.Entries
            Console.WriteLine(oContact.Name.ToString)
        Next
    Else
        Return RESULT_FAILED_OAUTH
    End If

    Return True
End Function

But I still get a 401 Exception. I have correctly added the Contacts API to my Google Console. Confused.

I am afraid I have a headache. I can't get past this 401 Unathorized issue.


Solution

  • I got it working! There were a few things that I had to do.

    Step 1

    It seems that I needed by scopes to be one line string with a space in between. So I changed my authentication method to:

    Private Function DoAuthentication(ByRef rStrToken As String, ByRef rParameters As OAuth2Parameters) As Boolean
    
        Dim credential As UserCredential
        Dim Secrets = New ClientSecrets()
        Secrets.ClientId = m_strClientID
        Secrets.ClientSecret = m_strClientSecret
        m_Scopes.Add("https://www.googleapis.com/auth/calendar https://www.google.com/m8/feeds/")
    
        Try
            credential = GoogleWebAuthorizationBroker.AuthorizeAsync(Secrets, m_Scopes,
                     "user", CancellationToken.None,
                     New FileDataStore("PublicTalkSoftware.Calendar.Application")).Result()
    
            ' Create the calendar service using an initializer instance
            Dim initializer As New BaseClientService.Initializer()
            initializer.HttpClientInitializer = credential
            initializer.ApplicationName = "Public Talks And Meeting Schedule Assistant Calendar"
            m_Service = New CalendarService(initializer)
    
            rStrToken = credential.Token.AccessToken.ToString()
            rParameters.AccessToken = credential.Token.AccessToken
            rParameters.RefreshToken = credential.Token.RefreshToken
        Catch ex As Exception
            ' We encountered some kind of problem, perhaps they have not yet authenticated?
            ' Can we isolate that as the exception?
            Return False
        End Try
    
        Return True
    End Function
    

    I commented out the line CalendarService.Scope.Calendar and used the literal text. Not sure if that was the best thing to do.

    Step 2

    In the aforementioned method I passed in a OAuth2Parameters object and populated a couple of entries.

    Step 3

    The calling code is something like this:

    Dim m_ContactsRequest As ContactsRequest
    Dim strToken As String = ""
    Dim iResult As Integer = 0
    Dim parameters As New OAuth2Parameters
    If (DoAuthentication(strToken, parameters)) Then
       iResult = RESULT_SUCCESS_OAUTH
    Else
       Return RESULT_FAILED_OAUTH
    End If
    
    Try
       Dim settings As New RequestSettings("XX", parameters)
       m_ContactsRequest = New ContactsRequest(settings)
       Dim f As Feed(Of Contact) = m_ContactsRequest.GetContacts()
    
       For Each oContact As Contact In f.Entries
             Console.WriteLine(oContact.Name.FullName.ToString)
       Next
    Catch ex As Exception
        ' We encountered some kind of problem, perhaps they have not yet authenticated?
        ' Can we isolate that as the exception?
        Return False
    End Try
    

    Step 4

    Since I already had an access token on the PC, I had to revoke it, so that I would also get access to the contacts as opposed to just the calendar service.