Google+ Server Side flow in C#
Out of date
Heads up dear reader, a whole lot has happened in the past 18 months and so this post is out of date. Please read my latest here – How to: OAuth 2.0 Flows in .NET using C# for updated guidance and a new .NET Authorization sample!
Also, you can read the official sample documentation online here.
Overview
I recently was looking into creating a server-side application using the Google+ API and the .NET library. It’s slightly different from doing a client-side application in C# or a Windows store app.
What’s different is that the client library will take the HTTP context from your server, then run the user through the authentication flow, finally giving you back a client with an access token and a refresh token.
If you have Visual Studio and Windows, you can download the sample app. If you don’t have Visual Studio, you can download Visual Studio Express from MSDN to try this out.
Setting up new projects
Although you will not need to perform these steps if you’re starting from the sample, you will need to do the following steps if you are interested in creating a new project from scratch with the client libraries:
- Get the latest version of the .NET library, which can be downloaded from here:
https://code.google.com/p/google-api-dotnet-client/wiki/Downloads
The “Binary Release” zip is all you need unless you want to debug into the various generated service libraries. - The project needs to be set up with the references you downloaded.
The following image shows you the references I have added:
Once you have all the requisite references set up, you should be able to access the client libraries from your app.
Running the sample
If you are trying the sample app, you will need to get a client id from the Google APIs console. Services, origins, and redirects for this client id must be turned on as described in the client-side flow.
The following image shows the only services I’ve turned on:
Next, you will need to add your authentication page to the list of Redirect URIs. In this example, mine is localhost:8080/auth.aspx, so my console looks like the following image (Client ID / secret omitted):
Next, enter the client id and client secret in the wrapper class, PlusWrapper.cs, replacing YOUR CLIENT ID HERE and YOUR CLIENT SECRET.
private static class ClientCredentials { // These come from the APIS console, https://code.google.com/apis/console static public string ClientID = "YOUR CLIENT ID HERE"; static public string ClientSecret = "YOUR CLIENT SECRET"; }
Click the run button in Visual Studio and the sample will start, opening the index for the site. You will get a folder like the following:
Open auth.aspx and the server will walk you through the authorization flow. When you are done, you will see your profile rendered as follows:
How it works
The following code shows how the the Authorization flow is kicked off.
// RefreshService /// <summary> /// Ensures that the current Plus service is authenticated and valid /// </summary> private void RefreshService() { // Create the service. if (plusService == null) { // Register the authenticator. var auth = CreateAuthenticator(); plusService = new PlusService(auth); if (plusService != null) { PeopleResource.GetRequest prgr = plusService.People.Get("me"); me = prgr.Fetch(); } } } public Person Authenticate() { // Use the client to perform all of the Auth steps. RefreshService(); // Now we should have the Plus service object, use it to perform a simple operation. return me; }
For convenience, the method Authenticate is called in the wrapper class. This is done to retrieve the current user who is signed in. When the user is retrieved, the PlusService object is lazily instantiated by calling the RefreshService method. This method will try and create a valid state object so that the client library can perform queries. Let’s take a look at the code which will try to create an OAuth2Authenticator object, used to build the IAuthorizationState object instance, state:
// CreateAuthenticator /// <summary> /// Creates the authenticator for the server-side flow. /// </summary> /// <returns>An authenticator to be used for queries</returns> private OAuth2Authenticator<WebServerClient> CreateAuthenticator() { // Register the authenticator. AuthorizationServerDescription description = GoogleAuthenticationServer.Description; if (description.AuthorizationEndpoint.AbsoluteUri.IndexOf("offline") < 1) { description.AuthorizationEndpoint = new Uri(description.AuthorizationEndpoint.AbsoluteUri + "?access_type=offline"); } var provider = new WebServerClient(description); provider.ClientIdentifier = ClientCredentials.ClientID; provider.ClientSecret = ClientCredentials.ClientSecret; var authenticator = new OAuth2Authenticator<WebServerClient>(provider, GetAuthorization) { NoCaching = true }; return authenticator; } // GetAuthorization /// <summary> /// Gets the authorization object for the client-side flow /// </summary> /// <param name="client">The web server client used for authorization</param> /// <returns>An authorization state that can be used for API queries </returns> private IAuthorizationState GetAuthorization(WebServerClient client) { // If this user is already authenticated, then just return the auth state. IAuthorizationState state = _authstate; if (state != null) { return state; } // Check if an authorization request already is in progress. HttpRequestInfo reqinfo = new HttpRequestInfo(HttpContext.Current.Request); state = client.ProcessUserAuthorization(reqinfo); // Check to see if we have an access token and use that to generate the state. if (_accessToken != null) { state = CreateState(_accessToken, true); // Check to see if we have a refresh token and use that to get the auth state. } else if (_refreshToken != null) { state = CreateState(_refreshToken); bool worked = client.RefreshToken(state); if (state != null) { return state; } } if (state != null && (!string.IsNullOrEmpty(state.AccessToken) || !string.IsNullOrEmpty(state.RefreshToken))) { // Store and return the credentials. HttpContext.Current.Session["AUTH_STATE"] = _authstate = state; _accessToken = state.AccessToken; _refreshToken = state.RefreshToken; return state; } // Otherwise do a new authorization request. string scope = PlusService.Scopes.PlusMe.GetStringValue(); OutgoingWebResponse response = client.PrepareRequestUserAuthorization(new[] { scope }); response.Send(); // Will throw a ThreadAbortException to prevent sending another response. return null; }
When the CreateAuthenticator method is called, parameters, such as the client ID and secret, are built into a provider object. This provider can be used to then perform authorization against the Google OAuth 2.0 endpoint. Because the client is performing a server-side flow, a WebServerClient is used to take over the user experience until the user is done with the authentication flow. At the conclusion of the authorization flow, you can retrieve the access token and the refresh token. These tokens can then be used to either re-establish state or to perform authenticated queries against the Google+ APIs. For convenience, another method is implemented for building the state object from cached tokens:
// CreateState /// <summary> /// Creates a state object from a refresh token or access token. /// </summary> /// <param name="refreshToken">The refresh token from an authorization response.</param> /// <returns>A generated authorization state.</returns> private IAuthorizationState CreateState(string token, bool isAccessToken = false) { string[] scopes = { PlusService.Scopes.PlusMe.GetStringValue() }; IAuthorizationState state = new AuthorizationState(scopes); if (isAccessToken) { state.AccessToken = token; } else { state.RefreshToken = token; } return state; }
When the state is recreated, subsequent calls to RefreshService will build out all of the required authentication pieces without needing any interaction from the user. Rebuilding the state is done in the following order:
- From a new authentication code
- From a valid access token
- From a refresh token
- Using the authentication flow from the client library
public Plus.v1.Data.Person me; protected void Page_Load(object sender, EventArgs e) { GPlusWrapper.PlusWrapper pw = new GPlusWrapper.PlusWrapper(); me = pw.Authenticate(); }
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="auth.aspx.cs" Inherits="GPlus_ServerSideFlow.auth" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> </head> <body> <div> <div>Name: <%=me.DisplayName %></div> <div>Tagline: <%=me.Tagline%></div> <div><img src="<%=me.Image.Url%>" /></div> </div> </body> </html>
Members of the me instance are now accessible on the page because the object was returned from the call to Authenticate made using the wrapper class. What is also interesting is that the server now has credentials for re-authenticating the user.
Closing thoughts
Although I didn’t expect it to be too difficult, I was still surprised with how easy it is to access the Google+ API from server-side flows. If you’re building a service or application that can use the library, you can get started very quickly, jumping right into accessing the available Google+ APIs. If you are a developer working on a Microsoft web stack, you should try playing with what’s available from Google+.
Hi, I tried to use your sample to access the fusion tables api. But when I debug it from Visual Studio, I am getting this error:
Method ‘get_Error’ in type ‘Google.Apis.Fusiontables.v1.Data.Table’ from assembly ‘Google.Apis.Fusiontables.v1
Can you please help me to figure this error.
Thanks
@Uday Thanks for the comment! There are a number of things that could be causing this issue, when in your code is this happening? Is it happening the first time you make an API call to the fusion tables library? Is it a build time error?
Thanks for this post, had been looking specifically for examples on using these C# libraries and found Google’s own documentation somewhat lacking.
I can’t seem to open you project with any version of Visual Studio though (I have 2003-2010, and 2012 express). What version was it created under?
@robbievgb, these projects were probably written in VS2012 because it was what I had as default on my computer 🙂 However, Google+ has an officially supported quickstart Google+ sample targeting C#/.NET and Visual Studio 2010.
Hi!
How to get user email??
me.Emails is always null?!
In order to get a user’s email for their account, you can request an additional scope, userinfo.email, and then retrieve the user’s profile to get their email. More information here: https://developers.google.com/+/web/people/
Hi,
Thanks for the post.
In addition to the functionality in the above post, i am trying to generate a access token and refresh token in exchange for the auth code returned . Unfortunately, using the google documentation at https://developers.google.com/accounts/docs/OAuth2WebServer#handlingtheresponse , i am unable to generate accesstoken and refresh token. i am getting a bad request error. It will be really helpful if you could provide you input on this.
Thanks!!
HI
Thanks for the post
HOW I CAN USE THIS IN WCF?
In wpf application i want to post and get comments into my google+ page.
can i use wcf service for my wpf application to interaction with google+?
In our samples we typically avoid WCF because it can create additional work. However, you can still use WCF with the Google OAuth 2.0 provider and can request the scope for Google+ in your project. Perhaps a topic for a future blog post 🙂
I did not get email id with example above.
Ouch! This is a really outdated post, please check the update here and hopefully it will solve your problems – http://gusclass.com/blog/2014/04/16/how-to-oauth-2-0-flows-using-the-google-net-api-client-libraries-1-7-in-c/