Login Using Google Oauth 2.0 with C#

Login using Google OAuth 2.0 with C#

I am explaining based on Google+ API, which uses Gmail ID to login. So, you will be authenticating your users to login with Gmail.

1: You need to turn on the Google+ API:

Google+ API

2: Once you turned on the Google+ API, then you need to add new Client ID.

Create New Client ID

Step 2

Web Application Client ID

Step 3

Client ID, Secret & Redirect URL

Here in Step 2, when you add Redirect URL, you will need to add the URL of your website on which page you want user to redirected to.

Once you have created your Client ID for Web Application.

Then in your application, you need to add two packages

1: Newtonsoft.Json

Install-Package Newtonsoft.Json

2: Microsoft.Net.Http

Install-Package Microsoft.Net.Http

Now add this namespaces;

using Newtonsoft.Json;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

Now in code first your declare this variables at top of your page;

protected string googleplus_client_id = "458878619548-khuatamj3qpiccnsm4q6dbulf13jumva.apps.googleusercontent.com";    // Replace this with your Client ID
protected string googleplus_client_secret = "4hiVJYlomswRd_PV5lyNQlfN"; // Replace this with your Client Secret
protected string googleplus_redirect_url = "http://localhost:2443/Index.aspx"; // Replace this with your Redirect URL; Your Redirect URL from your developer.google application should match this URL.
protected string Parameters;

Then in you Page Load event;

protected void Page_Load(object sender, EventArgs e)
{
if ((Session.Contents.Count > 0) && (Session["loginWith"] != null) && (Session["loginWith"].ToString() == "google"))
{
try
{
var url = Request.Url.Query;
if (url != "")
{
string queryString = url.ToString();
char[] delimiterChars = { '=' };
string[] words = queryString.Split(delimiterChars);
string code = words[1];

if (code != null)
{
//get the access token
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("https://accounts.google.com/o/oauth2/token");
webRequest.Method = "POST";
Parameters = "code=" + code + "&client_id=" + googleplus_client_id + "&client_secret=" + googleplus_client_secret + "&redirect_uri=" + googleplus_redirect_url + "&grant_type=authorization_code";
byte[] byteArray = Encoding.UTF8.GetBytes(Parameters);
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.ContentLength = byteArray.Length;
Stream postStream = webRequest.GetRequestStream();
// Add the post data to the web request
postStream.Write(byteArray, 0, byteArray.Length);
postStream.Close();

WebResponse response = webRequest.GetResponse();
postStream = response.GetResponseStream();
StreamReader reader = new StreamReader(postStream);
string responseFromServer = reader.ReadToEnd();

GooglePlusAccessToken serStatus = JsonConvert.DeserializeObject<GooglePlusAccessToken>(responseFromServer);

if (serStatus != null)
{
string accessToken = string.Empty;
accessToken = serStatus.access_token;

if (!string.IsNullOrEmpty(accessToken))
{
// This is where you want to add the code if login is successful.
// getgoogleplususerdataSer(accessToken);
}
}

}
}
}
catch (Exception ex)
{
//throw new Exception(ex.Message, ex);
Response.Redirect("index.aspx");
}
}
}

Now the event that will call the google API

protected void Google_Click(object sender, EventArgs e)
{
var Googleurl = "https://accounts.google.com/o/oauth2/auth?response_type=code&redirect_uri=" + googleplus_redirect_url + "&scope=https://www.googleapis.com/auth/userinfo.email%20https://www.googleapis.com/auth/userinfo.profile&client_id=" + googleplus_client_id;
Session["loginWith"] = "google";
Response.Redirect(Googleurl);
}

Add this GooglePlusAccessToken class;

// Google
public class GooglePlusAccessToken
{
public string access_token { get; set; }
public string token_type { get; set; }
public int expires_in { get; set; }
public string id_token { get; set; }
public string refresh_token { get; set; }
}

Also you can call other oauth API with the Access Token to retrieve some of users information.

private async void getgoogleplususerdataSer(string access_token)
{
try
{
HttpClient client = new HttpClient();
var urlProfile = "https://www.googleapis.com/oauth2/v1/userinfo?access_token=" + access_token;

client.CancelPendingRequests();
HttpResponseMessage output = await client.GetAsync(urlProfile);

if (output.IsSuccessStatusCode)
{
string outputData = await output.Content.ReadAsStringAsync();
GoogleUserOutputData serStatus = JsonConvert.DeserializeObject<GoogleUserOutputData>(outputData);

if (serStatus != null)
{
// You will get the user information here.
}
}
}
catch (Exception ex)
{
//catching the exception
}
}

public class GoogleUserOutputData
{
public string id { get; set; }
public string name { get; set; }
public string given_name { get; set; }
public string email { get; set; }
public string picture { get; set; }
}

Hope this is what you were looking for, I implemented this and it is working just fine.
Hope this helps.

I need to do oauth2 authentication to access gmail in C#

First off the code you have Show apears to be that you are trying to use the Gmail api. This is not the smtp server.

Also you have included.

[GoogleScopedAuthorize(GmailService.ScopeConstants.GmailCompose)]

Which leads me to believe you are following the asp .net core configure-your-application-to-use-google.apis.auth.aspnetcore3 sample.

As such this is what it is designed to do. It will open the consent window on the users machine and request their permission to access their gmail account.

server side.

If you want to access a users gmail account server side then you will need to authorize them as you are already doing then store the refresh token that is returned. Then you will be able to use that from your server sided application to access the users gmail account with out them being present.

The key here is that you need the users consent before you can access their data.

Application email account

If what you are trying to do is access an account that you control and this is not an account of the users of your system then things will be more difficult for you.

Unless this is a google workspace domain email address you can not user service account authorization. If it is a workspace domain account then I suggest you look into that.

If its a normal standard google gmail account then you will need to authorize the user once. store the refresh token in your system some where and then use that to request an access token as needed. You can use the installed app examples for this. You will need to watch it if your refresh token ever goes down you will loose access. This solution is not optimal but it is the only option available.

Or you can try an apps password with the code you have now. Google has not been clear as to wither or not this will work.

How to get email address of a user using Google Oauth .NET library

Make sure that you have include the "email" scope as part of your scopes.

create a service object.

var service = new PeopleService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "Peopleservice Oauth2 Authentication Sample"
});

Then make a request to the people api.

var results = service.People.Get("person/me").ExecuteAsync();

Using OAuth2 to Authenticate with a Google API in C#

You have a couple of options.

Is this an account you have access to. If it is then you can use a service account. Service accounts are preauthorized the you take the service account email address and add it as a user in Google analytics admin at the account level and the service account will be able to access the account for as long as it is valid. No pop up window is required. I have some sample code on how to authenticate with a service account here

/// <summary>
/// Authenticating to Google using a Service account
/// Documentation: https://developers.google.com/accounts/docs/OAuth2#serviceaccount
/// </summary>
/// <param name="serviceAccountEmail">From Google Developer console https://console.developers.google.com</param>
/// <param name="serviceAccountCredentialFilePath">Location of the .p12 or Json Service account key file downloaded from Google Developer console https://console.developers.google.com</param>
/// <returns>AnalyticsService used to make requests against the Analytics API</returns>
public static AnalyticsReportingService AuthenticateServiceAccount(string serviceAccountEmail, string serviceAccountCredentialFilePath)
{
try
{
if (string.IsNullOrEmpty(serviceAccountCredentialFilePath))
throw new Exception("Path to the service account credentials file is required.");
if (!File.Exists(serviceAccountCredentialFilePath))
throw new Exception("The service account credentials file does not exist at: " + serviceAccountCredentialFilePath);
if (string.IsNullOrEmpty(serviceAccountEmail))
throw new Exception("ServiceAccountEmail is required.");

// These are the scopes of permissions you need. It is best to request only what you need and not all of them
string[] scopes = new string[] { AnalyticsReportingService.Scope.Analytics }; // View your Google Analytics data

// For Json file
if (Path.GetExtension(serviceAccountCredentialFilePath).ToLower() == ".json")
{
GoogleCredential credential;
using (var stream = new FileStream(serviceAccountCredentialFilePath, FileMode.Open, FileAccess.Read))
{
credential = GoogleCredential.FromStream(stream)
.CreateScoped(scopes);
}

// Create the Analytics service.
return new AnalyticsReportingService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "AnalyticsReporting Service account Authentication Sample",
});
}
else if (Path.GetExtension(serviceAccountCredentialFilePath).ToLower() == ".p12")
{ // If its a P12 file

var certificate = new X509Certificate2(serviceAccountCredentialFilePath, "notasecret", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
var credential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = scopes
}.FromCertificate(certificate));

// Create the AnalyticsReporting service.
return new AnalyticsReportingService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "AnalyticsReporting Authentication Sample",
});
}
else
{
throw new Exception("Unsupported Service accounts credentials.");
}

}
catch (Exception ex)
{
Console.WriteLine("Create service account AnalyticsReportingService failed" + ex.Message);
throw new Exception("CreateServiceAccountAnalyticsReportingFailed", ex);
}
}

If this isn't something you can do. Then you should be aware of the fact that filedatastore() by default stores your credentials in %appData% you could simply copy that file onto the new server along with the code.

You can also move the location to some were other then %appData% by using the following code:

new FileDataStore(@"c:\datastore",true)     

I have a tutorial on how filedatastore works. here File datastore demystified

Preauthorizing service account to Google Analytics. Admin section of the Google analytics website. Grant it read access should be more then enough.

Sample Image



Related Topics



Leave a reply



Submit