Home > Mobile >  How to generate authorization URL for OAuth 2.0 consent screen in .Net Core Console Application?
How to generate authorization URL for OAuth 2.0 consent screen in .Net Core Console Application?

Time:10-01

I know that it is possible to generate OAuth2.0 consent screen URL within a .net framework via deprecated Google.GData.Client library in a bare Console Application. The flow looks like following:

// OAuth2Parameters object, which holds all the parameters related to OAuth 2.0.
OAuth2Parameters parameters = new OAuth2Parameters();

// Set OAuth 2.0 Client Id
parameters.ClientId = clientId;

// Set  OAuth 2.0 Client Secret
parameters.ClientSecret = clientSecret;

// Set Redirect URI (in this case it will return authorization code in browser)
parameters.RedirectUri = "urn:ietf:wg:oauth:2.0:oob";

// Set Desired Scope.
parameters.Scope = scope;

// desired URL via OAuthUtil's static method
string url = OAuthUtil.CreateOAuth2AuthorizationUrl(parameters);

This URL I could open in browser, view Google consent screen, click allow and retrieve authorization code, which I then would use to get appropriate access and refresh tokens like this:

parameters.AccessCode = Console.ReadLine();
OAuthUtil.GetAccessToken(parameters);
accessToken = parameters.AccessToken;
refreshToken = parameters.RefreshToken;

My major problem is that I would like to do this in a bare .Net Core Console Application (without GData ofcourse), but I struggle to find how. I guess, it is possible to do this in general, at least there are active examples for PHP, Ruby and Python for doing something very similar for calling YouTube API. Can somebody possibly know, how to do this in .Net Core?

Also, this can't be handled with service account (I don't have problem with that in my app) as users might not be from my organization, so looks like viewing consent screen is necessary.

CodePudding user response:

Oauth2 flow.

Oauth2 is actually easy enough to handle you just need to be able to do HTTP GET and HTTP Post calls.

The first thing we do is create the link that will cause the consent screen to appear. This is a HTTP Get call so can be placed in any web browser.

https://accounts.google.com/o/oauth2/v2/auth?client_id=XXXX.apps.googleusercontent.com&redirect_uri=urn:ietf:wg:oauth:2.0:oob&scope=https://www.googleapis.com/auth/userinfo.profile&response_type=code

When the user consents to access the authorization code will be displayed to them on the page.

The next thing you will need to do is exchange that authorization code for an access token and a refresh token.

This is a HTTP POST call, you can do it with .net core easy enouhg here is an example of the call using Curl

curl -s \
--request POST \
--data "code=4/1AY0e-g7BhBt0QU9f5HTgNDGNR1GYtH12q4xvgL_D2Q34A&client_id=XXXX.apps.googleusercontent.com&client_secret=zYAoXDam3mqsdwabh3dQ3NTh&redirect_uri=urn:ietf:wg:oauth:2.0:oob&grant_type=authorization_code" \
https://accounts.google.com/o/oauth2/token 

At which point the server will return to you an access token

{
  "access_token": "ya29.a0AfH6SMDypscIeiyNnPRvoizz3NvvA6SZdk9U4K8h4MyQRRm29kEc2shdrskPZp71Q1roy8RqIm_7spufW84ozUoSTk0QKkQ",
  "expires_in": 3599,
  "refresh_token": "1//09Y5LQ0XRxjt-CgYIARAAGAkSNwF-L9IrYzyMnbGtJHgh-FTf6z79cBhQ1hsPUAk71HFgFwqyXoiwpIa-4eA",
  "scope": "https://www.googleapis.com/auth/userinfo.profile",
  "token_type": "Bearer"
}

If you would like to know how it all works I have a video here Understanding Oauth2 with curl companion blog post How to get a Google access token with CURL

google .net client library

I strongly sujest that you use the Google .net clinet library supports .net core.

The following is an example of authorization with an installed application (console application).

    /// <summary>
    /// ** Installed Application only ** 
    /// This method requests Authentcation from a user using Oauth2.  
    /// Credentials are stored in System.Environment.SpecialFolder.Personal
    /// Documentation https://developers.google.com/accounts/docs/OAuth2
    /// </summary>
    /// <param name="clientSecretJson">Path to the client secret json file from Google Developers console.</param>
    /// <param name="userName">Identifying string for the user who is being authentcated.</param>
    /// <param name="scopes">Array of Google scopes</param>
    /// <returns>authencated UserCredential</returns>
    private static UserCredential GetUserCredential(string clientSecretJson, string userName, string[] scopes)
    {
        try
        {
            if (string.IsNullOrEmpty(userName))
                throw new ArgumentNullException("userName");
            if (string.IsNullOrEmpty(clientSecretJson))
                throw new ArgumentNullException("clientSecretJson");
            if (!File.Exists(clientSecretJson))
                throw new Exception("clientSecretJson file does not exist.");

            // These are the scopes of permissions you need. It is best to request only what you need and not all of them               
            using (var stream = new FileStream(clientSecretJson, FileMode.Open, FileAccess.Read))
            {
                string credPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
                credPath = Path.Combine(credPath, ".credentials/", System.Reflection.Assembly.GetExecutingAssembly().GetName().Name);

                // Requesting Authentication or loading previously stored authentication for userName
                var credential = GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.Load(stream).Secrets,
                                                                         scopes,
                                                                         userName,
                                                                         CancellationToken.None,
                                                                         new FileDataStore(credPath, true)).Result;

                credential.GetAccessTokenForRequestAsync();
                return credential;
            }
        }
        catch (Exception ex)
        {
            throw new Exception("Get user credentials failed.", ex);
        }
    }

Both my website Daimto.com and my YouTube channel Daimto developer tips Have examples for using the google apis with .net. I also have a github project Google-Dotnet-Samples with examples for most of the apis.

  • Related