A while back I wanted to create an ASP.Net MVC client for Google Fit that charted my weight. It turned out that offline Google authentication wasn’t as straight forward as one would hope. This article will explain how it works using the Google Fitness API as an example. The code is applicable to the whole Google API. In this example only a single authorization is stored and used¬†across multiple accounts.

If you need to store multiple authorizations, you can do so by implementing the IAuthenticationIdentifierProvider in a different way.

Building a client

Because authentication alone can be quite abstract, I’ll use the Google Fit client as an example. I used the following requirements to create the application:

  • Google Fit LogoThe idea is to build an MVC client for Google Fit.
  • Only a user with the Administrator can authorize the central Google Account.
  • Logged on¬†users will be able to use this authorization to view a weight graph.
  • The authorization must be for offline access and weight.

The actual implementation Google Fit API weight stuff is not part of this article, but is discussed in this article: Getting your weight from Google Fit with C#.

Flowchart

I’ve created a simple flowchart that shows how various MVC controllers will interact:

Design MVC controller flow

The logon controller is not part of this tutorial (a really simple one for hobby projects can be found here).

0. Nuget

Always. Start. With. Nuget.

Install-Package Google.Apis.Auth.Mvc»

Google provides us with many base classes to help us to create an authentication flow.

1.1 Offline authentication flow

The default GoogleAuthorizationCodeFlow issues a temporary token. I would like an offline token, because other people need to access my data and I don’t want to give out my credentials to those¬†users.

This code basically creates an offline Google Authorization URL with the right parameters.

1.2 Storing and using API settings

There are a million ways of keeping track of your API settings. I prefer to store them in my web.config as appSettings and using them in a single class.

I store the settings in the web.config. The ClientId and the ClientSecret can be retrieved from your app.

It can be filled using my AppSettingsProvider class (more info here).

1.3 Get in the (meta data) flow

Google will supply us with a token. We’ll need to refresh that token each time we’re going to use it (don’t worry, Google does it for you).¬†The flow meta data class is the bridge between the controller and the mechanism that will refresh the token. It will also determine how the token is stored and what flow it uses to refresh the token.

The flow will try to get an identifier from the controller. This identifier will be used to store / retrieve authentications form the data store. This can be used to tie an authorization to a user.

I’ll come back to this interface later.

2. Authentication callback controller

The AuthCallbackController will do the actual authentication. It will use the session to temporary store the identifier and scopes of the authentication. It uses the AppFlowMetadata.

Authentication¬†tokens will be stored in a data source. I’ve chosen a FileDataStore. I tested it with Windows Azure and it worked.

3. Abstract controller base with credentials

Both the¬†HomeController and the¬†WeightController¬†need to inspect the stored UserCredential.¬†I’ve created an abstract base class that facilitates this. The class also implements the¬†IAuthenticationIdentifierProvider¬†– by returning the same constant in the derived classes we make sure only one authentication is stored.

This class will use the¬†AuthCallbackController to do the actual requesting, storage and retrieval of the authentication token. Any derived class will need to give the¬†authentication scopes to the base constructor. Every Google Service will provide you with scopes; in case of Google Fit I’ll use the¬†FitnessService.Scope.FitnessBodyRead scope.

3.1 Home Controller

We’re almost there. All the helper classes are now written and can be used to create the actual program. First we’ll create the¬†HomeController. It derives from the¬†UserCredentialControllerBase. Because we’ll only allow a single authorization we’ll return a constant as¬†GetIdentifier() result.

Remember to decorate the controller method with the right Authorize attribute. The Credential property can be used to check if an authorization is present.

3.2 Weight Controller

The WeightController is pretty straight forward. When no credential is present, redirect back to the /Home/Index otherwise, get the data and render the view.

Final thoughts

I think Google has created a nice set of APIs. This article proves that the provided SDK is very pluggable.