Google+ Signin for ASP.NET MVC 4

With ASP.NET MVC 4 Microsoft has added the ability to allow your users to log in to your application using various OAuth and OpenID providers.  Microsoft has supplied clients for Facebook, Twitter, Google, Microsoft, LinkedIn and Yahoo.  The Google client is based on OpenID and not OAuth.  With the recent announcement of Google+ Signin I set out to create a client which uses the Google+ login via OAuth instead of the standard OpenID login.

Google has supplied some great documentation on how to achieve this, but what I wanted to do was to create something which integrated nicely with the existing OAuth infrastructure which Microsoft supplied in MVC 4.

Overview of the Google OAuth Client

The Google OAuth signin process is described in detail in the Google Developers documentation.  This is pretty much the standard process for any OAuth 2.0 provider. There is one caveat however, and that is that Google expects the redirect URL to exactly match the one you define when your register your application in the Google API Console (I describe the application registration later in the blog post).  This creates a problem for us as the OAuth framework which Microsoft has supplied in MVC 4 appends extra parameters to the query string of the redirect URL.  One of these parameters is named “provider” and it is crucial for the MVC OAuth infrastructure to be able to know which provider to use.

After a lot of searching I came across a solution to this by Matt Johnson.  He has made his solution available on Github in the repository named https://github.com/mj1856/DotNetOpenAuth.GoogleOAuth2.  Actually a lot of our solution to the problem is pretty much similar and I unashamedly borrowed his solution to work around the extra parameters which are added to the redirect URL.

What Google allows you to do is to send extra data through to the Authentication server in a state parameter which gets round tripped and passed back to you by the response.  What Matt’s solution does is to strip the entire query string from the redirect URL which is generated by the OAuth Web Security classes and pass it on to Google in the state parameter.  Once Google responds back from the Authentication URL, the data from the state parameter gets re-injected into the request which is made from the Google Authentication back to our application.

Register the application on the Google API Console

The first step is to register your application in the Google API Console.  Once the application has been created, select the API Access tab and click on “Create an OAuth 2.0 client ID”.

In the next dialog specify the name of your application and click Next

The next part is to specify the callback URL, so to do this click the “more options” link in the dialog and specify the redirect URL.  It is important that the redirect URL points to the ExternalLoginCallback action of your Account controller:

Once done you can click on the “Create client ID” button.  Take note of the Client ID and Client secret as you will need these later on when registering the new Google+ signin client.

Putting it all together

Microsoft has supplied most of the infrastructure already in place, so to create our own Google OAuth client we simply inherit from the DotNetOpenAuth.AspNet.Clients.OAuth2Client class and implement the 3 abstract methods which are defined.

The first method we need to implement is GetServiceLoginUrl:

protected override Uri GetServiceLoginUrl(Uri returnUrl)
{
    UriBuilder uriBuilder = new UriBuilder(AuthorizationEndpoint);
    uriBuilder.AppendQueryArgument("client_id", this.clientId);
    uriBuilder.AppendQueryArgument("redirect_uri", returnUrl.GetLeftPart(UriPartial.Path));
    uriBuilder.AppendQueryArgument("response_type", "code");
    uriBuilder.AppendQueryArgument("scope", "https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email");
    uriBuilder.AppendQueryArgument("state", returnUrl.Query.Substring(1));

    return uriBuilder.Uri;
}

Note that we are stripping the redirect URL back to just the path and extracting the query string and passing that through in the state parameter.

Once the user has successfully authenticated against the Google servers a callback will be made to the redirect URL, which means it will go the the ExternalLoginCallback on our AccountController.  It is at this point which the request must be rewritten before it gets passed on to the OAuth Web Security classes.  The code which rewrites the request is implemented in the RewriteRequest() method of our GooglePlusClient class, so we need to add the call to this method before any of the other code gets executed.

[AllowAnonymous]
public ActionResult ExternalLoginCallback(string returnUrl)
{
    // Rewrite request before it gets passed on to the OAuth Web Security classes
    GooglePlusClient.RewriteRequest();

    AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication(Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));

   // Rest of the controller follows as normal
}

At this point the OAuth classes will need to exchange the authorization code for an access token.  The source code for this is implemented in the second abstract method which we need to override, namely the QueryAccessToken(..) method.  This method calls back to the Google token endpoint and passes the authorization code as parameter. (For full documentation on this you can refer to the “Handling the Response” section in the Google documentation.)  The token endpoint will pass back a JSON object containing the access token, so we extract that from the response and pass it back to the OAuth Web Security infrastructure.

The third and final method we need to implement is the GetUserData() method.  This is called by the VerifyAuthentication() method of the base OAuth2Client class to retrieve a dictionary containing the user information.  The only key that is required to be present in the dictionary is the “id” key, which is the ID of the user on Google.  It is also looking for key named “username” or “name”, although this is not required.  Google does not return a username field so we create a username field in the dictionary with the value of the email address.

The final bit is to register our new GooglePlusClient class in the AuthConfig class:

public static class AuthConfig
{
    public static void RegisterAuth()
    {
        OAuthWebSecurity.RegisterClient(new GooglePlusClient("YOUR CLIENT ID", "YOUR CLIENT SECRET"), "Google+", null);
    }
}

Run the application and select to log in with Google+.  You will be selected with the new Google+ signin screen.

As always, all source code can be found in Github in the repository https://github.com/jerriep/GooglePlusOAuthLogin/