sup { vertical-align:text-top; }

Saas

Connect Enterprise Apps With Hosted BizTalk Services

Jon Flanders and Aaron Skonnard

This article is based on a prerelease version of ASP.NET 3.5 and the Microsoft AJAX Library. All information herein is subject to change.

This article discusses:

  • BizTalk Services as an ESB service
  • WCF apps on BizTalk Services
  • Relayed connectivity options
  • Identity services and token providers
This article uses the following technologies:
BizTalk Services, .NET Framework 3.0

Contents

Software as a Service
Internet Service Bus
BizTalk Services
BizTalk Services SDK
A Typical WCF Application
Relayed Connectivity Options
Passing through Firewalls with RelayedHttp
Configuring the Identity Services
Custom Token Providers
How to Get Started

Today, more than ever before, businesses require the ability to quickly develop, deploy, and integrate new applications into their existing environments. This growing need for dynamic, loosely coupled applications is one of the primary reasons why many businesses have moved or are currently moving toward Service-Oriented Architecture (SOA) as the new foundation for their applications.

As companies move toward SOA, there is a stronger focus on composing systems from the various applications found throughout the enterprise. In this new world, it's the developer's job to orchestrate business processes from these various application services that are made available on the network by other teams and organizations, who may be using different implementation technologies or line-of-business applications, thereby increasing the overall system complexity. Although SOA simplifies each point-to-point connection, composite applications can become unwieldy to manage and somewhat brittle as the total number of service connections required by the application increases over time (see Figure 1).

fig01.gif

Figure 1 Managing Point-to-Point Connections in Composite Applications

This reality has led many companies to embrace a more loosely coupled and sustainable service pattern commonly referred to as the Enterprise Service Bus (ESB). The ESB model has grown in popularity because it helps enterprises manage multiple service connections through a central bus that provides an abstraction layer over the underlying messaging details. For example, an ESB helps broker differences across services in terms of naming convention, identity management, message formats, and communication protocols. Once a service gets on the bus, anything else on the bus can connect to it, even if it wouldn't normally be able to communicate with the service directly (see Figure 2).

fig02.gif

Figure 2 Building Composite Applications with an ESB

This model introduces a level of indirection between the various services on the bus and between composite applications and the services they consume. ESBs also provide various messaging features including publish/subscribe functionality, which provides for looser coupling throughout the system. With publish/subscribe, consumers no longer have to be directly connected to services anymore—everything just needs a connection to the bus—and nodes can be added or removed at will. ESBs usually also provide a process flow engine for orchestrating the messaging interactions that make up a business process—this layer is often referred to as orchestration or workflow.

One way to build systems that employ the ESB pattern on the Microsoft platform is to use BizTalk® Server. BizTalk Server provides all of the ESB features we've discussed here out of the box.

Software as a Service

While ESBs have been growing in popularity within the enterprise, another business trend has also been blossoming on the Web that will surely impact enterprise systems in the years ahead. This trend, referred to as Software as a Service (SaaS), revolves around companies exposing complete applications or services on the Web—sometimes referred to as the Internet cloud—that other companies can simply pay to use. This allows consumers to avoid the complexities and costs associated with building or managing a similar piece of software (design, development, operational, and maintenance costs), which usually require large initial investments.

The SaaS model essentially allows consumers to remotely access software hosted by another company with expertise in a particular area (such as CRM, accounting, payroll, data storage, e-mail, and so on), as illustrated in Figure 3. With SaaS, the provider usually offers a complete solution for a particular software need, allowing the consumer to outsource that particular part of the system. The service provider manages the software over time and simply charges the consumer for usage, which means the consumer no longer has to manage those software services locally.

fig03.gif

Figure 3 Outsource Software Needs with SaaS

The applications or services offered by SaaS providers typically embrace standard Web protocols and data formats in order to increase their ease-of-use and potential reach. Today they tend to rely heavily on HTTP and on common Web data formats like XML, RSS, and JSON, which are ubiquitous today. Although SaaS does not constrain a provider to these specific choices, reach requirements often force providers in that direction.

Some architects may question how smart it is to take on the external dependencies that are inherent in an SaaS system architecture. Although they might raise concerns around connectivity and service level agreements (SLA), with the ubiquity of Internet connections today, it seems that exposing software on the Web has almost become completely acceptable and even extremely advantageous given the new doors it opens.

Internet Service Bus

Microsoft has embraced these popular ideas—ESB and SaaS—and has blended their most compelling characteristics into a new idea it calls the Internet Service Bus (ISB). The ISB model is similar to ESB in terms of functionality. However, ISB is made available at the broader Internet scope, so it's similar to the SaaS model in terms of standards, reach, and scalability. The Microsoft® ISB, in a nutshell, makes it easier for companies to adopt ESB infrastructure.

Although ESB functionality is compelling to a wide range of companies, it seems that only larger companies have significantly taken advantage of them today. This is mostly due to the upfront investment and financial risk associated with adopting a significant piece of infrastructure like an ESB. Instead, many companies end up creating their own custom—and often more costly—systems integration infrastructure. This happens to be one of the biggest impediments to BizTalk Server adoption today.

Further, companies able to implement an ESB are still challenged with trying to make their ESB talk to their partners' ESBs. No two ESB instances are alike, making cross-enterprise integration difficult, even when embracing the loosely coupled ESB pattern.

The Microsoft ISB platform addresses these realities by placing key service bus components in the Internet cloud for public consumption regardless of the platform using the components. Microsoft is essentially making the service bus available through the SaaS model, thereby allowing companies of any size to jump on the bus. ISB offers a publish/subscribe architecture and the necessary messaging infrastructure for traversing enterprise firewalls and network address translators (NATs). ISB also offers federated identity management and a workflow services layer for hosting custom business processes on the Web, as illustrated in Figure 4.

fig04.gif

Figure 4 Building on the New Internet Service Bus

Microsoft is actively working on making ISB a reality, and you can follow its work on the BizTalk Services Web site (see msdn.microsoft.com/biztalk). The current Community Technology Preview (CTP) offers several fundamental services that you can begin experimenting with today. In the years ahead, Microsoft plans for this initiative to blossom into a rich communication fabric capable of providing powerful building blocks for a wide variety of modern connected applications.

However, it's important to remember that, as a CTP, the bits made available today are only meant for experimentation and gathering feedback—they are not meant for production use. Microsoft provides no quality guarantees at this point. Also, Microsoft has not yet announced how it will charge for ISB usage once it's ready for production use.

BizTalk Services

BizTalk Services is the initial implementation of the ISB components that reside on the Web. Today BizTalk Services consists of a few core services including BizTalk Connectivity Services and Biz­Talk Identity Services. Another key service called BizTalk Workflow Services will become available in the very near future. More services will be added by Microsoft over time, and additional services might also be placed on the ISB by third parties.

Let's discuss each of the current core services in more detail. One of the most challenging problems when creating loosely coupled composite apps is managing how services will connect at the network level. For example, you might have one service that resides in the network perimeter and another service that resides inside the firewall, and they need to communicate with each other. Or you might want to expose a service to business partners, but those partner services are behind firewalls of their own or other network devices such as proxies or NATs.

BizTalk Connectivity Services simplifies many of these communication challenges by providing a universal naming convention for services along with a mechanism for direct/indirect communication between two nodes independent of network topology and configuration. It does this by providing a controlled mechanism for securely relaying connections through network devices. That said, in the cases where a direct connection can be made, BizTalk Connectivity Services can also get out of the way and let the nodes connect without relaying traffic.

You can certainly write this type of code yourself, although it can be challenging and cumbersome. The main advantage of letting BizTalk Services provide this functionality is that you don't have to write or maintain that code, which is often customized per endpoint. This frees you to concentrate on writing the code to solve your business problem rather than coding around these infrastructure problems. BizTalk Connectivity Services also provides other key features such as a global naming convention based on uniform resource identifiers (URIs), a simple publish/subscribe mechanism, and even multicast capabilities.

Another core part of BizTalk Services is the BizTalk Identity Services, a publicly accessible Security Token Service (STS) that conforms to the WS-Trust standard. WS-Trust is an interoperable standard for negotiating security based on trust relationships between parties. For example, one party can authenticate a client and issue a token that contains a set of claims about the client. That token can then be presented securely to other parties who also happen to trust the original party that issued the token. This approach makes it possible to federate valuable identity information across organizational boundaries.

Given this, BizTalk Identity Services can be used as a third-party identity and authentication management service even if you don't employ any other features like BizTalk Connectivity Services. However, when using the other BizTalk Services, BizTalk Identity Services will always be used to authenticate and authorize users.

When using BizTalk Connectivity Services, both the client and the service will be authenticated against BizTalk Identity Services using either a username/password, client certificate, or a managed card. Once authenticated, a set of authorization rules are processed to issue a new token that will be supplied to BizTalk Connectivity Services. The BizTalk Services Web site provides a user interface for managing your authorization rules along with a few programmatic APIs including a RESTful interface.

BizTalk Workflow Services has not yet been released for public consumption. However, a future release of BizTalk Services is expected to provide the capability to host workflow services based on Windows® Workflow Foundation (WF) on ISB. Workflows will activate based on messages received by ISB at a particular URI. These are the only details currently available.

BizTalk Services SDK

The BizTalk Services SDK is a free download available from msdn.microsoft.com/biztalk that will enable you to get started programming against ISB. Before you can get started, you'll need to install the BizTalk Services SDK and create a user account on the BizTalk Services site. BizTalk Services is built on Windows Communication Foundation (WCF). The SDK is just a set of assemblies built on the Microsoft .NET Framework 3.0 that allows you to use ISB via the WCF programming model.

Most of the BizTalk Services SDK is found in the System.ServiceBus assembly. System.ServiceBus uses standard WCF extensibility points to define a new binding named RelayBinding. For those not familiar with WCF, a binding determines what kind of communication will be exposed or used by a service endpoint. Bindings are used by the WCF runtime to create the communication layer, known as the channel stack, for sending and receiving messages. The objects in the channel stack perform the network communication, and they determine how security and other protocols are implemented for a particular endpoint.

On the listener side, the RelayBinding enables you to expose an endpoint that will be accessible through a global URI supported by BizTalk Connectivity Services. When an endpoint using RelayBinding has been opened, the URI will be registered with BizTalk Connectivity Services and from that point forward any authorized client will be able to send messages to that global URI using a similarly configured client. BizTalk Connectivity Services then becomes the conduit for communication between those two endpoints.

A Typical WCF Application

Let's take a closer look at a simple example. Imagine that we're a company and we currently expose a WCF service on our internal network that is called from a rich client application. The client application is used by salespeople to process orders. The application calls the service, and then the service initiates the back-end processing necessary to fulfill the order.

The service is currently configured with a single endpoint using NetTcpBinding, which enables high-speed connections over TCP/IP. NetTcpBinding is generally the best option for services operating within the firewall.

Here's the code that configures the endpoint and starts the service using the standard ServiceHost:

ServiceHost sh = new ServiceHost(typeof(SalesService));
sh.AddServiceEndpoint(typeof(ISalesService), 
  new NetTcpBinding(),
  "net.tcp://salesservicehost/SalesService");

sh.Open();
...

This is standard WCF code. The service implementation is the type SalesService and the contract is ISalesServices. The ServiceEndpoint, created when AddServiceEndpoint is called, uses NetTcpBinding and has an address of net.tcp://salesservicehost/SalesService.

Instead of hardcoding the endpoint this way, we could have also configured the endpoint in the application's configuration file (which is how you'd typically do it). But this sample should be easier to follow by keeping everything in code. Here is a sample client application that then invokes the SalesService to process a sale:

static void MakeSale(SaleData sd) {
  EndpointAddress ea = new EndpointAddress(
    "net.tcp://salesservicehost/SalesService");
  ChannelFactory<ISalesService> cf = 
    new ChannelFactory<ISalesService>(new NetTcpBinding(), ea);
  ISalesService service = cf.CreateChannel();
  service.EnterSale(sd);
}

As time goes on, the sales force becomes more mobile, and reports begin coming in that some salespeople aren't able to connect to process orders when they are out of the office and attached to random networks (some of which don't allow Virtual Private Network, or VPN, connections).

BizTalk Services is able to solve this problem. Let's see what it takes to expose SalesService via BizTalk Connectivity Services:

ServiceHost sh = new ServiceHost(typeof(SalesService));
sh.AddServiceEndpoint(typeof(ISalesService), 
  new RelayBinding(),
  "sb://connect.biztalk.net/services/contososervices/SalesService");

sh.Open();
...

As you can see, in order to expose the service through BizTalk Services, all we have to do is change one line of code—the call to ServiceHost.AddServiceEndpoint. Instead of NetTcpBinding, we use the RelayBinding, which in turn uses BizTalk Connectivity Services to expose this endpoint to the world at the specified URI. Messages sent to that address are then relayed to the local Sales­Service instance.

Notice the format of the URI—it begins with the "sb" scheme and is followed by the BizTalk Services host name, which is then followed by "services." After that, we add the BizTalk Services identity (the account name we've set up), in this case it's contososervices. Then we can add anything we want to the URI in order to make it unique. Here we've simply appended SalesService.

When you call ServiceHost.Open, the RelayBinding causes WCF to communicate with BizTalk Identity Services in order to authenticate the service identity and to authorize it to listen on the specified URI. The default behavior at this point is for the Windows CardSpace™ selector to appear, asking someone to select a card representing the service's identity.

The fact that a UI appears during authentication is obviously prohibitive for most services since they generally run in headless environments where there isn't someone logged into the machine. However, we can get around this problem with a little code, which we'll show you later, so don't be concerned. For now, we're just going to select a card that will enable SalesService to begin listening. You can manage which identities are allowed to listen on a particular URI with BizTalk Identity Services.

Now let's look at what it will take to update the client so that it can consume the BizTalk Services endpoint:

static void MakeSaleISB(SaleData sd) {
  string uri =   
    "sb://connect.biztalk.net/services/contososervices/SalesService";
  ChannelFactory<ISalesService> cf = new ChannelFactory<ISalesService>(
    new RelayBinding(), new EndpointAddress(uri));
  ISalesService service = cf.CreateChannel();
  service.EnterSale(sd);
}

Notice that the client and service stay exactly the same except for using RelayBinding and specifying the service bus (sb://...) URI. The client will also see the Windows CardSpace selector by default, allowing the client to select an identity, which is then sent to BizTalk Identity Services for authentication and authorization. If the client is authorized to send messages to the specified URI, BizTalk Identity Services will return a token indicating that fact, which is then passed to BizTalk Connectivity Services as proof.

Having the Windows CardSpace selector appear in this scenario seems pretty acceptable since it's an interactive client application. Again, you can manage which client identities are allowed to send to a particular URI using BizTalk Identity Services.

When BizTalk Connectivity Services receives an incoming message from an authorized sender, it simply relays the message to an instance of SalesService running locally. You shouldn't really care how it does this because it's an implementation detail that will very likely change in the future. However, under the covers, Relay­Binding uses WCF's TcpTransport to connect to BizTalk Connectivity Services. When relaying messages, BizTalk Connectivity Services can tunnel through the existing TCP connection back to the local service instance.

Why was this so simple? Because BizTalk Connectivity Services takes advantage of standard WCF extensibility points to encapsulate the connectivity and relay logic for both the client and the service inside the new RelayBinding. The fact that you can make fundamental communication changes by simply changing the binding (which can be done entirely in configuration) is one of the real advantages of adopting the WCF programming model.

Relayed Connectivity Options

One of the important properties on the RelayBinding object is ConnectionMode. The property's type is an enum named RelayedConnectionMode. This setting determines how the connection to BizTalk Connectivity Services is made. BizTalk Connectivity Services allows for numerous communication modes between senders and receivers that offer a great deal of flexibility for specific communication scenarios (see Figure 5).

Figure 5 RelayBinding ConnectionMode Options

ConnectionMode Value Description
RelayedOneWay The connection is set up to accept or send one-way operations only. To use this setting, all methods on your service contract must have an OperationContractAttribute with its IsOneWay property set to true.
RelayedDuplex The connection is set up to support request-reply contracts (including duplex contracts).
RelayedDuplexSession Same as RelayedDuplex but configured to use WS-ReliableMessaging.
DirectDuplexSession Same as RelayedDuplexSession with an optimization. The initial connection between sender and receiver will use BizTalk Connectivity Services, but then it will try to bridge a direct connection between the two nodes if possible. If a direct connection can be made, the sender and receiver will then communicate without BizTalk Connectivity Services in the middle. If a direct connection can't be made, BizTalk Connectivity Services will continue to provide a relay for communication.
RelayedMulticast The connection is set up to provide publish/subscribe capabilities. Multiple listeners can register with the same address when using this mode. To use this setting, all methods on your service contract must have an OperationContractAttribute with its IsOneWay property set to true.
RelayedHttp The connection is set up to expose an HTTP endpoint via BizTalk Services that relays back to a service running on a machine on your local network, even if that service would not normally be accessible through the Internet.

RelayedOneWay is meant for one-way messaging scenarios, hence you can only use it with operations marked with IsOneWay=true. RelayedDuplex, on the other hand, is meant for request-reply scenarios including duplex contracts. RelayedDuplexSession is just like RelayedDuplex, but it also enables reliable messaging within the channel stack. This is the default connection mode so it's the one we actually used in the previous examples. Additionally, the DirectDuplexSession mode is an optimization of RelayedDuplexSession in that it attempts to bridge a direct connection between the sender and receiver if possible. If it cannot, it will fall back to relaying the traffic.

We're going to dive into the last two connection modes in more detail. First, RelayedMulticast enables publish/subscribe over WCF, a communication pattern that isn't available from any of the built-in WCF bindings. Additionally, RelayedHttp allows you to expose HTTP-based endpoints from within a corporate firewall or behind a NAT, something that developers have struggled with since the advent of Web services.

BizTalk Connectivity Services allows multiple listeners to register themselves at a URI when RelayedMulticast is specified by the first listener. Each ServiceHost that has an endpoint listening on that same URI implicitly becomes a subscriber. When a client sends a message to that URI, the message is delivered to all service endpoints currently subscribed. The only real constraint when you use RelayedMulticast is that, like RelayedOneWay, all operations must be marked with IsOneWay=true.

Let's return to our previous sales application. Assume that periodically during the day, we update the price of the different items being sold. We want to broadcast new prices to all salespeople so they are instantly aware. To make this happen, each client application can start a ServiceHost and listen to the same URI using the RelayBinding with ConnectionMode set to RelayMulticast:

ServiceHost sh = new ServiceHost(typeof(PriceUpdateService));
sh.AddServiceEndpoint(typeof(IPriceUpdateService),
  new RelayBinding(RelayConnectionMode.RelayedMulticast),
  "sb://connect.biztalk.net/services/contososervices/priceupdate");
sh.Open();
...

Each client runs this code when the application starts, and thus all client applications will be subscribers to messages sent to sb://con­nect.biztalk.net/services/contososervices/clientupdate. Each client has now become a subscribing service for purposes of this contract and URI. In this scenario, the back-end system plays the role of the WCF client and broadcasts (publishes) a message to all subscribers, as illustrated here:

static void DoPriceUpdate(PriceUpdate pu) {
  EndpointAddress ea = new EndpointAddress(
    "sb://connect.biztalk.net/services/contososervices/priceupdate");
  ChannelFactory<IPriceUpdateService> cf = 
    new ChannelFactory<IPriceUpdateService>(
      new RelayBinding(RelayConnectionMode.RelayedMulticast), ea);
  IPriceUpdateService service = cf.CreateChannel();
  service.UpdatePrice(pu);
}

When UpdatePrice is called, the PriceUpdate message is sent to BizTalk Connectivity Services, which then relays the message to all the services currently subscribed to the same URI.

Passing through Firewalls with RelayedHttp

RelayedHttp mode enables you to take an HTTP service running on your local network and expose it through BizTalk Connectivity Services via HTTP on the public Web, even if that service would not normally be directly accessible from outside your network. This feature is especially handy when used in conjunction with the new WCF Web programming model found in the .NET Framework 3.5.

This new Web programming model makes it easier to implement RESTful Web services with WCF. It also provides features that make it easy to integrate your WCF services with existing RSS/Atom and AJAX infrastructure found on the Web today. Biz­Talk Services doesn't require the .NET Framework 3.5, but given these new WCF features, RelayedHttp mode has more functionality when you have the .NET Framework 3.5 installed.

Going back to the sales application, sometimes salespeople are not running the rich client application, but they still need to be notified of the latest pricing information. One interesting way to expose data that is updated often is through a Web feed—an HTTP endpoint that returns well-known XML formats, such as RSS or Atom, to applications that know how to consume those feeds. Web feeds can be polled for new content on a set schedule by a feed reader (the common name for a program that aggregates Web feeds into a human-facing UI). This enables the end user to receive updates without actively navigating to the site but rather by looking at his feed reader.

Using the WCF Web programming model, we can easily build a Web feed that exposes the price update data. The first thing we need is a contract that uses the new WCF attributes for enabling HTTP invocations. These attributes inform the WCF messaging layer how to route incoming HTTP requests to the methods on the service based on the URI rather than the SOAP Action header. Here's an example:

[ServiceContract]
public interface IPriceUpdateFeed {
  [OperationContract()]
  [WebGet(UriTemplate = "*")]
  Atom10FeedFormatter GetPriceUpdate();
}

Here WebGetAttribute tells WCF that this method should be called whenever an HTTP GET request arrives at the service (in contrast to SOAP requests, which always use HTTP POST).

Also note the UriTemplate property on WebGetAttribute. This tells WCF exactly how to route incoming messages to different methods based on the URI of the incoming request. This example uses a wildcard template ("*") to indicate that we want all GET requests routed to this particular method. You could easily configure multiple methods on a service, each of which handles a different UriTemplate. There's also a WebInvokeAttribute that you can use when you want to respond to other HTTP verbs besides GET (including POST, PUT, DELETE, and HEAD).

The other thing to notice about this contract is the method's return type. The WCF Web programming model includes new types specifically designed to help produce today's standard feed formats. The two major formats supported today are Atom and RSS. The example here uses the Atom format.

Figure 6 shows a simple implementation of the GetPriceUpdate operation that produces an Atom syndication feed. This implementation uses the new SyndicationFeed API for producing a logical feed, which it returns wrapped in an Atom10FeedFormatter object in order to produce the correct XML format.

Figure 6 Producing a Web Feed

public Atom10FeedFormatter GetPriceUpdate() {
  SyndicationFeed feed = new SyndicationFeed("Product Update Feed",
    "", null);
  List<SyndicationItem> items = new List<SyndicationItem>();
  feed.Items = items;
  IEnumerable<Product> products = GetUpdatedProducts();
  string iText = "Product update for {0}. Old price={1}. New Price={2}";
  foreach (var product in products) {
    items.Add(new SyndicationItem("Product update for " + product.Name,
      String.Format(iText, product.Name, product.OldUnitPrice,   
      product.UnitPrice),
      null, 
      product.Name, 
      product.UpdatedTime));
  }
  return new Atom10FeedFormatter(feed);
}

Now we need to configure an endpoint to listen for these requests. WCF 3.5 comes with a new binding class to make configuring the endpoint very easy. The WebHttpBinding class encapsulates the details around creating a RESTful channel stack that won't expect SOAP messages. It simply uses the HTTP transport and the text-based message encoder from WCF, with the message version of the encoder set to None. Here is the code required to get our new endpoint hooked up and running:

ServiceEndpoint se = 
  sh.AddServiceEndpoint(typeof(IPriceUpdateFeed), 
  new WebHttpBinding(), "https://localhost:8099/ProductFeed");
se.Behaviors.Add(new WebHttpBehavior());
...

Notice that the WebHttpBinding endpoint is configured with an instance of WebHttpBehavior, which injects the necessary HTTP-based dispatching logic into the runtime. Once you have the Service­Host up and running with this new endpoint configured, you can browse to the HTTP URI the service is listening to at localhost:8099/ProductFeed, and you should see the Atom feed.

Now suppose we want to expose this feed to salespeople who are not on the internal network. Rather than expose this machine through the firewall, we can simply use BizTalk Connectivity Services to relay the HTTP traffic to our local service. We accomplish this by adding another endpoint using the RelayBinding but specifying RelayedHttp for the ConnectionMode, as illustrated here:

ServiceEndpoint se = 
  sh.AddServiceEndpoint(typeof(IPriceUpdateFeed),
  new RelayBinding(RelayConnectionMode.RelayedHTTP),
  "https://connect.biztalk.net/services/contososervices/ProductFeed");
se.Behaviors.Add(new WebHttpBehavior());
...

With this in place, our service is now securely exposed on the public Web, but the logic is hosted on an internal server. In Figure 7, you can see this feed exposed through a public, Internet-accessible URI. Of course, the feed looks exactly the same, and now salespeople on the road can subscribe to this feed and get updates without any complications around VPNs, firewalls, or network issues.

fig07.gif

Figure 7 Exposing an HTTP Service through BizTalk Connectivity Services

Configuring the Identity Services

Regardless of the connection mode you use with RelayBinding, both the Listener (service) and the Sender (client) must be authenticated and authorized against BizTalk Identity Services. Authentication is the process of identifying the client or requestor given an initial set of claims. Authorization is the process of applying a set of user-defined authorization rules on that initial set of claims.

The authorization rules simply produce a new set of claims through a series of claim transformations (each rule maps a set of input claims to a set of output claims).The initial set of input claims are those presented to BizTalk Identity Services by the requestor. Today BizTalk Identity Services supports three types of initial claim sets: username/password, client certificate, and managed cards. In the case of username/password, the username is the initial claim and the password is the evidence of that claim.

BizTalk Identity Services begins processing the authorization rules using the username claim as the starting point to produce output claims. As new claims are produced, they can serve as input claims for other rules, allowing for a degree of rule-chaining. The final set of output claims is what's contained in the token returned by BizTalk Identity Services. When you're attempting to access BizTalk Connectivity Services, certain output claims must be present.

You can also configure BizTalk Identity Services with a certificate to protect the tokens it produces. When a certificate is configured, the token provided to the requestor will be encrypted with the public key from the certificate, and thus it will be safer traveling on the wire and less susceptible to client tampering in transit.

There are a few ways to configure these authorization rules. One way is through the UI provided on the BizTalk Services Web site (see Figure 8). The other way is programmatically using the Identity Management API found in the SDK. Recently, a RESTful version of that interface was also released.

fig08.gif

Figure 8 BizTalk Services Web Site Claim Mapping UI

When you configure your authorization rules, you'll want to think about how you are using BizTalk Identity Services. Again, you can use BizTalk Identity Services as a generic STS or as your BizTalk Connectivity Services access control mechanism.

When using BizTalk Identity Services as a generic STS, you can map incoming username input claims to any output claim. The output claim will be placed in the resulting token that can then be presented to other parties. When using it this way you must have at least one rule where the input claim is username. You can add more rules that cascade based on new output claims—for example, taking the output claim produced by the username rule as the input claim for another output claim—allowing you to build up an arbitrary set of output claims. See the AccessControl samples in the BizTalk Services SDK for a complete example.

In order to authenticate with BizTalk Connectivity Services, you need to make sure you configure BizTalk Identity Services with a few specific rules. As mentioned, you must have at least one rule where the input claim is username, and you may also have cascading rules.

Where BizTalk Connectivity Services is unique, however, is that it will expect to find a Resource#Operation output claim in the final token, where the resource must be the service's listening URI and the operation must be either Listen or Send. For example, {URI}#Listen allows the user to start a service endpoint listening on the specified URI, whereas {URI}#Send allows the user to send a message to the specified URI.

Custom Token Providers

Earlier we mentioned it's usually odd for a server application to have an interactive login screen like the Windows CardSpace selector appear when the server begins listening. This happens because each endpoint that uses RelayBinding employs an object that implements the ITokenProvider interface. The default implementation for this interface is CardspaceTokenProvider, which causes the Windows CardSpace selector to appear when a connection is made to BizTalk Connectivity Services.

In addition to CardspaceTokenProvider, the SDK contains a few more implementations of ITokenProvider. UsernameToken­Provider retrieves a token using a registered username and password from the BizTalk Identity Services. AutomaticRenewalTokenProvider causes the Windows CardSpace selector to appear, but it will automatically get a new token before the current token expires, enabling configure-once endpoints. Both of these implementations are also endpoint behaviors that can be added to a client or service endpoint to replace the default CardspaceTokenProvider.

Our service can now avoid the interactive login by configuring UsernameTokenProvider on its endpoint before calling ServiceHost.Open, as shown here:

ServiceHost sh = new ServiceHost(typeof(SalesService));
ServiceEndpoint se = sh.AddServiceEndpoint(typeof(ISalesService),
  new RelayBinding(),
  "sb://connect.biztalk.net/services/contososervices/SalesService");
UsernameToken token = new UsernameTokenProvider("someusername", 
  "somepassword");
se.Behaviors.Add(token);
sh.Open();
...

So now whenever the service process starts, it will automatically authenticate with BizTalk Identity Services without any human intervention. Alternate implementations of ITokenProvider can also be configured on your RelayBinding endpoint by simply adding the implementation as an endpoint behavior (the TokenProvider base class found in the SDK implements both ITokenProvider and IEndpointBehavior).

How to Get Started

If you'd like to get started with BizTalk Services, first browse to labs.biztalk.net and create an account. You'll need to ensure that you have the .NET Framework 3.0 installed, and then you can download and install the BizTalk Services SDK. Once you have an account in place and the SDK installed on your machine, you should be able to recreate the samples we've shown you in this article. Of course, you'll need to change the account name used in the URIs from "contoso" to your account name. Also, the SDK comes with some additional samples for your perusal, which may help better illustrate some of the concepts we've covered. As you get started, if you have additional questions, be sure to check out the FAQ on the BizTalk Services site. Good luck!

Jon Flanders is an independent consultant, speaker, and trainer for Pluralsight. He specializes in BizTalk Server, Windows Workflow Foundation, and Windows Communication Foundation.

Aaron Skonnard is a cofounder of Pluralsight, a premier Microsoft .NET training provider. Aaron is the author of numerous books, white papers, and articles as well as Pluralsight's Applied Windows Communication Foundation, Applied BizTalk Server 2006, and Applied Web Services courses.