Use Google OAuth 2.0 for Web Applications In C#

In this article, we will learn how web applications use Google API or Google OAuth 2.0 endpoints to implement OAuth to use Google APIs.

When our application requires some permission on behalf of multiple users we need to implement OAuth authentication. Todo this we need to follow the below steps.

  1. First, create or log in with an account here.
  2. Create a project. You can find the create project option in the left top bar.
  3. Find and enable the API or service which you want to use.
  4. From the left panel click on Credentials.
    1. Click on the “+ Create Credentials” button from the top bar.
    2. Select OAuth Client ID.
    3. Select Application Type as a Web application.
    4. Give a proper name for OAuth 2.0 client.
    5. Add URI for Authorized JavaScript origins.
    6. Add URIs for Authorized redirect URIs.
    7. Click on Create button.

 

  1. Click on the OAuth consent screen from the left panel.
  2. Register your app with the required details.
    1. if your app Publishing status is Testing then you have to enter a test email and only those users will able to access the app.  in test mode we can add 100 users.
    2. If your app Publishing status is In production then all new emails will able to access your app.

  1. Now Download the JSON file (Client ID for Web application).

Create an empty or testing application that you want to authenticate and use Google Apis.

We will need the below Nuget packages.

  • Google.Apis
  • Google.Apis.Auth
  • Google.Apis.Auth.Mvc
  • Google.Apis.Core
  • Google.Apis.Drive.v2
  • Google.Apis.Drive.v3
  • Google.Apis.Oauth.v2

Now copy the JSON file which we downloaded from google console and give the proper name and paste it into your root project directory, here I’ll rename it as “client_secret.json”.

The below function will create Auth URL for google authentication, so we call this function for each user and it will return Auth URL and we need to redirect users on that generated URL.

public async Task<string> GetCredentialOrAuthUrl(string userName, CancellationToken cancellationToken)
        {
            string[] scopes = new string[] { /* MY REQUIRED SCOPES */ };

            using (var stream = new FileStream($"{HostingEnvironment.ApplicationPhysicalPath}/client_secret.json", FileMode.Open, FileAccess.Read))
            {
                FileDataStore dataStore = null;
                if (string.IsNullOrWhiteSpace(userName))
                {
                    userName = Guid.NewGuid().ToString();
                }
                else
                {
                    var uploadRootFolderInput = $"{HostingEnvironment.ApplicationPhysicalPath}/FaisalCredentials";
                    if (!Directory.Exists(uploadRootFolderInput))
                        Directory.CreateDirectory(uploadRootFolderInput);
                    var directoryFullPathInput = uploadRootFolderInput;
                    string filePath = Path.Combine(directoryFullPathInput, userName);

                    dataStore = new FileDataStore(filePath);
                }

                IAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
                {
                    ClientSecrets = GoogleClientSecrets.Load(stream).Secrets,
                    Scopes = scopes,
                    DataStore = dataStore
                });

                Uri myuri = new Uri(System.Web.HttpContext.Current.Request.Url.AbsoluteUri);
                var hostName = myuri.GetLeftPart(UriPartial.Authority);

                var redirectUri = $"{hostName}/CONTROLLERNAME/GetLoginUserCredentialFromAuthCode/";
                var authResult = await new AuthorizationCodeWebApp(flow, redirectUri, userName)
                .AuthorizeAsync("user", cancellationToken);

                return authResult.RedirectUri;
            }
        }

var redirectUri is must be the same which you added in the Authorized redirect URI of google console. Here I use {hostName}/CONTROLLERNAME/GetLoginUserCredentialFromAuthCode/. where GetLoginUserCredentialFromAuthCode is my callback action name.

Here is the code of callback action GetLoginUserCredentialFromAuthCode.

public async Task<bool> GetLoginUserCredentialFromAuthCode(AuthorizationCodeResponseUrl authorizationCode, CancellationToken taskCancellationToken)
        {
            string[] scopes = new string[] {/* MY REQUIRED SCOPES */ };
            using (var stream = new FileStream($"{HostingEnvironment.ApplicationPhysicalPath}/client_secret.json", FileMode.Open, FileAccess.Read))
            {
                var uploadRootFolderInput = $"{HostingEnvironment.ApplicationPhysicalPath}/FaisalCredentials";
                if (!Directory.Exists(uploadRootFolderInput))
                    Directory.CreateDirectory(uploadRootFolderInput);
                var directoryFullPathInput = uploadRootFolderInput;
                string filePath = Path.Combine(directoryFullPathInput, authorizationCode.State);
                string oldFilePath = Path.Combine(directoryFullPathInput, "faisal");

                if (Directory.Exists(oldFilePath))
                    Directory.Delete(oldFilePath, true);
                IAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow(
                new GoogleAuthorizationCodeFlow.Initializer
                {
                    ClientSecrets = GoogleClientSecrets.Load(stream).Secrets,
                    Scopes = scopes,
                    DataStore = new FileDataStore(filePath)
                });

                Uri myuri = new Uri(System.Web.HttpContext.Current.Request.Url.AbsoluteUri);
                var hostName = myuri.GetLeftPart(UriPartial.Authority);
                var returnUrl = $"{hostName}/Faisal/GetLoginUserCredentialFromAuthCode/";
                var token = await flow.ExchangeCodeForTokenAsync("faisal", authorizationCode.Code, returnUrl,
                taskCancellationToken).ConfigureAwait(false);

                if (!string.IsNullOrWhiteSpace(authorizationCode.State))
                {
                    string newPath = Path.Combine(directoryFullPathInput, "faisal");
                    if (filePath.ToLower() != newPath.ToLower())
                    {
                        if (Directory.Exists(newPath))
                            Directory.Delete(newPath, true);

                        Directory.Move(filePath, newPath);
                    }
                }

                return true;
            }
        }

“faisal” is the username.

The above method will read state code and generate Credentials file for that user on a given path. In my case, it will save inside the “FaisalCredentials” folder.

If you want to read the credentials file, the below methods will help for the same, it will return Google.Apis.Drive.v3.DriveService type and then we can use that service variable to further task/process. we need to pass a username to whom you want to read the configuration file.

public async Task<Google.Apis.Drive.v3.DriveService> GetLoginUserCredential(string userName)
       {
           string[] scopes = new string[] { /* MY REQUIRED SCOPES */ };
           //string userName = "";
           if (string.IsNullOrWhiteSpace(userName))
               userName = Guid.NewGuid().ToString();

           UserCredential credential = null;
           using (var stream = new FileStream($"{HostingEnvironment.ApplicationPhysicalPath}/client_secret.json", FileMode.Open, FileAccess.Read))
           {
               var uploadRootFolderInput = $"{HostingEnvironment.ApplicationPhysicalPath}/FaisalCredentials";
               if (!Directory.Exists(uploadRootFolderInput))
                   Directory.CreateDirectory(uploadRootFolderInput);
               var directoryFullPathInput = uploadRootFolderInput;
               string filePath = Path.Combine(directoryFullPathInput, userName);

               credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
               GoogleClientSecrets.Load(stream).Secrets,
               scopes,
               "faisal",
               CancellationToken.None,
               new FileDataStore(filePath));
           }
           Google.Apis.Drive.v3.DriveService service = new Google.Apis.Drive.v3.DriveService(new BaseClientService.Initializer()
           {
               HttpClientInitializer = credential,
               ApplicationName = "My Application name",
           });

           
           return service;
       }

And That’s it. we have done with Google OAuth API.

I hope you guys found something useful. Please give your valuable feedback/comments/questions about this article. Please let me know how you like and understand this article and how I could improve it.

Submit a Comment

Your email address will not be published. Required fields are marked *

Subscribe

Select Categories