This post is the seventeenth in a weekly series intended to briefly spotlight those things that you need to know about new features in BizTalk Server 2013. It is also the final part of a five-part series on REST support in BizTalk Server 2013.
I’m going to forego a long introduction this week by simply stating outright that we are going to see how it is possible to do OAuth with BizTalk Server 2013. That being said up front, I do want to take a few moments to recall where we have been, and what has led up to this post.
Re-cap of the RESTful Services Series
We’ve covered quite a bit of ground so far in this mini-series. If you have not yet read the parts leading up to this post, you will want to do so before we begin. You can find the pervious posts here:
Giving BizTalk 2013 the Valet Keys
If you’ve been listening to the messaging and buzz around BizTalk Server 2013, it would appear that one of the major focuses of the 2013 version is all about enabling integration with cloud-based services. Most of these services expose APIs that make it possible to automate that integration, and a growing number of those are RESTful APIs. Each service provider can choose the methods with which they perform authentication and authorization. However a fairly common choice1 is to use OAuth for authorization.
Let’s imagine that we’re going to use BizTalk Server 2013 to call the Salesforce API. Before we can make the API call, a call is made to request a special token (essentially a valet key) that will provide limited access to specific functionality within Salesforce for BizTalk Server’s use.
This means for each call that is made, a corresponding token request call must be made. How can we handle this? Ultimately, we could make BizTalk server do this any number of ways. We could use a custom pipeline component in the Send pipeline to request the token before making the call. We could setup an orchestration to coordinate these two sends – or we could even call into custom .NET code which will get the token. However, as with the CORs headers last week, I would rather push this need closer to the transport (since that’s closer to where the issue originates).
Making WCF Do the Heavy Lifting
Since, in our fictional scenario here, we’re dealing with a RESTful API, the WCF-WebHttp adapter will be in play. As a WCF adapter, we are able to take advantage of the WCF extensibility model during configuration via the Behavior tab of the adapter configuration:
What does this enable us to do? At the end of the day, it allows us to take full control of the message right before being transmitted over the wire (and even right after being received over the wire in the case of a reply). For the purposes of implementing OAuth, we can actually simply look to a portion of one of the tutorials that shipped as part of the product documentation for BizTalk Server 2013 on MSDN: Integrating BizTalk Server 2013 with Salesforce.
By reading the document linked above, you will find that the tutorial is taking advantage of the IClientMessageInspector interface to provide a last minute hook into the communications process. During that last minute in the BeforeSendRequest method, the OAuth token is being retrieved through a specially constructed POST request to the OAuth authorization endpoint (which can differ depending on which instance to which you have been assigned):
[sourcecode language=”csharp”] private void FetchOAuthToken()
if ((tokenExpiryTime_ == null) || (tokenExpiryTime_.CompareTo(DateTime.Now) <= 0))
StringBuilder body = new StringBuilder();
.Append("client_id=" + consumerKey_ + "&")
.Append("client_secret=" + consumerSecret_ + "&")
.Append("username=" + username_ + "&")
.Append("password=" + password_);
result = HttpPost(SalesforceAuthEndpoint, body.ToString());
// do something
// Convert the JSON response into a token object
this.token_ = ser.Deserialize<SalesforceOAuthToken>(result);
this.tokenExpiryTime_ = DateTime.Now.AddSeconds(this.sessionTimeout_);
NOTE: I do not advocate merely swallowing exceptions. You will want to do something with that WebException that is caught.
[sourcecode language=”csharp”]WebHeaderCollection headers = httpRequest.Headers;
headers.Add(HttpRequestHeader.Authorization, "OAuth " + this.token_.access_token);
While the tutorial provides instructions for registering extensions via the machine.config file, a ready alternative is available.
For any WCF-based adapter, each host can provide unique configuration data specifying extensions that are available for use by that adapter when executed by the host. Performing the configuration here can ease the configuration burden on those BizTalk groups containing more than a single machine.
Ready to REST
I highly recommend that you read that tutorial, and spend some time replicating that solution so that you can see what BizTalk Server 2013 is bringing to the table with regards to integration with RESTful services.
I hope that this series has also accomplished the same – that you can see the possibilities, the potential extensibility points, and have a greater appreciation for BizTalk Server 2013 as the integration tool ready to tackle those more tricky hybrid on-premise meets cloud scenarios.
Until next week, take care!
1 Just because it’s common does not mean it is the least complex or best choice – but it does mean that it can end up being one you’re stuck with.