Google Data Authentication in C# with 2-Step Verification

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
AviationAceSole-ProprietorAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

David Johnson, CD, MVPOwnerCommented:
use an application password https://www.google.com/settings/security
0
AviationAceSole-ProprietorAuthor Commented:
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
AviationAceSole-ProprietorAuthor Commented:
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
Ultimate Tool Kit for Technology Solution Provider

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy now.

AviationAceSole-ProprietorAuthor Commented:
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
AviationAceSole-ProprietorAuthor Commented:
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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
AviationAceSole-ProprietorAuthor Commented:
That fact that a project name hadn't been set up yet was key.  That should be documented better.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
.NET Programming

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.