Solved

Google Data Authentication in C# with 2-Step Verification

Posted on 2014-09-19
6
1,723 Views
Last Modified: 2015-03-02
using System;
//using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;

using Google.GData.Client;
using Google.GData.Extensions;
using Google.GData.Calendar;
using System.Diagnostics;

namespace RepBusGoogleCalandar
{
    public class CalandarMain
    {

        public bool m_isInitialized;
        private CalendarService m_calServiceSDER;
        public gcEvent m_gcEvent;
        private EventQuery m_query;
        private EventFeed m_feed;
        public const char fs = (char)29;//13; //field separator

        public CalandarMain()
        {
            RefreshFeed();
        }

        ~CalandarMain()
        {
            
        }

        //OAuth 2.0

        private void RefreshFeed()
        {
            bool bolGood;

            m_calServiceSDER = new CalendarService("SDERcalApp");
            m_calServiceSDER.setUserCredentials("MyUN", "MyPW");   // <----- UN and PW hard coded here

            //InvalidCredentialsException
            m_query = new EventQuery();
            m_query.Uri = new Uri(calendarURI);
            m_query.NumberToRetrieve = int.MaxValue;
            bolGood = false;
            try
            {
                m_feed = m_calServiceSDER.Query(m_query) as EventFeed;
                bolGood = true;
            }
            catch (Exception e)
            {
                string cs_err;
                cs_err = e.Message;
                Console.WriteLine(cs_err);
                Console.WriteLine(e.Source);
                //MessageBox.Show(cs_err, e.Source);
            }
            m_gcEvent = new gcEvent();
            if(bolGood)
            {
                Console.WriteLine("****** RefreshFeed: calFeed.Entries.Count: " + m_feed.Entries.Count);
            }
            m_isInitialized = bolGood;
        }
}

Open in new window


This code listed here worked just fine until I set up Google 2-Step Verification.
https://www.google.com/landing/2step/

Question: What extra code is needed to deal with the Google 2-Step Verification process?
NOTE: Look were I have the //InvalidCredentialsException notation.

Thanks!
 - Dave
0
Comment
Question by:AviationAce
  • 5
6 Comments
 
LVL 80

Expert Comment

by:David Johnson, CD, MVP
ID: 40334019
use an application password https://www.google.com/settings/security
0
 

Author Comment

by:AviationAce
ID: 40334351
I understand that in concept, but need help in hammering out the details.  If you were going to modify the class I posted, where exactly would you start?

Please note: I have already created a new "Client ID for native application" at the Google Developers Console.  See the attachment.
Screenshot-2014-09-20-08.07.59.png
0
 

Author Comment

by:AviationAce
ID: 40339255
It appears to me that modifying the old class is not feasible.  So, I am writing a new one using the new V3 interface.

I'm getting a type conversion error and I don't understand why.  Please look at the comment that starts with Error 1 and advise.

using System;
using System.IO;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Diagnostics;

//For use in class CalandarMain
//using Google.GData.Client;
//using Google.GData.Extensions;
//using Google.GData.Calendar;


//For use in class CalandarMainV3  :  An entirly new class needed to 
using System.Threading;
using System.Threading.Tasks;
using Google;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Calendar.v3;
using Google.Apis.Calendar.v3.Data;
using Google.Apis.Services;
using Google.Apis.Util.Store;

    public class CalandarMainV3
    {
        const String ClientSecretsFile = "C:\\Users\\User1\\Documents\\Visual Studio 2010\\Projects\\Programming\\Projects\\Google Ops\\client_secrets.json";

        const String CalAppName = "MyCalAppV3";

        bool m_Init;

        public CalandarMainV3()
        {
            m_Init = AuthGoogleDataInterface();
        }

        private bool AuthGoogleDataInterface()
        {
            bool b_success;
            try
            {
                UserCredential credential;

                using (var stream = new FileStream(ClientSecretsFile, FileMode.Open, FileAccess.Read))
            {
                //Error	1	Cannot implicitly convert type 'System.Threading.Tasks.Task<Google.Apis.Auth.OAuth2.UserCredential>' to 'Google.Apis.Auth.OAuth2.UserCredential'	C:\Users\user1\Documents\Visual Studio 2010\Projects\Programming\Projects\Google Ops\RepBusGoogleCalandar\RepBusGoogleCalandar\ClalandarMain.cs	273	30	RepBusGoogleCalandar
                credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
                    GoogleClientSecrets.Load(stream).Secrets,
                    new[] { Google.Apis.Calendar.v3.CalendarService.Scope.Calendar },
                    "user",
                    CancellationToken.None,
                    new FileDataStore("Calendar.MyCal")
                    );
            }
                Console.WriteLine("AuthGoogleDataInterface: Success");
                b_success = true;
            }
            catch (Exception e)
            {
                string cs_err;
                cs_err = e.Message;
                Console.WriteLine(cs_err);
                Console.WriteLine(e.Source);
                Console.WriteLine("AuthGoogleDataInterface: Fail");
                b_success = false;
                throw;
            }

            return b_success;
        }
    }
}

Open in new window

0
The New “Normal” in Modern Enterprise Operations

DevOps for the modern enterprise offers many benefits — increased agility, productivity, and more, but digital transformation isn’t easy, especially if you’re not addressing the right issues. Register for the webinar to dive into the “new normal” for enterprise modern ops.

 

Author Comment

by:AviationAce
ID: 40347101
The code below complies correctly and runs, but I am now having a problem with the CLIENT SECRETS file.

using System;
using System.IO;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Diagnostics;

//For use in class CalandarMainV3  :  An entirely new class needed to 
using System.Threading;
using System.Threading.Tasks;
using Google;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Calendar.v3;
using Google.Apis.Calendar.v3.Data;
using Google.Apis.Services;
using Google.Apis.Util.Store;

namespace RepBusGoogleCalendarV3
{
    public class CalandarMainV3
    {
        const String ClientSecretsFile = "C:\\Users\\user1\\Documents\\Visual Studio 2010\\Projects\\Programming\\Projects\\Google Ops\\client_secrets.json";

        bool m_Init;

        public CalandarMainV3()
        {
            Console.WriteLine("Calling: AuthGoogleDataInterface()");
            m_Init = AuthGoogleDataInterface();
        }

        private bool AuthGoogleDataInterface()
        {
            bool b_success;
            try
            {
                Console.WriteLine("New User Credential");
                // New User Credential
                UserCredential credential;
                using (var stream = new FileStream(ClientSecretsFile, FileMode.Open, FileAccess.Read))
                {
                    credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
                        GoogleClientSecrets.Load(stream).Secrets,
                        new[] { CalendarService.Scope.Calendar },
                        "user", CancellationToken.None,
                        null).Result;
                        //new FileDataStore("My.cal")).Result;
                }

                Console.WriteLine("New Service");
                // Create the service.
                var service = new CalendarService(new BaseClientService.Initializer
                {
                    HttpClientInitializer = credential,
                    ApplicationName = "My Calendar API",
                });
                
                Console.WriteLine("AuthGoogleDataInterface: Success");
                b_success = true;
            }
            catch (Exception e)
            {
                string cs_err;
                cs_err = e.Message;
                Console.WriteLine(cs_err);
                Console.WriteLine(e.Source);
                Console.WriteLine("AuthGoogleDataInterface: Fail");
                b_success = false;
                throw;
            }
            return b_success;
        }
    }
}

Open in new window


Contents of the client_secrets.json file.

{"installed":{"auth_uri":"https://accounts.google.com/o/oauth2/auth","client_secret":"xxxxxxxxxxxxxxxxxxxxxxxx","token_uri":"https://accounts.google.com/o/oauth2/token","client_email":"","redirect_uris":["urn:ietf:wg:oauth:2.0:xxx","xxx"],"client_x509_cert_url":"","client_id":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs"}}

Open in new window


When I run the program, it loads a web page with the following contents:

401. That’s an error.

Error: invalid_client

no application name

Request Details
scope=https://www.googleapis.com/auth/calendar
response_type=code
redirect_uri=http://localhost:00000/authorize/
access_type=offline
client_id=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com

That’s all we know.

What am I doing wrong?
0
 

Accepted Solution

by:
AviationAce earned 0 total points
ID: 40347667
stackoverflow.com/questions/18677244/error-invalid-client-no-application-name

At the link above I discovered that the error was being caused because I had not set up "Project Name" in my Google APIs Dashboard.

After setting it up the code ran with out error.  The first time I ran it a web page was displayed asking me to ok this device to use the service.
0
 

Author Closing Comment

by:AviationAce
ID: 40361055
That fact that a project name hadn't been set up yet was key.  That should be documented better.
0

Featured Post

Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

There are many add-ons for Google docs, slides and sheets that can be extremely helpful in keeping your files organized and simple to use. Add-ons are installed into your Google docs, slides or sheets through Google's Add-On Store. One of my favorit…
Entity Framework is a powerful tool to help you interact with the DataBase but still doesn't help much when we have a Stored Procedure that returns more than one resultset. The solution takes some of out-of-the-box thinking; read on!
This Micro Tutorial will demonstrate how marketers can use the Mobile Emulation Tool in Chrome Developer Tool. This will let you preview your site on any mobile device.
This Micro Tutorial will demonstrate using Google Doc how to import live data to another spreadsheet in Google Spreadsheets using the IMPORTRANGE function.

828 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question