How to: OAuth 2.0 Flows using the Google+ .NET API Client Libraries 1.7+ in C#

There have recently been significant changes to the .NET Libraries for Google APIs. As such, it’s a great time to show my favorite scenarios for OAuth 2. In this brief post I’ll show you a basic API query and then some more complicated examples such as code exchange.

Using a Basic API key

Before we begin, I want to add that for making basic API calls, you do not need a client id / client secret. You first start by creating a project in the Google Developer Console and then constructing a service object as follows:

PlusService plusService = new PlusService(
                    new Google.Apis.Services.BaseClientService.Initializer()
                    {
                        ApiKey = API_KEY
                    });

You are now ready to make API calls using the service object as follows:

Person me = plusService.People.Get(@"+GusClass").Execute();

If you inspect the me variable, you will see all of the data for the user +GusClass in your data. This is the easy one so if you want to make sure your configuration is working, start with a basic API such as Plus.People.Get as shown above or Plus.Activities.Search. Note, for performance, you should use the async methods:

Person me = await plusService.People.Get(@"+GusClass").ExecuteAsync();

Pre-steps for OAuth 2.0 Flows in C# / .NET

You must get API keys from the Google Developer Console. For code exchange and refresh flows, where your application is authorized to perform operations on a user’s data, you will also need to provide a client ID and secret, which now be loaded from JSON as described in the next section. I’m not going to get into very deep detail about much beyond how the client (service) is authenticated.

Building the objects for performing flows

Constructing a TokenInfo object:

        /// <summary>Retrieves the Client Configuration from the server path.</summary>
        /// <returns>Client secrets that can be used for API calls.</returns>
        public static GoogleClientSecrets GetClientConfiguration()
        {
            using (var stream = new FileStream("client_secrets.json", FileMode.Open, FileAccess.Read))
            {
                return GoogleClientSecrets.Load(stream);
            }
        }

Constructing a service given a TokenInfo object:

        /// <summary>
        /// Gets a Google+ service object for making authorized API calls to Google+ endpoints.
        /// </summary>
        /// <param name="credentials">The OAuth 2 credentials to use to authorize the client.</param>
        /// <returns>
        /// A <see cref="PlusService">PlusService</see>"/> object for API calls authorized to the
        /// user who corresponds with the credentials.
        /// </returns>
        public static PlusService GetPlusService(TokenResponse credentials)
        {
            IAuthorizationCodeFlow flow =
            new GoogleAuthorizationCodeFlow(
                new GoogleAuthorizationCodeFlow.Initializer
                {
                    ClientSecrets = GetClientConfiguration().Secrets,
                    Scopes = new string[] { PlusService.Scope.PlusLogin }
                });

            UserCredential credential = new UserCredential(flow, "me", credentials);

            return new PlusService(
                new Google.Apis.Services.BaseClientService.Initializer()
                {
                    ApplicationName = "Haikunamatata",
                    HttpClientInitializer = credential
                });
        }

 

OAuth 2.0 Flows examples

Again, the key flows are:

  • Basic API Key – You want to make an API call that does not require user authorization.
  • Code exchange – You have an authorization code from a redirect or the Sign-In Button and want an access / refresh token combo.
  • Refresh – You have a refresh token, your access token is expired, and you want to have a new access token.

Code Exchange

Code exchange is the first type of authenticated OAuth 2.0 flows I want to demonstrate. The authorization code typically is passed to your client from an authorization server and is only valid for exchange once.

response = null;

    // Use the code exchange flow to get an access and refresh token.
    IAuthorizationCodeFlow flow =
        new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
        {
            ClientSecrets = GetClientConfiguration().Secrets,
            Scopes = new string[] { PlusService.Scope.PlusLogin }
        });
    TokenResponse response = flow.ExchangeCodeForTokenAsync("", code, "postmessage", CancellationToken.None).Result; // response.accessToken now should be populated

You can now perform authenticated queries on a service object using the TokenResponse object and can securely store the refresh token if it was returned from the code exchange.

Refresh Token

When you have a valid refresh token and want to make authenticated API calls to Google, you will not be able to directly use the refresh token to make API calls. However, you can get a temporary access token by exchanging the refresh token with the server. The following code shows a refresh token flow:

    TokenResponse token = new TokenResponse
        {
            AccessToken = this.GoogleAccessToken,
            RefreshToken = this.GoogleRefreshToken
        };

    IAuthorizationCodeFlow flow =
        new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
            {
                ClientSecrets = PlusHelper.GetClientConfiguration().Secrets,
                Scopes = new string[] { PlusService.Scope.PlusLogin }
            });

    UserCredential credential = new UserCredential(flow, "me", token);
    bool success = credential.RefreshTokenAsync(CancellationToken.None).Result;

    token = credential.Token;

Making API calls once you have TokenResponse

You are now ready to make authenticated API calls with the response:

    PlusService plusService = new PlusService(
        new Google.Apis.Services.BaseClientService.Initializer()
        {
            ApplicationName = "Haikunamata",
            HttpClientInitializer = credential
        });

 

I have put together an update to the Google+ Quickstart that demonstrates the new way of doing things.

 

See Also

If you’re using ASP.NET MVC: