30

I want to allow User to login using Gmail. So, I googled and got many samples but all were using OpenID and as I have checked Google Documentation, they have stopped new domain registration for OpenID and from now, Developer will need to use OAuth API.

I have registered my Project and got Secrey KEY & Client ID. Now I want to integrate it my Project but I am unable to find any sample working Project.

Please help me regarding this. I am not using MVC.

computingfreak
  • 4,939
  • 1
  • 34
  • 51
Jeeten Parmar
  • 5,568
  • 15
  • 62
  • 111

3 Answers3

68

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.

Tim Pickin
  • 369
  • 4
  • 15
Vyas
  • 2,734
  • 18
  • 14
  • Thank you so much for your brief details. I will check it and If I get perfect data then I will mark your post as Answer. – Jeeten Parmar Jun 08 '14 at 05:14
  • Hey, I was getting some errors but finally I have solved it and got all data. Thank you again. :) – Jeeten Parmar Jun 08 '14 at 10:01
  • Where does GoogleUserOutputData come from? using Google.xxx? – Per G Oct 15 '14 at 07:21
  • I do not understand. What properties does GoogleUserOutputData have? – Per G Oct 15 '14 at 08:11
  • 2
    I have edited the answer, GoogleUserOutputData is a class to access the data that is returned by calling google api's... in our scenario, I have edited and shown the response that we get from calling the google api. – Vyas Oct 15 '14 at 08:40
  • 3
    Thank u. I had problems with async and void etc. Instead I used synced: WebClient client = new WebClient(); string downloadString = client.DownloadString(urlProfile); – Per G Oct 15 '14 at 08:54
  • @Vyas is it possible to pre-fill email id in google sign in page? – Alex Mathew Jan 13 '18 at 06:21
  • @AlexMathew Sorry for the late response, but try adding 'login_hint=abc@gmail.com' to Parameters variable... See if this helps. – Vyas Feb 27 '18 at 06:08
  • @Vyas thanks and sorry for late regards. Its pre-filling the section but sometimes if we have multiple account in logged in browser, its asking for account to choose.. Instead of that is it possible to select and move to password page? – Alex Mathew Apr 23 '18 at 10:20
  • Many thanks for this perfect complete and detailed example. I've got a functional implementation using .Net WebApi based on your tuto. so helpfull. Thanks a lot. – Fernando Jaconete Aug 30 '18 at 22:17
  • Top notch example, easy to convert to net core, thank you – s1cart3r Nov 05 '21 at 08:15
0

Based on Google lastest API for DotNet I have used below code which works for Console App, Web Form and Asp.Net MVC as well.

 public async Task<UserCredential> getUserCredential()
    {
        UserCredential credential;
        string[] scopes = new string[] {  }; // user basic profile

        //Read client id and client secret from Web config file

        credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
                   new ClientSecrets
                   {
                       ClientId = ConfigurationManager.AppSettings["ClientId"],
                       ClientSecret = ConfigurationManager.AppSettings["ClientSecret"]
                   }, scopes,
            "user", CancellationToken.None, new FileDataStore("Auth.Api.Store"));

        return credential;
    }

Here ClientId and ClientSecret stored in web.config file which can be modified later easily if requires.

anomepani
  • 1,796
  • 2
  • 25
  • 34
  • This returns error: _Failed to launch browser with "https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&response_type=code&client_id=xxx.apps.googleusercontent.com&redirect_uri=http%3A%2F%2F127.0.0.1%3A62006%2Fauthorize%2F&scope" for authorization. See inner exception for details._ And the inner exception: _Access denied_ . I've tried some options from my ASP.NET app (server side) but no luck. Google documentation sucks. – Fer R Mar 09 '18 at 17:02
  • 1
    http://www.dotnetexample.in/2018/02/login-using-google-api-with-c.html?m=1 Look into this if you miss any configuration – anomepani Mar 10 '18 at 18:15
  • Yep, all those steps I have followed with no luck. It seems like only works with IIS Express, but when I try with a site in IIS, the error appears, although all permissions are correct – Fer R Mar 12 '18 at 17:41
  • If you have client id or client secret in a file. Your application should have permission to that path so it can be read by an app while you are publishing to IIS. Check the Physical path is accessible for current user or IUSR by verifying using “Test Settings” for hosted site – anomepani Mar 13 '18 at 11:07
  • in the third parameter, what should be used to replace "user"? – Farooq Hanif Jun 06 '19 at 08:32
  • @FarooqHanif Here on SDK documentation, it says Users to Authorize, I didn't fully understand https://developers.google.com/api-client-library/dotnet/reference/1.9.3/classGoogle_1_1Apis_1_1Auth_1_1OAuth2_1_1GoogleWebAuthorizationBroker#a95045cb55eeb08fadd27b33e0193327c – anomepani Jun 07 '19 at 07:12
0

If you are using Asp.Net MVC or Asp.Net Core and you want some east setup for Google Login than you can try package Install-Package GoogleAuthentication -Version 1.0.0. This package help you in getting Google sign In data using three methods.

 public async Task<ActionResult> GoogleLoginCallback(string code)
    {
        try
        {
            var ClientSecret = "Enter Client Secret here";
            var ClientID = "Enter Client Id here";
            var url = "https://localhost:44375/Login/GoogleLoginCallback";
            var token = await GoogleAuth.GetAuthAccessToken(code, ClientID, ClientSecret, url);
            var userProfile = await GoogleAuth.GetProfileResponseAsync(token.AccessToken.ToString());
            var googleUser = JsonConvert.DeserializeObject<GoogleProfile>(userProfile);
           
        }
        catch (Exception ex)
        {
            
        }
        return RedirectToAction("index", "Users");
    }

You can check out the installation steps for this package and also all steps for getting clientId and Client Secret from Google Sign In using GoogleAuthentication Nuget Package in detailed steps and also with sample code provided

Shubham
  • 443
  • 2
  • 10