Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

Consuming OAUTH Enabled Restful WCF Service using JavaScript

4.17/5 (3 votes)
10 Sep 2014CPOL4 min read 28.5K   684  
Client Web Application which consumes OAUTH enabled restful WCF service using JavaScript

Introduction

This can be considered as an extension to the article Secure WCF RESTful service using OAUTH. In the earlier article, you can find the examples on how to create a restful WCF service using OAUTH and how to create a .NET based consuming application.

I have seen the comments section of the article and most of the people were requesting for how to consume the restful service using JavaScript code. So this has encouraged me to write my first ever article on CodeProject. I hope this would be helpful for people out there and further encourages me to write more.

I have modified the example so that a realistic scenario is considered. Before diving deep into the article, please download the required source code required for OAUTH.

Using the Code

Following are the methods which are exposed by our restful WCF service, alongside the description.

Method Description

GetBooksList

Gets the list books that are stored in the DB in the form of serialized List of Book .NET object as XML string. This method doesn’t require any OAUTH authentication for accessing.

GetBookById

Gets the book by ID. Queries the DB for the available book with the given ID and returns Book .NET object as XML string. This method doesn’t require any OAUTH authentication for accessing.

AddBook

Adds the book to the DB. This method doesn’t require any OAUTH authentication for accessing.

UpdateBook

Updates the book to the DB based on the ID passed. This method doesn’t require any OAUTH authentication for accessing.

DeleteBook

Deletes the book to the DB based on the ID passed. This method doesn’t require any OAUTH authentication for accessing.

GetBookNames

Gets the book names that are available in the DB as JSON object. This method doesn’t require any OAUTH authentication for accessing.

GetBookNames_WithOAuth

Gets the book names that are available in the DB as JSON object. This method requires OAUTH authentication for accessing

So we would require the last method in the list, which is our point of interest for this article. I would expose few lines of code which would be almost similar to our parent article.

C#
public List<string> GetBookNames_WithOAuth()
{
    try
    {
        if (Authenticate(WebOperationContext.Current.IncomingRequest))
        {
            using (LibraryEntities entities = new LibraryEntities())
            {
                return entities.Books.Select(b => b.BookName).ToList();
            }
        }
        else
        {
            WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.Unauthorized;
            return new List<string> { "Unauthorized Request." };
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

private bool Authenticate(IncomingWebRequestContext context)
{
    bool isAuthenticated = false;
    string normalizedUrl;
    string normalizedRequestParameters;
    
    NameValueCollection pa = context.UriTemplateMatch.QueryParameters;
    if (pa != null && pa["oauth_consumer_key"] != null)
    {
        string uri = context.UriTemplateMatch.RequestUri.OriginalString.Replace(context.UriTemplateMatch.RequestUri.Query, "");
        string consumerSecret = "secretkey";
        OAuthBase oAuth = new OAuthBase();
        string hash = oAuth.GenerateSignature(
            new Uri(uri),
            pa["oauth_consumer_key"],
            consumerSecret,
            null,
            null,
            "GET",
            pa["oauth_timestamp"],
            pa["oauth_nonce"],
            out normalizedUrl,
            out normalizedRequestParameters
            );
            
        isAuthenticated = pa["oauth_signature"] == hash;
    }
    return isAuthenticated;
}

There is nothing much to explain about this code. The web method would authenticate the request before returning the list of book names available in the DB. Authenticate method would get the reference from OAUTH class.

Now, we will create a client Web Application which will consume the above restful WCF service using JavaScript and OAUTH authentication.

Create a normal web application from Visual Studio with framework as .NET 4.0. Include oauth.js and sha1.js files downloaded from the GoogleCode links provided in the introduction section. Create a custom JavaScript file with name as ConsumeRest.js file. Below is the screen shot for how the solution explorer would look like.

Below is the sample code which needs to include in ConsumeRest.js file.

JavaScript
function consumeRestWCFService() {
    var accessor =
        {
            consumerSecret: "secretkey",
            tokenSecret: null,
            serviceProvider:
            {       
                accessTokenURL: "http://localhost:7776/libraryservice/OAuthBooks"
            },
            consumerKey: "test"
        };

    var message =
        {
            action: accessor.serviceProvider.accessTokenURL,
            method: "GET",
            parameters: []
        };

    message.parameters.push(["oauth_consumer_key", accessor.consumerKey]);
    message.parameters.push(["oauth_signature_method", "HMAC-SHA1"]);
    message.parameters.push(["oauth_version", "1.0"]);
    message.parameters.push(["oauth_timestamp", ""]);
    message.parameters.push(["oauth_nonce", ""]);
    message.parameters.push(["oauth_signature", ""]);

    OAuth.setTimestampAndNonce(message);
    OAuth.SignatureMethod.sign(message, accessor);
    var authorizationHeader = OAuth.getAuthorizationHeader("", message.parameters);
    var requestBody = OAuth.formEncode(message.parameters);
    var requestToken = newXMLHttpRequest();
    requestToken.onreadystatechange = function()
    {       
        if (requestToken.readyState == 4) {
            alert(requestToken.responseText);
        }
    };

requestToken.open(message.method, message.action + "?" + requestBody, true);
requestToken.setRequestHeader("Authorization", authorizationHeader);
requestToken.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
requestToken.send(null);
}

function newXMLHttpRequest() {
    try {
        return new XMLHttpRequest();
    } catch (e) {
        try {
            return new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
            try {
                return new ActiveXObject("Microsoft.XMLHTTP");
            } catch (e) {
                alert("Sorry, your browser doesn't support AJAX.");
                throw e;
            }
        }
    }
}

In the above JavaScript code, we are setting the values for accessor and message variables. Accessor variable would have all the defined values which are required for communicating with the restful WCF service. The consumerSecret attribute must be the same as that used in the WCF application, otherwise unauthorized access would be prompted. Also please change the accessTokenURL attribute, which is nothing but the WCF service URL.

We are pushing the required parameters to the message variable which is required for OAuth. OAuth.setTimestampAndNonce would set oauth_timestamp and oauth_nonce attributes of message variable. All these attributes would be required to generate a signature key and some encryption logic is used to generate this key. In this example, we are using SHA1 encryption to generate the signature key. OAuth.SignatureMethod.sign method would generate the signature key and set the oauth_signature attribute of message variable.

For sending the request asynchronously, we are using XMLHttpRequest and ActiveXObject. The remaining code is self-explanatory.

Create or use the existing Web form to call the method consumeRestWCFService(). I have written my code on default.aspx page by adding an anchor link with below as sample code. Also please add references to the JavaScript files that are used.

HTML
<script src="Scripts/sha1.js"></script>
<script src="Scripts/oauth.js"></script>
<script src="Scripts/ConsumeRest.js"></script>
<a href="javascript:consumeRestWCFService();">Call REST WCF</a>

If you look at the restful WCF service URL, it seems to be unusual as the .svc is missing. I have used the routing concepts of .NET 4.0 to route/rewrite the required URL. Below is the sample code of the same.

Needs to be written on the Interface:

C#
[OperationContract]
[WebGet(UriTemplate = "OAuthBooks", ResponseFormat = WebMessageFormat.Json)]
List<string> GetBookNames_WithOAuth();

Needs to be written on the Global.asax:

C#
protected void Application_Start(object sender, EventArgs e)
{
    RouteTable.Routes.Add(new ServiceRoute
    ("libraryservice", new WebServiceHostFactory(), typeof(BookService)));
}

Finally, when you execute your client application, you should be alerted with list of books available in the DB in JSON format. If you are facing any difficulty, please download the source code and help it yourselves. This example purely deals with JavaScript, this can be further extended to use jQuery. Hope this would be helpful for most people like me.

Happy coding!!! Cheers!!!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)