AviationAce
asked on
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;
}
}
This code listed here worked just fine until I set up Google 2-Step Verification.
https://www.google.com/lan
Question: What extra code is needed to deal with the Google 2-Step Verification process?
NOTE: Look were I have the //InvalidCredentialsExcept
Thanks!
- Dave
use an application password https://www.google.com/settings/security
ASKER
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
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
ASKER
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.
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;
}
}
}
ASKER
The code below complies correctly and runs, but I am now having a problem with the CLIENT SECRETS file.
Contents of the client_secrets.json file.
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=xxxxxxxxxxxxxxxx xxxxxxxxxx xxxxxxxxxx xxxxxxxxx. apps.googl euserconte nt.com
That’s all we know.
What am I doing wrong?
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;
}
}
}
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"}}
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=xxxxxxxxxxxxxxxx
That’s all we know.
What am I doing wrong?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
That fact that a project name hadn't been set up yet was key. That should be documented better.