Are you trying to connect to one of the Google APIs Using C#? Are you trying to do this in .net framework 3.5 – 2.0? In this post I will be showing you how to authenticate to Google API, as an example we will be email and google plus profile as example. If you can use .net framework 4.0 or 4.5 I strongly recommend that you use the Google .net client library using the client library is much easier. This is doing it the hard way in my opinion. I have a sample project on GitHub to go along with this tutorial feel free to download it to follow along GoogleAuthSimple
There are several reasons why I’m not going to use the dlls.
- To understand how Open Authentication works it helps to see the Pure code. See how it works instead of relying on a third party dll.
- If you are planing on referencing Google’s open Auth dll into your own dll it wont work because inst currently strong named. (They should be soon)
- I personally like to limit the number of 3rd party dll’s I use in my projects.
Creating the Form
Lets get started. I am going to assume here that you have created a project in Google APIs console if you haven’t I have a previous post you can read on how to do it: Googles APIs Console
The first thing we need to do is create a windows form application. Create two forms one with a button on it and one with a web-browser control.
AuthResponse
AuthResponse is a class I have created that contains all the methods we need to authenticate. You should copy it now the rest of the tutorial will be using methods directly from it.
using System; using System.Collections.Generic; using System.Text; using Newtonsoft.Json; using System.Net; using System.IO; namespace GoogleAuthWinForm { public class AuthResponse { private string access_token; public string Access_token { get { // Access token lasts an hour if its expired we get a new one. if (DateTime.Now.Subtract(created).Hours > 1) { refresh(); } return access_token; } set { access_token = value; } } public string refresh_token { get; set; } public string clientId { get; set; } public string secret { get; set; } public string expires_in { get; set; } public DateTime created { get; set; } ////// Parse the json response /// // "{\n \"access_token\" : \"ya29.kwFUj-la2lATSkrqFlJXBqQjCIZiTg51GYpKt8Me8AJO5JWf0Sx6-0ZWmTpxJjrBrxNS_JzVw969LA\",\n \"token_type\" : \"Bearer\",\n \"expires_in\" : 3600,\n \"refresh_token\" : \"1/ejoPJIyBAhPHRXQ7pHLxJX2VfDBRz29hqS_i5DuC1cQ\"\n}" /// /// ///public static AuthResponse get(string response) { AuthResponse result = JsonConvert.DeserializeObject (response); result.created = DateTime.Now; // DateTime.Now.Add(new TimeSpan(-2, 0, 0)); //For testing force refresh. return result; } public void refresh() { var request = (HttpWebRequest)WebRequest.Create("https://accounts.google.com/o/oauth2/token"); string postData = string.Format("client_id={0}&client_secret={1}&refresh_token={2}&grant_type=refresh_token", this.clientId, this.secret, this.refresh_token); var data = Encoding.ASCII.GetBytes(postData); request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; request.ContentLength = data.Length; using (var stream = request.GetRequestStream()) { stream.Write(data, 0, data.Length); } var response = (HttpWebResponse)request.GetResponse(); var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd(); var refreshResponse = AuthResponse.get(responseString); this.access_token = refreshResponse.access_token; this.created = DateTime.Now; } public static AuthResponse Exchange(string authCode, string clientid, string secret, string redirectURI) { var request = (HttpWebRequest)WebRequest.Create("https://accounts.google.com/o/oauth2/token"); string postData = string.Format("code={0}&client_id={1}&client_secret={2}&redirect_uri={3}&grant_type=authorization_code", authCode, clientid, secret, redirectURI); var data = Encoding.ASCII.GetBytes(postData); request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; request.ContentLength = data.Length; using (var stream = request.GetRequestStream()) { stream.Write(data, 0, data.Length); } var response = (HttpWebResponse)request.GetResponse(); var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd(); var x = AuthResponse.get(responseString); x.clientId = clientid; x.secret = secret; return x; } public static Uri GetAutenticationURI(string clientId, string redirectUri) { string scopes = "https://www.googleapis.com/auth/plus.login email"; if (string.IsNullOrEmpty(redirectUri)) { redirectUri = "urn:ietf:wg:oauth:2.0:oob"; } string oauth = string.Format("https://accounts.google.com/o/oauth2/auth?client_id={0}&redirect_uri={1}&scope={2}&response_type=code", clientId, redirectUri, scopes); return new Uri(oauth); } } }
Add this class to visual studio will allow you to run the rest of the tutorial.
[wp_ad_camp_3]
Request user access.
In order for this to work you need to have first register your application in Googles APIs Console. Under API Access you should have something like this.
In order to display the Authentication request to the user you must first have the Uri to put into your web browser control. note &response_type=code
public static Uri GetAutenticationURI(string clientId, string redirectUri) { // separate more then one scope with a space string scopes = "https://www.googleapis.com/auth/plus.login email"; if (string.IsNullOrEmpty(redirectUri)) { redirectUri = "urn:ietf:wg:oauth:2.0:oob"; } string oauth = string.Format("https://accounts.google.com/o/oauth2/auth?client_id={0}&redirect_uri={1}&scope={2}&response_type=code", clientId, redirectUri, scopes); return new Uri(oauth); }
This first request is just a simple HTTP GET. A HTTP GET requests a representation of the specified resource. Requests using GET should only retrieve data and should have no other effect. With Visual Stuido C# and as far back as .net 2.0 we can also do HTTP GET just by using System.Net.
- {ClientID} – This is the Id that identifies your application to Google. Its the id that was created for you in the Google Apis Console.
- {Redirect URI} – This tells the server where to send the authorization code to. Put urn:ietf:wg:oauth:2.0:oob there and it will redirect to the current browser window and its title.
- {Scope} – This is what API you are requesting access to. When you registered your project you checked off which API’s you will be using in the services tab. Each API has one or more Scope. For Google+ its https://www.googleapis.com/auth/plus.login and for email its just “email” you can add more then one by separating them with a space. Check the API you will be using to find out which Scope you need to access the data you are looking for.
- Response_type=code – This just tells them you want an authorization code back.
If you debug the code you will see that oauth now looks like this :
https://accounts.google.com/o/oauth2/auth?client_id=XXXX-d0vpdthl4ms0soutcrpe036ckqn7rfpn.apps.googleusercontent.com&redirect_uri=urn:ietf:wg:oauth:2.0:oob&scope=https://www.googleapis.com/auth/plus.login email&response_type=code"
You can place that string into any web browser and it will work.
I like to call the method like this
webBrowser1.Navigate(AuthResponse.GetAutenticationURI(clientId, redirectURI));
When the web browser:.
Authentication
Now we are asking the User if they want to give you access to there data. Lets assume they clicked “Accept”.
There are three types of codes you need to be aware of with Open Autentication.
- Authentication code – This is the code that is returned to you when the user gives you access. You only need this once its used to get a refreshtoken.
- Refresh token – This is the only thing you need to remember for next time. You need to save this in your application so that when the user starts your program again they wont need to re-Authenticate. With a refresh token you can request a new access token.
- Access token – This is the main token you need. When ever you send a request you must send this along with the request. Access tokens have a life of about an hour so you need to check if its expired or not. By checking the Expire time. We will look into that later.
Finding the Authentication Code
[wp_ad_camp_3]
The Authentication code is returned to us in Visual Studio web-browser control in both in the body of the page when it reloads as well as in the title. I recommend that you read it from the body. I have had some issues with not getting the complete code out of the title. I don’t know if it was because it was to long or if its because the code has special characters in it. I just know on a several occasions I have had issues with it so I always read from the body.
////// The authentication code is returned in the webbrowser. /// /// /// private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { string Mytitle = ((WebBrowser)sender).DocumentTitle.ToLower(); if (Mytitle.IndexOf("success code=") > -1) { webBrowser1.Visible = false; // searching the body for our code string AuthCode = webBrowser1.DocumentTitle.Replace("Success code=", ""); string webText = ((WebBrowser)sender).DocumentText; int start = webText.IndexOf("id=\"code\""); start = webText.IndexOf(AuthCode, start); int end = webText.IndexOf('"', start); string authCode = webText.Substring(start, end - start); //Exchange the code for Access token and refreshtoken. access = AuthResponse.Exchange(authCode, clientId, clientSecret, redirectURI); processAccess(); } }
I am sure some C# guru can come up with a nice Regex match to find the code for us. I use this because its simple and it works and it doesn’t require that I include regex into my project. AuthCode now contains the authentication code, we will use the authentication code to get a refresh token.
Exchanging the Authentication Code
Now we have an Authentication code but what we need is an Access token and a refresh token. This time we will be doing a HTTP POST, a HTTP Post can also be done with visual studio as far back as .net framework 2.0. What we want to do is send some information to the server this time.
The authentication code, the client id , the client secret and the redirect uri. note grant_type=authorization_code
Once we have done this the server will return to us an Access token which we can use to make requests against the api and a refresh token. Access tokens are only good for about an hour so we will we need to get a new one we use the refresh token to get a new access token.
public static AuthResponse Exchange(string authCode, string clientid, string secret, string redirectURI) { var request = (HttpWebRequest)WebRequest.Create("https://accounts.google.com/o/oauth2/token"); string postData = string.Format("code={0}&client_id={1}&client_secret={2}&redirect_uri={3}&grant_type=authorization_code", authCode, clientid, secret, redirectURI); var data = Encoding.ASCII.GetBytes(postData); request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; request.ContentLength = data.Length; using (var stream = request.GetRequestStream()) { stream.Write(data, 0, data.Length); } var response = (HttpWebResponse)request.GetResponse(); var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd(); var x = AuthResponse.get(responseString); x.clientId = clientid; x.secret = secret; return x; }
You should now have an access token and a refresh token that you can use for all future request against the Google APIs.
Using the refresh token
When your Access token has expired you need to request a new one. For that you use the refreshToken. Note grant_type=refresh_token
public void refresh() { var request = (HttpWebRequest)WebRequest.Create("https://accounts.google.com/o/oauth2/token"); string postData = string.Format("client_id={0}&client_secret={1}&refresh_token={2}&grant_type=refresh_token", this.clientId, this.secret, this.refresh_token); var data = Encoding.ASCII.GetBytes(postData); request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; request.ContentLength = data.Length; using (var stream = request.GetRequestStream()) { stream.Write(data, 0, data.Length); } var response = (HttpWebResponse)request.GetResponse(); var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd(); var refreshResponse = AuthResponse.get(responseString); this.access_token = refreshResponse.access_token; this.created = DateTime.Now; }
Conclusion
As you can see it is possible to gain access to Google APIs without using the client library. Its not really that hard you just have to know what calls to make. Once you have the access token you can then make any request against the API you wish by simply adding the key to the end of the request url. I have uploaded a sample project for this to GitHub that should get you started.
Hello
Thanks for the codes, that can be used to authorize for any Google service.
But how can we instantiate a Google Drive Service, client using above approach.
Thanks
Please reply soon.
hi
I am looking sample code that help me to extract google Task item using email address and create task. I could not find any tutorial and sample code. i used to google Task API but able to create task
I don’t have any tutorials yet for Google Task API but i don’t think you are going to get it to work with an email address. You need to use Oauth2, Google doesn’t like client login anymore.
Hello. Very good explanation on how to connect Google using OAuth. Although Google itself provides an OAuth API, which does the same thing. But I prefer the method you explained here because I want to be in control of the web browser window. Google OAuth Api uses the default web browser on the computer. I’ve had trouble catching situations where user closes the browser window instead of accepting or rejecting userconsent. That’s why with my own webbrowser I am able to catch this.
Now next step is to inject the access token in the DriveService for using Google Drive SDK. The most familiar code is this:
drvservice = New DriveService(New BaseClientService.Initializer() With {.HttpClientInitializer = credential, .ApplicationName = “app”})
How do I use the access token received from your article and apply it on the DriveService so I can access the user’s Drive account.
What you are talking about would be merging non client lib code with client lib code. If your not going to use Googles Client lib to create the Oauth code then i think you are going to have problems using the client lib. I will look into it you might be able to create the credential object manually in the client lib but I’m not sure.
Could you share a SampleProject for everybody , because i’m a beginner for Google API , i don’t know how to use those introduction to create a usable WinForms Application even i try it that i failed , so if you can share example for me , i should be glad for your sharing.
I have been slowly going though my tutorials and adding sample projects up on GitHub, I will add this one to my list. I am not sure which API you are using, but https://github.com/LindaLawton/Google-Analytics-Management-API.Net might help, it uses the Google-dot-net-client lib and is much easier to understand then doing things manually.
Where the POST function come from?
//Posting the Data to Google
string response = Post(“https://accounts.google.com/o/oauth2/token”, postData);
post is a method in the tutorial public static string Post(string _Url, List _PostData) {
Thank you! I read over it 😉
In the code:
//Posting the Data to Google
string response = Post(Properties.Resource.TokenEndpoint, postData);
Where Properties come from?
Maybe my question must be: What is contain in TokenEndpoint? An URL?
Hello, Linda. Congratulations for your code and website, it’s literally saving my life! Hahaha
Well, I have a question about your code. What does that line means:
GoogleAnalyticsWin.MainForm._MainUIForm.SetAutentication(myAutentication);
?
That’s not working in my application
What am I doing wrong?
Please help me!
Ok you are the second one to have found this tutorial. I think its time to do an update on it. Because i seriously have no idea 🙂
string response = Post(Properties.Resource.TokenEndpoint, postData);
Getting Error in this line..What is Properties.Resource.TokenEndpoin means
plz reply
This tutorial is really old. I am really not that sure, I will add it to my list of Clean up tutorials. If you can’t use the Google .net client lib feel free to email me and i will see if i cant find the source code for this tutorial someplace.
i am uploading the youtube video in .net using oauth 2.0 but while deploying into IIS its not able to authenticate. is there any specific configuration is required while deploying the application.
there shouldn’t be. The only thing i can think of is if you are still using filedatastore that IIS may not have access to write to %appdata%
Thanks for your reply.
i am using the below code for the authentication.
var stream = new FileStream(clientSecretFilePath, FileMode.Open, FileAccess.Read);
{
if (scope == YouTubeScope.ReadOnly)
{
credentials = await GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
new[] { YouTubeService.Scope.YoutubeReadonly },
“user”,
CancellationToken.None,
new FileDataStore(Assembly.GetExecutingAssembly().GetName().Name)
);
}
else
{
credentials = await GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
new[] { YouTubeService.Scope.YoutubeUpload },
“user”,
CancellationToken.None
);
}
After running this code its not able to authorized to the Google from IIS. Is there any other way to use this authentication or any configuration we can do in IIS. Same code if i am running using Visual Studio its working properly.
i have given same window credential in IIS App pool. Is there any other changes are required or do I need to change the code?
I would make sure that IIS has access to clientSecretFilePath
IIS has access of clientSecretFilePath. i found while remote debugging that it hangs over at the below mehod.
await GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
new[] { YouTubeService.Scope.YoutubeReadonly },
“user”,
CancellationToken.None,
new FileDataStore(Assembly.GetExecutingAssembly().GetName().Name)
);
Well there is your problem. You cant use a service account with the YouTube API. YouTube API only supports OAuth2 authentication.
But the same code works if its running from the code in visual studio. once i deploy in IIS then only its not working.
Never mind that. This isn’t the best place to do debugging of code. You should post your question to http://stackoverflow.com/ tag it google-api-dotnet-client and youtube-api. Comments on this site just doesn’t work for asking questions not related to the tutorial in question.
i am using the below code for the authentication.
var stream = new FileStream(clientSecretFilePath, FileMode.Open, FileAccess.Read);
{
if (scope == YouTubeScope.ReadOnly)
{
credentials = await GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
new[] { YouTubeService.Scope.YoutubeReadonly },
“user”,
CancellationToken.None,
new FileDataStore(Assembly.GetExecutingAssembly().GetName().Name)
);
}
else
{
credentials = await GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
new[] { YouTubeService.Scope.YoutubeUpload },
“user”,
CancellationToken.None
);
}
After running this code its not able to authorized to the Google from IIS. Is there any other way to use this authentication or any configuration we can do in IIS. Same code if i am running using Visual Studio its working properly.
i have given same window credential in IIS App pool. Is there any other changes are required or do I need to change the code?
Make sure that IIS has access to read your clientSecretFilePath.
Hi Linda,
I have a doubt regarding the above sample code given by you.
1) Where we have to declare this “myAutentication” variable?
2) In “wbAuthenticate_DocumentCompleted” function
if (myAutentication.ErrorMessage.Length > 0)
what is “>” meant for ?
3) And in the same method
else if (Mytitle.IndexOf(“denied error=”) > -1)
{
// the user declined access. Show them the URL again
wbAuthenticate.Url = GetAutenticationURI(myAutentication);
}
Where is this “GetAutenticationURI” located in?
Please provide me the sample project for web browser control,windows App using c# if possible …
Thank You for your Guidance… 🙂
This tutorial was very old, I have updated it and added a sample project on Github. I hope the update clears up your issues.
Hi Linda, i am using code provided by youtube api v3 to upload video. this is my code to get authentication
UserCredential credential;
using (var stream = new FileStream(jsonFileName, FileMode.Open, FileAccess.Read))
{
credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets, new[] { YouTubeService.Scope.YoutubeUpload },
“user”,
CancellationToken.None
);
}
This is work well when i use visual studio, but when i host this on IIS i am getting error ”access to the path ‘google.apis.auth’ is denied”
i am not able to fix this error, i have set all the permission to folder.
Make sure you have Googles dlls either in GAC or have them in the directory with your code. Sounds like you are missing them.
Really Useful, i’m trying to access Google APi using my own Embed Webbrowser, but i need to access Youtube API. Can you help me get “Uri GetAutenticationURI(string clientId, string redirectUri)” for Youtube API
Here is a tutorial about how to get access to Google using Oauth2 Google 3-Legged Oauth flow hope it helps
Hi Linda,
I try to run the Google Auth Simlple example in my computer but It does not return the values in Access Form. It stops at the Auth Form and nothing else after I click Accept. I could not find out where the errors were. Help me plz….
Hi Linda,
I found this very useful because I don’t need to worry about browser close event. But I was wondering how can I further continue to download/upload files from Google Drive. Because all the examples I have seen over the internet is based on DriveService and as pointed out I should not be using the same. Can you help me out with a function/example that further uses the access token to upload a file in google drive. It will be very helpful. Thanks Again.
Regards,
Amrut
Hello Linda,
First of all, thank you for your article. Very great work. Thank you very much!
I download your example at Github, however I am getting an error. I dont know why after I approve the authentication at the Auth Form, I get an error at line ” int end = webText.IndexOf(‘”‘, start); ” within the method webBrowser1_DocumentCompleted(). It seems that start has a value -1. It get the value -1 at “start = webText.IndexOf(AuthCode, start);” Before, start has another value. Has google changed the format of the authorization code? I dont know if the format (“id=\”code\””) is not working anymore.
Any idea?
Thank you very much in advance
Yes that code is really old they may have changed it. I changed my application a while ago to read from document.title I think. There was also something about it doing a double load if i remember you need to be sure that the document complete was the correct one. Its been a while i will have to dig around in some code.
Hello
Thanks for the code. How can i get user email after authentification ?
which API are you using?
how to upload in google drive use this app
You should check out the upload tutorial Google Drive api upload
Hi Linda,
I have a problem in Drive api integration in my asp.net mvc application. I wrote all the code and user are able to do all functionality related to google drive. But In my project all user can perform any operation without login because they don’t know my Userid or password. but right now they need my gmail uid and password before doing any operation.
Below is my all code.
I am waiting for your reply
Thanks
If you are only going to be accessing the one account then you should be using a service account. Oauth2 is for gaining access to others accounts not a single one. This article may help you Google developer console service account
If you have any issues i recommend posting your code on stack overflow that was to much code for this forum to support.
If you need any assistance i have a consulting service you can contact me here
Hi,
Thank you for the code, I am using this code to get the access token and using that access token I am trying to create a VIrtual Machine on google cloud. While creating Virtual Machine I have an Unauthorized exception(401)exception
I am using c# language.
Could you please help me to resolve this issue.
Thank you
Sorry i dont have much experience with Google cloud you may want to try asking on stackoverflow.com
Hi linda, can you teach how to do this in WPF. It would be much appreciated.
I dont know of any WPF examples for the .net client library sorry. But you should be using a native client so that should get you started.
Thanks for reply. Its Okay though. In addition it is office work and i see this sample so maybe i can work something out of it. I wonder u can hep me to build WPF interface and get user information from this sample. https://github.com/google/google-api-dotnet-client-samples/tree/master/Tasks.WPF.ListTasks. Hope hear from u soon…
Hi Linda, what about WCF service. can you do tutorial on this one to fetch image, user profile, etc in google account. because its a new task for me.
Linda regarding my previous comment. Because there is none topic or discussion how to do this yet in my research. i wish u could help me develop a wcf service which is capable of listening to the request from other application and provides the necessary information of google plus account. This service will serve or send the data in XML with basic details from google plus like displayName, id, profile url, image url etc.
I offer a [consulting](https://www.daimto.com/consulting-service/) service if your interested. I am not the best person to be writing tutorials on wcf sorry.
Thank you Sooooooooooooo much Linda.
This template class is really convenient and works very well 🙂
Your post saved my day <3
Hey there,
do you have an updated version for 2020?
ty
There should be no change that i am aware of.