I am using Google Contacts Api. I am not sure whether I can send an Auth Token as a parameter.
string _token = _google.Token;
RequestSettings requestSettings = new RequestSettings("AppName",_token);
ContactsRequest contactsRequest = new ContactsRequest(requestSettings);
// Get the feed
Feed<Contact> feed = contactsRequest.GetContacts();
I get 401 Unauthorised as a response for this code, but if I send the username and password as parameters, I am able to get a response.
Whoops, sorry, I didn't quite get it right the first time. I'm using this code in a real app, I just do things a bit different in my code because I'm constantly refreshing tokens.
In any case, here's the proper logic:
// get this information from Google's API Console after registering your app
var parameters = new OAuth2Parameters
{
ClientId = #"",
ClientSecret = #"",
RedirectUri = #"",
Scope = #"https://www.google.com/m8/feeds/",
};
// generate the authorization url
string url = OAuthUtil.CreateOAuth2AuthorizationUrl(parameters);
// now use the url to authorize the app in the browser and get the access code
(...)
// get this information from Google's API Console after registering your app
parameters.AccessCode = #"<from previous step>";
// get an access token
OAuthUtil.GetAccessToken(parameters);
// setup connection to contacts service
var contacts = new ContactsRequest(new RequestSettings("<appname>", parameters));
// get each contact
foreach (var contact in contacts.GetContacts().Entries)
{
System.Diagnostics.Debug.WriteLine(contact.ContactEntry.Name.FullName);
}
FYI, after you call GetAccessToken() against your access code, your parameters data structure will include the AccessToken and RefreshToken fields. If you STORE these two values, you can set them in the parameters structure in subsequent calls (allowing you to skip asking for authorization in the future) and instead of calling GetAccessToken() simply call RefreshAccessToken(parameters) and you'll always have access to the contacts. Make sense? Here, take a look:
// get this information from Google's API Console after registering your app
var parameters = new OAuth2Parameters
{
ClientId = #"",
ClientSecret = #"",
RedirectUri = #"",
Scope = #"https://www.google.com/m8/feeds/",
AccessCode = "",
AccessToken = "", /* use the value returned from the old call to GetAccessToken here */
RefreshToken = "", /* use the value returned from the old call to GetAccessToken here */
};
// get an access token
OAuthUtil.RefreshAccessToken(parameters);
// setup connection to contacts service
var contacts = new ContactsRequest(new RequestSettings("<appname>", parameters));
// get each contact
foreach (var contact in contacts.GetContacts().Entries)
{
System.Diagnostics.Debug.WriteLine(contact.ContactEntry.Name.FullName);
}
Edit:
// generate the authorization url
string url = OAuthUtil.CreateOAuth2AuthorizationUrl(parameters);
// now use the url to authorize the app in the browser and get the access code
(...)
// get this information from Google's API Console after registering your app
var parameters = new OAuth2Parameters
{
ClientId = #"",
ClientSecret = #"",
RedirectUri = #"",
Scope = #"https://www.google.com/m8/feeds/",
AccessCode = #"<from previous step>",
};
// get an access token
OAuthUtil.GetAccessToken(parameters);
// setup connection to contacts service
var contacts = new ContactsRequest(new RequestSettings("<appname>", parameters));
// get each contact
foreach (var contact in contacts.GetContacts().Entries)
{
System.Diagnostics.Debug.WriteLine(contact.ContactEntry.Name.FullName);
}
Related
I am supporting an IT admin, who is himself facilitating the use of compliance software. To that end, I have written some C# code that iterates through all users in a directory, and performs operations on their messages. My current solution uses two different APIs to accomplish this (code snippet below), but obviously it would be better to only use one API. Having scanned through other posts here, I failed to find a satisfactorily clear answer on how to make that happen. My app is a service account, with Google Workspace domain-wide delegation enabled. How can I use only one API to accomplish what I am doing with two?
[working code snippet]
string domain; // domain name
string adminEmail; // admin e-mail
string directoryClientEmail; // client e-mail for Directory API
string directoryPrivateKey; // private key for Directory API
string directoryPrivateKeyId; // private key ID for Directory API
string gmailClientEmail; // client e-mail for Gmail API
string gmailPrivateKey; // private key for Gmail API
string gmailPrivateKeyId; // private key ID for Gmail API
CancellationToken cancellationToken; // a cancellation token
DirectoryService directoryClient = new DirectoryService(
new BaseClientService.Initializer
{
HttpClientInitializer = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(creds.DirectoryClientEmail)
{
User = adminEmail,
Scopes = new[] { DirectoryService.Scope.AdminDirectoryUser },
Key = RSA.Create(directoryPrivateKey),
KeyId = directoryPrivateKeyId
}.FromPrivateKey(directoryPrivateKey))
});
UsersResource.ListRequest userListRequest = directoryClient.Users.List();
userListRequest.Domain = domain;
Users userList = await userListRequest.ExecuteAsync(cancellationToken);
foreach (User user in userList)
{
GmailService gmailClient = new GmailService(
new BaseClientService.Initializer
{
HttpClientInitializer = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(gmailClientEmail)
{
User = user.PrimaryEmail,
Scopes = new[] { GmailService.Scope.MailGoogleCom },
Key = RSA.Create(gmailPrivateKey),
KeyId = gmailPrivateKeyId
}.FromPrivateKey(gmailPrivateKey))
});
ListRequest listRequest = new ListRequest(gmailClient, "me");
ListMessageResponse listMessageResponse = await listRequest.ExecuteAsync(cancellationToken);
foreach (Message message in listMessageResponse.Messages)
{
// do stuff
}
}
To achieve what you want, you can't only use one API. As the Gmail API will not give you the users in the domain, but you can get a user's messages with it; which you need. So Gmail API is a requirement.
Then if you want an up-to-date domain users list, then you need to use the Directory API, so unless you have a list of users somewhere else, you require this API too.
I have an AngularJS + C#.NET OnePage Application Website. The goal is to retrieve a JSON from a private Google Spreadsheet that I own with C# (not with AngularJS). I read various Google Sheets Documentation and API, OAuth 2.0 etc. and tried some examples, but none of them seem to work for me. I see there are different ways to access and retrieve data from a Google Spreadsheet, still, they don't work for my case.
Can anyone help me?
Thank you.
Edit: I managed to get a token by creating an Other Application type under Google Developers Console=>Credentials=>Create Client ID. Here's the C# Console Application:
using System;
using Google.GData.Client;
using Google.GData.Spreadsheets;
namespace MySpreadsheetIntegration
{
class Program
{
static void Main(string[] args)
{
////////////////////////////////////////////////////////////////////////////
// STEP 1: Configure how to perform OAuth 2.0
////////////////////////////////////////////////////////////////////////////
// TODO: Update the following information with that obtained from
// https://code.google.com/apis/console. After registering
// your application, these will be provided for you.
string CLIENT_ID = "12345678.apps.googleusercontent.com";
// This is the OAuth 2.0 Client Secret retrieved
// above. Be sure to store this value securely. Leaking this
// value would enable others to act on behalf of your application!
string CLIENT_SECRET = "Gc0230jdsah01jqpowpgff";
// Space separated list of scopes for which to request access.
string SCOPE = "https://spreadsheets.google.com/feeds https://docs.google.com/feeds";
// This is the Redirect URI for installed applications.
// If you are building a web application, you have to set your
// Redirect URI at https://code.google.com/apis/console.
string REDIRECT_URI = "urn:ietf:wg:oauth:2.0:oob";
////////////////////////////////////////////////////////////////////////////
// STEP 2: Set up the OAuth 2.0 object
////////////////////////////////////////////////////////////////////////////
// OAuth2Parameters holds all the parameters related to OAuth 2.0.
OAuth2Parameters parameters = new OAuth2Parameters();
// Set your OAuth 2.0 Client Id (which you can register at
// https://code.google.com/apis/console).
parameters.ClientId = CLIENT_ID;
// Set your OAuth 2.0 Client Secret, which can be obtained at
// https://code.google.com/apis/console.
parameters.ClientSecret = CLIENT_SECRET;
// Set your Redirect URI, which can be registered at
// https://code.google.com/apis/console.
parameters.RedirectUri = REDIRECT_URI;
////////////////////////////////////////////////////////////////////////////
// STEP 3: Get the Authorization URL
////////////////////////////////////////////////////////////////////////////
// Set the scope for this particular service.
parameters.Scope = SCOPE;
// Get the authorization url. The user of your application must visit
// this url in order to authorize with Google. If you are building a
// browser-based application, you can redirect the user to the authorization
// url.
string authorizationUrl = OAuthUtil.CreateOAuth2AuthorizationUrl(parameters);
Console.WriteLine(authorizationUrl);
Console.WriteLine("Please visit the URL above to authorize your OAuth "
+ "request token. Once that is complete, type in your access code to "
+ "continue...");
parameters.AccessCode = Console.ReadLine();
////////////////////////////////////////////////////////////////////////////
// STEP 4: Get the Access Token
////////////////////////////////////////////////////////////////////////////
// Once the user authorizes with Google, the request token can be exchanged
// for a long-lived access token. If you are building a browser-based
// application, you should parse the incoming request token from the url and
// set it in OAuthParameters before calling GetAccessToken().
OAuthUtil.GetAccessToken(parameters);
string accessToken = parameters.AccessToken;
Console.WriteLine("OAuth Access Token: " + accessToken);
////////////////////////////////////////////////////////////////////////////
// STEP 5: Make an OAuth authorized request to Google
////////////////////////////////////////////////////////////////////////////
// Initialize the variables needed to make the request
GOAuth2RequestFactory requestFactory =
new GOAuth2RequestFactory(null, "MySpreadsheetIntegration-v1", parameters);
SpreadsheetsService service = new SpreadsheetsService("MySpreadsheetIntegration-v1");
service.RequestFactory = requestFactory;
Console.ReadLine();
}
}
}
With this code I have to copy the link I get and paste it in a browser in order to get a token. Is there a way to get this token directly in my app without the need to copy the link manually?
I found another working solution where you don't have to open a browser window which is similar to the solution with the p12-key above.
First, create in the Google Developer Console under Create Credentials a Service account key.
Then, you have to choose a service account type, you can choose App Engine Default Service account and you can download a json file that contains the private key.
With this file, you can create programmatically Google credentials (where "sheets-test.json" is the downloaded json file):
var credential = GoogleCredential.FromStream(new FileStream("Sheets-test.json", FileMode.Open)).CreateScoped(Scopes);
Give the service user (you can find it in the json file in the client_email field) access to your spreadsheet.
Here is the full code that enables you to append a value to the first free row in a spreadsheet, I modified the google .NET quickstart project:
using System;
using System.Collections.Generic;
using System.IO;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Services;
using Google.Apis.Sheets.v4;
using Google.Apis.Sheets.v4.Data;
namespace SheetApiTest
{
public class SheetApiWithGoogleCredentials
{
static string[] Scopes = { SheetsService.Scope.Spreadsheets };
static string ApplicationName = "Google Sheets API .NET Quickstart";
public void AppendData()
{
// the downloaded jsonn file with private key
var credential = GoogleCredential.FromStream(new FileStream("Sheets-test.json", FileMode.Open)).CreateScoped(Scopes);
var service = new SheetsService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
// spreadsheet id - your own spreadsheet id
var spreadsheetId = "11AwV7d1pEPq4x-rx9WeZHNwGJa0ehfRhh760";
var valueRange = new ValueRange { Values = new List<IList<object>> { new List<object>() } };
valueRange.Values[0].Add(DateTime.Now.ToLongTimeString());
// insert here the name of your spreadsheet table
var rangeToWrite = "Tabellenblatt1";
var appendRequest = service.Spreadsheets.Values.Append(valueRange, spreadsheetId, rangeToWrite);
appendRequest.ValueInputOption = SpreadsheetsResource.ValuesResource.AppendRequest.ValueInputOptionEnum.USERENTERED;
var appendReponse = appendRequest.Execute();
}
}
}
There is a way for server-to-server communication using certificate instead of copy/paste the provided by Google AccessCode for the communication to be established.
First you will need to get your certificate from Google Console.
If you haven't already created a project do so and give it a name. Then:
Go to "Credentials" section (found on the left menu) and
Click on the button "Create Credentials" and choose "Service account key"
Choose the service account to be "App Engine default service account" and
Choose the "key type" to be "p.12" which is the certificate type.
Image for reference:
After these steps are completed, the certificate will be automatically downloaded. Upload it in some folder in your project and use it as shown below.
Note: for the sake of simplicity the code is placed in the controller.
public async Task<ActionResult> ServerAuth()
{
ViewBag.Message = "Server to server authentication";
List<string> records = new List<string>();
const string ServiceAccountEmail = "your-account#appspot.gserviceaccount.com";
string fullKeyPath = HttpContext.Server.MapPath("~/Key/MyProjectKey.p12"); // The certificate generated by Google and uploaded in the project.
var certificate = new X509Certificate2(fullKeyPath, "notasecret", X509KeyStorageFlags.Exportable); // "notasecret" is the password for the certificate
var serviceAccountCredentialInitializer = new ServiceAccountCredential.Initializer(ServiceAccountEmail)
{
Scopes = new[] { "https://spreadsheets.google.com/feeds", "http://spreadsheets.google.com/feeds/spreadsheets/private/full" }
}.FromCertificate(certificate);
var credential = new ServiceAccountCredential(serviceAccountCredentialInitializer);
if (!await credential.RequestAccessTokenAsync(System.Threading.CancellationToken.None))
{
throw new InvalidOperationException("Access token request failed.");
}
var requestFactory = new GDataRequestFactory(null);
requestFactory.CustomHeaders.Add("Authorization: Bearer " + credential.Token.AccessToken);
var service = new SpreadsheetsService(null) { RequestFactory = requestFactory };
SpreadsheetQuery query = new SpreadsheetQuery();
query.Title = "Test Sheet"; // The exact name of the sheet you want to read
query.Exact = true;
var feed = service.Query(query);
foreach (SpreadsheetEntry entry in feed.Entries)
{
foreach (WorksheetEntry worksheet in entry.Worksheets.Entries.Cast<WorksheetEntry>())
{
CellQuery cellQuery = new CellQuery(worksheet.CellFeedLink);
CellFeed cellFeed = service.Query(cellQuery);
foreach (CellEntry cell in cellFeed.Entries)
{
records.Add(cell.InputValue);
}
}
}
return View(records);
}
I'm suddenly starting to get the following exception when attempting to authenticate and access a spreadsheet on Google drive:
Unhandled Exception: Google.GData.Client.GDataRequestException:
Execution of aut hentication request returned unexpected
result: 404
at Google.GData.Client.Utilities.getAuthException(TokenCollection tokens,
Htt pWebResponse response)
at Google.GData.Client.Utilities.QueryClientLoginToken(GDataCredentials
gc, S tring serviceName, String applicationName, Boolean
fUseKeepAlive, IWebProxy prox yServer, Uri
clientLoginHandler)
at Google.GData.Client.GDataGAuthRequest.QueryAuthToken(GDataCredentials
gc)
at Google.GData.Client.GDataGAuthRequest.EnsureCredentials()
at Google.GData.Client.GDataRequest.EnsureWebRequest()
at Google.GData.Client.GDataGAuthRequest.EnsureWebRequest()
at Google.GData.Client.GDataRequest.Execute()
at Google.GData.Client.GDataGAuthRequest.Execute(Int32 retryCounter)
at Google.GData.Client.GDataGAuthRequest.Execute()
at Google.GData.Client.Service.Query(Uri queryUri, DateTime ifModifiedSince, String etag, Int64& contentLength)
at Google.GData.Client.Service.Query(FeedQuery feedQuery)
at Google.GData.Documents.DocumentsService.Query(DocumentsListQuery
feedQuery )
at GoogleLogger.GoogleService.getLastXECLogRows(String folderName, String fileName, Int32 rows)
This is in code that has been running for two years without any problems. I first thought that I may have lost access permissions on my production system but Google drive loads fine in my web browser. Tried it on several other systems and am getting the very same.
Did they change something in the Google API today? This can't be coincidence!
Google has retired their older authentication API. OAuth 2.0 should be used instead.
I spent too much time to figure out how to use newer Auth API with older GData API grabbing bits and pieces of information here and there from the Internet.
I decided to share all the the details with screenshots to save your time.
Go to https://console.developers.google.com/project
Hit Create Project button
Create project. Type in some name.
Go to API & Auth > Credentials and hit Create new Client ID button. It will create JSON key for you automatically - ignore that.
Hit Generate new P12 key
File download will start automatically. Remember the password, you will need it to open the file you just downloaded.
Rename downloaded file to Key.p12 and add it to your solution. Make sure you set Build Action and Copy to Output Directory accordingly.
Install Google API Auth using Nuget. Type the following in the Package Manager Console
Install-Package Google.Apis.Auth
Copy service account email address that was generated in Step #4.
Grant appropriate permission to this user in your Google Spreadsheet.
Use the following code to query the spreadsheet. Replace email and Google spreadsheet URL address in the code below.
const string ServiceAccountEmail = "452351479-q41ce1720qd9l94s8847mhc0toao1fed#developer.gserviceaccount.com";
var certificate = new X509Certificate2("Key.p12", "notasecret", X509KeyStorageFlags.Exportable);
var serviceAccountCredentialInitializer =
new ServiceAccountCredential.Initializer(ServiceAccountEmail)
{
Scopes = new[] { "https://spreadsheets.google.com/feeds" }
}.FromCertificate(certificate);
var credential = new ServiceAccountCredential(serviceAccountCredentialInitializer);
if (!credential.RequestAccessTokenAsync(System.Threading.CancellationToken.None).Result)
throw new InvalidOperationException("Access token request failed.");
var requestFactory = new GDataRequestFactory(null);
requestFactory.CustomHeaders.Add("Authorization: Bearer " + credential.Token.AccessToken);
var service = new SpreadsheetsService(null) { RequestFactory = requestFactory };
var query = new ListQuery("https://spreadsheets.google.com/feeds/list/0ApZkobM61WIrdGRYshh345523VNsLWc/1/private/full");
var feed = service.Query(query);
var rows = feed.Entries
.Cast<ListEntry>()
.Select(arg =>
new
{
Field0 = arg.Elements[0].Value,
Field1 = arg.Elements[1].Value
})
.ToList();
I've managed to solve this by using this solution with Service Account with oAuth2.0
Accessing older GData APIs (Spreadsheet API) using OAuth 2 and a service account
The solution:
1. Create Project and Google Service Account in https://console.developers.google.com/project
Generate your p12 key.
Allow APIs in Developer console you want to use (basically we are going to use old API, so you can skip this step, but just in case)
Use the code below (.NET Framework 4.5!)
Also don't forget to grant "youraccount#developer.gserviceaccount.com" access to your spreadsheet document as you grant permissions for usual users by pressing Share.
Code:
using System.Security.Cryptography.X509Certificates;
using Google.GData.Client;
using Google.GData.Extensions;
using Google.GData.Spreadsheets;
using Google.Apis.Auth.OAuth2;
string keyFilePath = #"C:\key.p12"; // found in developer console
string serviceAccountEmail = "youraccount#developer.gserviceaccount.com"; // found in developer console
var certificate = new X509Certificate2(keyFilePath, "notasecret", X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(serviceAccountEmail) //create credential using certificate
{
Scopes = new[] { "https://spreadsheets.google.com/feeds/" } //this scopr is for spreadsheets, check google scope FAQ for others
}.FromCertificate(certificate));
credential.RequestAccessTokenAsync(System.Threading.CancellationToken.None).Wait(); //request token
var requestFactory = new GDataRequestFactory("Some Name");
requestFactory.CustomHeaders.Add(string.Format("Authorization: Bearer {0}", credential.Token.AccessToken));
SpreadsheetsService myService = new SpreadsheetsService("You App Name"); //create your old service
myService.RequestFactory = requestFactory; //add new request factory to your old service
SpreadsheetQuery query = new SpreadsheetQuery(); //do the job as you done it before
SpreadsheetFeed feed = myService.Query(query);
Alright, I figured it out. Step by step instructions as follows - also see the code I provided below. FYI, this runs in .Net 3.5 and unlike the solution offered previously there are no new dependencies. You should be up and running in no time.
If you haven't yet create your OAuth 2.0 credentials - I assume you already know how to get those but here:
a) Log into your Google developer console: http://console.developers.google.com
b) Create a project
c) Create your credentials - use 'installed application'
d) add the APIs that you need - I think Drive API is definitely required. I also added Drive SDK just in case.
Copy the code below into VS and edit the first Main() method with your client key and secret key.
Run the app and copy both the new access token and the refresh token. Put those and your remaining credentials into the second Main() method below.
You now should be able to run the second Main() method (just reverse the naming). From now on that will be all you need - there is no need to re-run the first Main() method.
BTW, the first Main() method below was found here: https://developers.google.com/google-apps/spreadsheets/authorize
I did however add the missing token type as well the access type. Those are needed, so use the code below:
using System;
using Google.GData.Client;
using Google.GData.Spreadsheets;
using Google.GData.Documents;
using System.Configuration;
using System.Collections.Specialized;
namespace GoogleSpreadsheet
{
class GoogleOAutho2
{
private static String folderName = "crazy.ivan";
static void Main(string[] args)
{
////////////////////////////////////////////////////////////////////////////
// STEP 1: Configure how to perform OAuth 2.0
////////////////////////////////////////////////////////////////////////////
// TODO: Update the following information with that obtained from
// https://code.google.com/apis/console. After registering
// your application, these will be provided for you.
string CLIENT_ID = "your_client_id";
// This is the OAuth 2.0 Client Secret retrieved
// above. Be sure to store this value securely. Leaking this
// value would enable others to act on behalf of your application!
string CLIENT_SECRET = "your_secret_key"
// Space separated list of scopes for which to request access.
string SCOPE = "https://www.googleapis.com/auth/drive https://spreadsheets.google.com/feeds https://docs.google.com/feeds";
// This is the Redirect URI for installed applications.
// If you are building a web application, you have to set your
// Redirect URI at https://code.google.com/apis/console.
string REDIRECT_URI = "urn:ietf:wg:oauth:2.0:oob";
string TOKEN_TYPE = "refresh";
////////////////////////////////////////////////////////////////////////////
// STEP 2: Set up the OAuth 2.0 object
////////////////////////////////////////////////////////////////////////////
// OAuth2Parameters holds all the parameters related to OAuth 2.0.
OAuth2Parameters parameters = new OAuth2Parameters();
// Set your OAuth 2.0 Client Id (which you can register at
// https://code.google.com/apis/console).
parameters.ClientId = CLIENT_ID;
// Set your OAuth 2.0 Client Secret, which can be obtained at
// https://code.google.com/apis/console.
parameters.ClientSecret = CLIENT_SECRET;
// Set your Redirect URI, which can be registered at
// https://code.google.com/apis/console.
parameters.RedirectUri = REDIRECT_URI;
////////////////////////////////////////////////////////////////////////////
// STEP 3: Get the Authorization URL
////////////////////////////////////////////////////////////////////////////
// Set the scope for this particular service.
parameters.Scope = SCOPE;
parameters.AccessType = "offline"; // IMPORTANT and was missing in the original
parameters.TokenType = TOKEN_TYPE; // IMPORTANT and was missing in the original
// Get the authorization url. The user of your application must visit
// this url in order to authorize with Google. If you are building a
// browser-based application, you can redirect the user to the authorization
// url.
string authorizationUrl = OAuthUtil.CreateOAuth2AuthorizationUrl(parameters);
Console.WriteLine(authorizationUrl);
Console.WriteLine("Please visit the URL above to authorize your OAuth "
+ "request token. Once that is complete, type in your access code to "
+ "continue...");
parameters.AccessCode = Console.ReadLine();
////////////////////////////////////////////////////////////////////////////
// STEP 4: Get the Access Token
////////////////////////////////////////////////////////////////////////////
// Once the user authorizes with Google, the request token can be exchanged
// for a long-lived access token. If you are building a browser-based
// application, you should parse the incoming request token from the url and
// set it in OAuthParameters before calling GetAccessToken().
OAuthUtil.GetAccessToken(parameters);
string accessToken = parameters.AccessToken;
string refreshToken = parameters.RefreshToken;
Console.WriteLine("OAuth Access Token: " + accessToken + "\n");
Console.WriteLine("OAuth Refresh Token: " + refreshToken + "\n");
////////////////////////////////////////////////////////////////////////////
// STEP 5: Make an OAuth authorized request to Google
////////////////////////////////////////////////////////////////////////////
// Initialize the variables needed to make the request
GOAuth2RequestFactory requestFactory =
new GOAuth2RequestFactory(null, "MySpreadsheetIntegration-v1", parameters);
SpreadsheetsService service = new SpreadsheetsService("MySpreadsheetIntegration-v1");
service.RequestFactory = requestFactory;
// Make the request to Google
// See other portions of this guide for code to put here...
// Instantiate a SpreadsheetQuery object to retrieve spreadsheets.
Google.GData.Spreadsheets.SpreadsheetQuery query = new Google.GData.Spreadsheets.SpreadsheetQuery();
// Make a request to the API and get all spreadsheets.
SpreadsheetFeed feed = service.Query(query);
// Iterate through all of the spreadsheets returned
foreach (SpreadsheetEntry entry in feed.Entries)
{
// Print the title of this spreadsheet to the screen
Console.WriteLine(entry.Title.Text);
}
Console.ReadLine();
}
// once you copied your access and refresh tokens
// then you can run this method directly from now on...
static void MainX(string[] args)
{
GOAuth2RequestFactory requestFactory = RefreshAuthenticate();
SpreadsheetsService service = new SpreadsheetsService("MySpreadsheetIntegration-v1");
service.RequestFactory = requestFactory;
// Instantiate a SpreadsheetQuery object to retrieve spreadsheets.
Google.GData.Spreadsheets.SpreadsheetQuery query = new Google.GData.Spreadsheets.SpreadsheetQuery();
// Make a request to the API and get all spreadsheets.
SpreadsheetFeed feed = service.Query(query);
// Iterate through all of the spreadsheets returned
foreach (SpreadsheetEntry entry in feed.Entries)
{
// Print the title of this spreadsheet to the screen
Console.WriteLine(entry.Title.Text);
}
Console.ReadLine();
public static GOAuth2RequestFactory RefreshAuthenticate() {
OAuth2Parameters parameters = new OAuth2Parameters(){
RefreshToken = "the_refresh_token_you_copied_from_the_CLI_running_the_first_method";
AccessToken = "the_access_token_you_copied_from_the_CLI_running_the_first_method";
ClientId = "your_client_id";
ClientSecret = "your_dirty_little_secret";
Scope = "https://www.googleapis.com/auth/drive https://spreadsheets.google.com/feeds",
AccessType = "offline",
TokenType = "refresh"
};
string authUrl = OAuthUtil.CreateOAuth2AuthorizationUrl(parameters);
return new GOAuth2RequestFactory(null, "evilspeculator", parameters);
}
}
}
Hope that works for you guys - best of luck!
Andrew I was wondering how you got the google.apis.auth.oauth2 dll. Im trying to impliment your fix and I cant find the correct way to install the library.
I feel like I may be able to get this to work after I have that part.
Scenario: I want to get user access token of the fb page admin by JS login and retrieving token ONE TIME, and will store that in database. Then daily, I want to do wall post to those page.
I am using JS to get the initial token and storing it. Then using c# FacebookSDK for the web requests.
FB.login(function (response) {
var r = response;
// get access token of the user and update in database
$("#FacebookAccessToken").val(response.authResponse.accessToken);
},
{
scope: 'manage_pages,publish_stream'
});
Now I am saving this token in database as I will be using this for future graph calls - is this right?
On server side when I need to do a post after a day I retrieve that token and do the processing as below:
// step 1 get application access token
var fb1 = new FacebookClient();
dynamic appTokenCLient = fb1.Get("oauth/access_token", new
{
client_id = appId,
client_secret = appSecret,
grant_type = "client_credentials",
scope = "manage_pages,publish_stream",
redirect_uri = siteUrl
});
var fbTokenSettingVal = GetTokenFromDB(); // getting access token from database which was stored during JS fb login
// step 2 extend token
var fb2 = new FacebookClient(appTokenCLient.access_token);
dynamic extendedToken = fb2.Get("oauth/access_token", new
{
client_id = appId,
client_secret = appSecret,
grant_type = "fb_exchange_token",
fb_exchange_token = fbTokenSettingVal.Val
});
var userExtendedToken = extendedToken.access_token; // get extended token and update database
// step 3 get page access token from the pages, that the user manages
var fb3 = new FacebookClient { AppId = appId, AppSecret = appSecret, AccessToken = userExtendedToken };
var fbParams = new Dictionary<string, object>();
var publishedResponse = fb3.Get("/me/accounts", fbParams) as JsonObject;
var data = JArray.Parse(publishedResponse["data"].ToString());
var pageToken = "";
foreach (var account in data)
{
if (account["name"].ToString().ToLower().Equals("PAGE_NAME"))
{
pageToken = account["access_token"].ToString();
break;
}
}
// step 4 post a link to the page - throws error !
var fb4 = new FacebookClient(pageToken);
fb4.Post("/PAGE_NAME/feed",
new
{
link = "http://www.stackoverflow.com"
});
The last 4th step throws error, when posting to selected page:
The user hasn't authorized the application to perform this action
Have tried several different ways, but in vain. Assume that there is just a simple step which I am doing wrong here.
Also, is it ok to extend the fb access token for user every time before making request?
Any way to check if token is expired or not?
If you want to use that access token for future. You need to take offline_access token and that token you need to store in database.
This offline accesstoken will be expire once user will change the password or delete your application from facebook account.
private void GetPermenentAccessTokenOfUser(string accessToken)
{
var client2 = new FacebookClient(accessToken);
//get permenent access token
dynamic result = client2.Post("oauth/access_token", new
{
client_id = _apiKey,
client_secret = _apiSecret,
grant_type = "fb_exchange_token",
fb_exchange_token = accessToken
});
_accessToken = result.access_token;
}
Looks like for new apps we need to apply for manage_pages permission from our application:
which I am doing now. As it shows error when doing login:
Also, the app needs to be live, so they can reproduce this permission and verify that we do need this permission to post to pages. Its good for fb users safety but a time taking process for developers.
Any way this can be skipped for testing purpose?
I'm trying to create desktop application which will allow to list files and folders on google drive account. On this momment I'm able to do it but there is a one issue. I have to re-login each time I want to open google drive account from my application. Is it possible to use stored locally AccessToken/Refresh tokens in order to avoid re-authorization each time?
Here method which is used to get authorization.
private IAuthorizationState GetAuthorization(NativeApplicationClient arg)
{
IAuthorizationState state = new AuthorizationState(new[] { "https://www.googleapis.com/auth/drive.file", "https://www.googleapis.com/auth/drive", "https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile" });
// Get the auth URL:
state.Callback = new Uri("urn:ietf:wg:oauth:2.0:oob");
UriBuilder builder = new UriBuilder(arg.RequestUserAuthorization(state));
NameValueCollection queryParameters = HttpUtility.ParseQueryString(builder.Query);
queryParameters.Set("access_type", "offline");
queryParameters.Set("approval_prompt", "force");
queryParameters.Set("user_id", email);
builder.Query = queryParameters.ToString();
//Dialog window wich returns authcode
GoogleWebBrowserAuthenticator a = new GooogleWebBrowserAuthenticator(builder.Uri.ToString());
a.ShowDialog();
//Request authorization from the user (by opening a browser window):
string authCode = a.authCode;
// Retrieve the access token by using the authorization code:
return arg.ProcessUserAuthorization(authCode, state);
}
SOLVED:
In order to invoke methods from Google Drive sdk first you need to instance of service:
var provider = new NativeApplicationClient(GoogleAuthenticationServer.Description, GoogleDriveHelper.CLIENT_ID, GoogleDriveHelper.CLIENT_SECRET);
var auth = new OAuth2Authenticator<NativeApplicationClient>(provider, GetAuthorization);
Service = new DriveService(auth);
Those CLIENT_ID and CLIENT_SECRET you will have after you sign up for application in Google API console.
Then you need to define GetAuthorization routine, which might look as following:
private IAuthorizationState GetAuthorization(NativeApplicationClient arg)
{
IAuthorizationState state = new AuthorizationState(new[] { "https://www.googleapis.com/auth/drive.file", "https://www.googleapis.com/auth/drive", "https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile" });
state.Callback = new Uri("urn:ietf:wg:oauth:2.0:oob");
state.RefreshToken = AccountInfo.RefreshToken;
state.AccessToken = AccountInfo.AccessToken;
arg.RefreshToken(state);
return state;
}
It will works if you already have Refresh and Access tokens (at least Refresh). So you need to authorize for some user account first.
Then you can use that Service instance to invoke sdk methods.
Hope it will help someone.