Getting social network access token from C# backend

Acquire Facebook or Google+ access token from C# code

FbkgplsMost popular social networks such is Facebook and Google+ are providing authentication for web applications with fancy javascript pop-ups. However this approach might not work in all browsers and most likely not on every device.

For example this approach does not work on iPhone or iPad because browser itself does not allow pop-ups. The most convenient way of doing this is to navigate off from your page, authenticate and allow access to your social network app. In exchange you will get token with which you can then make calls to social network APIs.

This sounds simple, basically it is, but there is a small problem. Both Facebook and Google+ do not return access token as a query string to your callback page. Instead they return token in URL after # character. 

This value cannot be read on the back-end because it anything after # character server does not consider as a value for back-end, so it ignores it.

To get the token as a query string value, there is one more step to be done before invoking token API call. We need to fetch code value first. Code is a sort of token but only server side code and expires a lot more faster than access token. It is only used so that server back-end code can acquire access token.

To make it more secure there are few more small tricks which need to be taken in consideration. 

Google+ access token

First well get the code value by making a simple web request to Google service. As it needs to contain some values that are available from Google App console, we are going to build a URL with all values as query string values.

 string authUrl = string.Format("https://accounts.google.com/o/oauth2/auth?client_id={0}&redirect_uri={1}&response_type=code&scope={2}",
            APPLOICATION_ID,
            CALLBACK_URL,
            "https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email"
            );

Response.Redirect(authUrl, true);
    
Note

The key parameter is response_type=code, if we change it to response_type=token will get the token but after # character in URL.

Now when we got code as query string in callback URL we can fetch token. As I mentioned before, there is another catch to make this a bit more secured. You have to request for access token with POST web request. 

This will require to write values to a request stream instead of just adding them to the URL you are going to request for.

var url = string.Format("code={0}&client_id={1}&client_secret={2}&redirect_uri={3}&grant_type=authorization_code",
                    Request["code"],
                    APPLICATION_ID,
                    CLIENT_SECRET,
                    CALLBACK_URL
                    );
                var req = WebRequest.Create("https://accounts.google.com/o/oauth2/token");
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                ASCIIEncoding encoder = new ASCIIEncoding();
                byte[] data = encoder.GetBytes(url);
                req.ContentLength = data.Length;
                req.GetRequestStream().Write(data, 0, data.Length);
				string tokenResponse = new StreamReader(req.GetResponse().GetResponseStream()).ReadToEnd();
    

Access token along with some additional values will be returned as a JSON string in the following format

{  
   "access_token":"u4nIKLPVs_yJCfO1qdBNzzJI7fzPRc0YXU",
   "token_type":"Bearer",
   "expires_in":3598,
   "id_token":"cy5nb29nbGUuY29tIiwiaWQiOiIxMDQzOTI5"
}
    

Token string value can be easily fetched as string from JSON with JSOn serializer

string token = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(tokenResponse).access_token;
    

Facebook acess token

Facebook API has a pretty much the same approach. First code needs to be ackuired.

string authUrl = string.Format("https://www.facebook.com/dialog/oauth?client_id={0}&redirect_uri={1}&response_type=code&scope=email&state={2}",
           "APPLICATION_ID",
           "CALLBACK_URL",
           Guid.NewGuid().ToString());
            Response.Redirect(authUrl,true);
    

Parameter state is not mandatory, but it is useful to have it in case the same page handles callback from Google+ and Facebook (if state is not empty that it is Facebook callback, otherwise it is Google+ callback).

Return from Facebook will return code in querystring to a callback page. Facebook API does not care whether access token request is POST or GET, but to reuse code above, we'll make POST request just as for Google+. 

				var url = string.Format("client_id={0}&redirect_uri={1}&client_secret={2}&code={3}",
                    "APPLICATION_ID",
                    "CALLBACK_URL",
                    "CLIENT_SECRET", 
					Request["code"]);
                var req = WebRequest.Create("https://graph.facebook.com/oauth/access_token");
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                ASCIIEncoding encoder = new ASCIIEncoding();
                byte[] data = encoder.GetBytes(url);
                req.ContentLength = data.Length;
                req.GetRequestStream().Write(data, 0, data.Length);
				string tokenResponse = new StreamReader(req.GetResponse().GetResponseStream()).ReadToEnd();
    

However, Facebook does not return JSON, instead it return name-value pair string, so fetching token is a bit different

string token = tokenResponse.Replace("access_token=", string.Empty);
    

Disclaimer

Purpose of the code contained in snippets or available for download in this article is solely for learning and demo purposes. Author will not be held responsible for any failure or damages caused due to any other usage.


About the author

DEJAN STOJANOVIC

Dejan is a passionate Software Architect/Developer. He is highly experienced in .NET programming platform including ASP.NET MVC and WebApi. He likes working on new technologies and exciting challenging projects

CONNECT WITH DEJAN  Loginlinkedin Logintwitter Logingoogleplus Logingoogleplus

JavaScript

read more

SQL/T-SQL

read more

Umbraco CMS

read more

PowerShell

read more

Comments for this article