Skip to main content

Implementing OAuth2 consumer in C#

Recently I worked on a project that involved integrating with social networking and jobs websites like Elance. These days almost all major services that allow applications to access users' data, perform authorization/authentication using OAuth1.0 or OAuth2. OAuth2 compared to OAuth1 is very easy to implement. OAuth1 involves generating nonce,timestamp,signaturebase and signing the request with any algorithm like HMAC-SHA1 and appending data to query string of URL and passing in Authorization header of HTTP. OAuth2 removed all these requirements. Following is OAuth2 process in a nutshell
1) Redirect user to Authorization url passing client_id and redirect_url in query parameters
2) If user authenticates successfully through service provider it will redirect user to the redirect_url passed with authorization access code in query parameters.
3) After getting authorization access code you exchange this to receive access token. You make a POST HTTP request to a URL passing client_id , client_secret and authorization code.
4) After access token is received you can call API of service provider using that access token.
In this blog post I will implement OAuth2 for Elance in a desktop C# app. Elance provide you API Key (client_id) and secret code (client_secret) when you apply for new API keys.

Lets start by creating a class named OAuth2 that will hold variables that is common to all OAuth2 consumers.

namespace Usmani.OAuth2
{
    public abstract class OAuth2
    {
        public string AuthorizationUrl { get; protected set; }
        public string AccessTokenUrl { get; protected set; }
        public string RedirectUrl { get; protected set; }
        public string AuthorizationCode { get; protected set; }
        public string ClientId { get; private set; }
        public string ClientSecret { get; private set; }
        public string AccessToken { get; protected set; }
        public string RefreshToken { get; protected set; }

        protected string AuthorizationCodeParameter { get; set; }
        protected string ClientIdParameter { get; set; }
        protected string ClientSecretParameter { get; set; }

        public OAuth2(string clientId, string clientCode,string rUrl)
        {
            this.ClientId = clientId;
            this.ClientSecret = clientCode;
            this.RedirectUrl=rUrl;
        }

        protected string GetFullAuthorizationUrl(string queryStringToAppend)
        {
            return AuthorizationUrl + "?" + ClientIdParameter + "=" + ClientId + "&" + queryStringToAppend;
        }

        protected void SetAuthorizationCode(string queryStringPart)
        {
            NameValueCollection nvc = HttpUtility.ParseQueryString(queryStringPart);
            this.AuthorizationCode = nvc[AuthorizationCodeParameter];
        }

        protected string GetAccessTokenResponse(string queryStringToAppend, string postDataToAppend)
        {
            string fullUrl = AccessTokenUrl + "?" + queryStringToAppend;
            string postData = AuthorizationCodeParameter+"=" + HttpUtility.UrlEncode(AuthorizationCode);
            postData += "&" + ClientIdParameter + "=" + HttpUtility.UrlEncode(ClientId);
            postData += "&" + ClientSecretParameter + "=" + HttpUtility.UrlEncode(ClientSecret);
            postData += "&" + postDataToAppend;

            return HttpClient.postFormData(fullUrl,postData);
        }

        public abstract void GetAccessToken();
        public abstract void UserRedirectedAfterAuthorization(string queryPart);
    }
}

Now we will create class specific to Elance OAuth2 which will inherit from OAuth2.

namespace Usmani.OAuth2
{
    public class ElanceOAuth2 : OAuth2
    {
        public ElanceOAuth2(string apiKey,string consumerSecret,string redUrl)
            : base(apiKey,consumerSecret,redUrl)
        {
            this.AuthorizationUrl = "https://api.elance.com/api2/oauth/authorize";
            this.AccessTokenUrl = "https://api.elance.com/api2/oauth/token";
            this.RedirectUrl = "http://yourredirecturl";
            this.ClientIdParameter = "client_id";
            this.ClientSecretParameter = "client_secret";
            this.AuthorizationCodeParameter = "code";
        }

        public override void GetAccessToken()
        {
            string response = GetAccessTokenResponse(string.Empty, "grant_type=authorization_code");
            //Elance return response in Json format.I am using Newtonsoft Json library here
            JToken jobj = JToken.Parse(response);
            jobj = jobj.Value<JObject>("data");
            AccessToken = jobj.Value<string>("access_token");
            RefreshToken = jobj.Value<string>("refresh_token");
        }

        public override void UserRedirectedAfterAuthorization(string queryPart)
        {
            SetAuthorizationCode(queryPart);
        }
    }
}

GUI Part
We can perform following part in our GUI to allow user to login to elance and perform authorization and authentication.

ElanceOAuth2 elApi=new ElanceOAuth2("YOUR_API_KEY","CONSUMER_SECRET","REDIRECT_URL");
WebBrowser brw=new WebBrowser();
this.Controls.Add(brw);
brw.Navigated+=new WebBrowserNavigatedEventHandler(browser_Navigated);

brw.Navigate(elApi.GetFullAuthorizationUrl("scope=basicInfo&response_type=code"));

public void browser_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
    if (e.Url.AbsoluteUri.StartsWith(el.RedirectUrl))
    {
        elApi.UserRedirectedAfterAuthorization(e.Url.Query);
    }
}

Comments

  1. Whats up very cool blog!! Man .. Beautiful .. Superb ..
    I'll bookmark yiur blog and take the feeds additionally?
    I'm satisfied to find a lot of helpful info right here within the post, we'd like develop more techniques on this regard, thank
    you for sharing. . . . . .

    ReplyDelete

Post a Comment

Share your wisdom

Popular posts from this blog

Decoding JPEG image file using libavcodec

I got a chance to work on a video encoding application that decodes series of jpeg files and convert them into ogg theora video file. I used the infamous libavcodec library that is used in FFMPEG . I decided to write blog posts explaining how I decode jpeg images and convert them into ogg video file. This is the first part and in this I will explain how to decode jpeg images using libavcodec. To learn how to write decoded images as a ogg video file please read http://random-stuff-mine.blogspot.com/2017/07/encoding-raw-images-to-ogg-theora-video.html Before reading this blog post you must be aware of using and setting up libavcodec. I highly recommend this tutorial to get basics of using libavcodec http://www.ffmpeg.org/doxygen/0.6/api-example_8c-source.html Allocating input format context We will first allocate input format for reading the file. We will use avformat_open_input function that will allocate AVFormatContext structure passed to it , the function detects input typ

CryptographicException: An error occurred while trying to encrypt the provided data. Refer to the inner exception for more information

I created a new Blazor Server app in Visual Studio 2019 and tried to run it. But I was getting this error CryptographicException: An error occurred while trying to encrypt the provided data. Refer to the inner exception for more information. I couldn't find any reason or solution to this problem. I tried creating the project multiple times but same error. I created a new .Net Core Web App and added a new razor component and included that component in a razor page (cshtml file) like this @(await Html.RenderComponentAsync<GeofenceWork>(RenderMode.ServerPrerendered)) and <component type="typeof(GeofenceWork)" render-mode="serverprerendered" /> As soon as I navigate to this page that has component added I got the same error: CryptographicException: An error occurred while trying to encrypt the provided data. Refer to the inner exception for more information. This was very frustrating. After hours of trying and searching I figured out the solution. 

Encoding raw images to Ogg Theora video using libavcodec

In one of the blog posts we learned how to decode jpeg images using libavcodec. This is the second part of that post. In this we will learn how to encode decoded images (raw images) to theora and write them in ogg video file. In the end of the first part we saved our raw image in raw_data variable and its length in raw_data_size variable. Lets assume that we packaged all our decoding code in one function called "decode_jpeg_image" which has following signature int decode_jpeg_image(char *filename,int file_name_size,uint8_t *raw_data,int *raw_data_size) filename = name of jpeg file to decode file_name_size = length of jpeg file's name raw_data = contains decoded raw image on return raw_data_size = contains length of raw_data on return Now let's start working on how to encode this image in raw_data to theora and write that image to ogg video file. Finding Theora encoder We first have to find encoder for THEORA which is represented by AVCodec structure. He