in Software Development

Google+ Signin for ASP.NET MVC

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”.

Capture

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

Capture

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:

Capture

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.

Capture

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:

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.

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:

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

Capture

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

  • john

    Can you explain how to implement the RewriteRequest(), GetUserData() and QueryAccessToken() methods.

    And the AuthorizationEndpoint in the uriBuilder doesn’t exist, can you explain how to create this var

    • jerriep

      John, everything is implemented in the actual project which you can find on Github at https://github.com/jerriep/GooglePlusOAuthLogin/ . Please refer to that for the implementation of everything asked about. You can find the file under App_StartGooglePlusClient.cs

      • john

        Ok, Thank you very much for the reply

  • Laurent Brouck

    Hi, I met a problem after a google is log in, the api google plus return me the following error : Erreur :redirect_uri_mismatch
    The redirect URI in the request: http://localhost:1111/Ident/ExternalLoginCallback/ did not match a registered redirect URI

    from_login=1
    scope=https://www.googleapis.com/auth/plus.login
    https://www.googleapis.com/auth/userinfo.email
    response_type=code
    access_type=online
    redirect_uri=http://localhost:1111/Ident/ExternalLoginCallback/
    state=__provider__=GooglePlus&__sid__=a77838a78e724e95b1ea68e7e030d44b
    as=-739382c7f9e88065
    display=page
    client_id=205225857538.apps.googleusercontent.com
    hl=fr-FR

    I have create a classic account (using API Console) and the redirection url is valid, like you she go to the method (same as your example). I have test using another redirect url (not http://localhost:1111) but the same error.

    Have you an idea of this problem ?

    Thanks

    Laurent

    • jerriep

      Laurent,

      There are 2 things I can think of:

      1. Are you sure the redirect URL matches *exactly* with the one you registered in Google?

      2. Are you making sure that you are calling the GooglePlusClient.RewriteRequest() method in the ExternalLoginCallback() action?

      Jerrie

      • Laurent Brouck

        I have recreate a new project in Google API Console (with no filling the field “Authorized JavaScript Origins”) and it’s work ! Thanks you for your advice and your quick answer. Your code is great ! :)

        • jerriep

          Glad to hear you have got it working

  • Guest

    I don’t undestard how to download the project from GitHub: should i download file by file ?

    • jerriep

      You cannot “download” a Github repository. You will need to clone the repository. You can do a Google search on how to clone a Github repository.

      The easiest way would be the following:
      1. Download and install Github for Windows from http://windows.github.com/
      2. Go to the repository in your Web Browser and click on the “Clone in Windows” button (see attached image). That will open Github for Windows and allow you to clone the project to your local harddrive so you can work with it.

      You can also do a search on Youtube. You will find plenty of videos there which shows you how to do it.

      Hope it helps

  • Jed Grant

    This is exactly what I needed, but it seems it’s a little incomplete. Any chance you have another blog post lying around somewhere about how to get details like the user first and last name, photo, gender etc?

    • jerriep

      Hi Jed,

      I don’t have any blog post describing that, but you can look at the Google+ documentation at https://developers.google.com/+/api/latest/people/get to see what needs to be done.

      Basically you need to do the following:

      1.Ensure that you add “https://www.googleapis.com/auth/plus.me” to the list of scopes on line 67 of GooglePlusClient.cs

      2. After that you can just make an OAuth2 call to https://www.googleapis.com/plus/v1/people/me to get all the information for the currently signed in user. You will probably need some 3rd party OAuth library for this, or otherwise just use the Google C# SDK – look at https://developers.google.com/+/quickstart/csharp for help on this

      You can test the API call on the documentation page I listed above. Under the “Try It!” section on the documentation page ensure you switch on “Authorize requests using OAuth 2.0″, then type in “me” in the “userid” field and click Execute. It will execute the call and allow you to see the data returned from the API call

      This is unfortunately as much assistance as I can give you. Hope you manage :)

  • Tomas Ekenman

    Awesome! Thank you. Very clear and easy to understand!

  • http://codeofmatt.com/ Matt Johnson

    Hi Jerrie. Great write up, and thanks for the credit! I am very happy that I could help you find a solution!

    I am curious though – is there a reason that you needed to reimplement the whole thing? I think you could just pass the Google Plus scopes in to the optional constructor parameter “requestedScopes” in my original code. Or is there something more that I overlooked in your implementation?

    I haven’t been paying much attention to changes at Google. Is there something different about Google Plus authentication than just regular Google authentication? Or is it just that you have access to Google Plus by requesting those scopes?

    • http://www.beabigrockstar.com/ Jerrie Pelser

      Hi Matt. This was quite a while back, but I think here is no reason not to have used your solution. The thing was that I was already trying to solve the problem completely unaware that you have solved it and only came across your solution when I got stuck on that final bit right at the end.

      I decided just to write the blog post in any case to document the solution.

      • http://codeofmatt.com/ Matt Johnson

        Yeah, I saw you wrote it in March, but I just stumbled upon it today. :)

        I like the detail of your post, I just wanted to make sure I didn’t miss something critical for G+. Thanks again!

  • Riku H

    Hi Jerrie. Thanks a lot for this post. I had been searching this sort of solution for a while and finally this was the exact piece I was looking for.

    • http://www.beabigrockstar.com/ Jerrie Pelser

      It is a pleasure Riku :)

  • Sara

    its great help. but i’m facing some issue. on this:
    AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication(Url.Action(“ExternalLoginCallback”, new { ReturnUrl = returnUrl }));
    i’m getting i’m getting issuccessfull==false, and i’m getting no error. its same for local and live.

    • http://www.beabigrockstar.com/ Jerrie Pelser

      @disqus_YR7DvqEF5E:disqus I am not sure what the reason for this could be. Did you make sure that you have Google+ API Access enabled? You can go to your Google Developer Console and go to APIs & Auth > APIs and make sure that you have turn “Google+ API” on

      • Guest

        @disqus_YR7DvqEF5E:disqus I also had a compilation error on that line.
        “The name OAuthWebSecurity does not exist in the current context”
        You need to install the Microsoft WebPages OAuth Library from nuget otherwise your app will not be able to use the OAuthWebSecurity class.

  • Benjamin Day

    I’m using the Owin.Security.GooglePlus.GooglePlusAuthenticationOptions class in my MVC5 app in the Startup.Auth.cs to do Google+ authentication, Is there a any way to get “request_visible_actions=http://schemas.google.com/AddActivity” and “access_type=offline” in the query string of the post that goes out to Google?

    • http://www.beabigrockstar.com/ Jerrie Pelser

      @benjamin_day:disqus I will look into doing this for you. Give me a few days to get around to it. Alternatively, if you are in a hurry you can fork the repo in Github, make the changes and submit a pull request

    • Benjamin Day

      I’ve been trying the last few days to figure it out with no success. I eagerly await to see what you can come up with. Thanks for looking into this to see what can be done.

      • http://www.beabigrockstar.com/ Jerrie Pelser

        Benjamin Day I have moved the Google+ provider to the Nuget package Owin.Security.Providers and added the features you requested. If you upgrade the Owin.Security.GooglePlus package it will automatically bring in the dependency to the new package. You will just need to update your namespace references

        New properties in GooglePlusAuthentications:

        - RequestOfflineAccess will allow you to request offline access. GooglePlusAuthenticatedContext will contain RefreshToken in this case

        - MomentTypes will allow you to specify the moment types to request permissions for

        See https://github.com/owin-middleware/OwinOAuthProviders/blob/master/OwinOAuthProvidersDemo/App_Start/Startup.Auth.cs for demo to use (it is commented out, but you’ll figure it out I am sure).

        • Benjamin Day

          Jerrie, thank you so much for this update. I was able to update with no problem and add the stuff from the demo on github. Now it’s time to figure out the Google.Apis.Plus.v1 library to share a moment. Thanks again for your help!

          • http://www.beabigrockstar.com/ Jerrie Pelser

            Cool :)

  • Gouri

    Is it a good idea to use Google+ Sign In in MVC4 application without integrating it with existing OAuth infrastructure that Microsoft provides ? I don’t want to use DotnetOpenAuth dll’s in my project and the reason behind it is I started facing same issue as described here:

    http://stackoverflow.com/questions/21370874/authenticationresult-issuccessful-started-returning-false-for-google

    • http://www.beabigrockstar.com/ Jerrie Pelser

      I think it makes your life just a little bit easier if you use the build-in authentication framework in ASP.NET MVC. In ASP.NET MVC the old Membership system has been replaced with ASP.NET Identity which has no dependency on DotnetOpenAuth. I have written plenty of blog posts on using ASP.NET Identity. I have also written a Nuget package which adds support for Google+ (OAuth) to ASP.NEt Identity: http://blog.beabigrockstar.com/google-oauth-sign-asp-net-identity/