Yossi Dahan [BizTalk]

Google
 

Tuesday, January 13, 2009

Calling a service with federated identity from BizTalk Server [2009] – Part I

Finally I’ve reached the point where I’m ready to hook up BizTalk to my STS implementation to participate in a federated identity scenario.

My goal is to confirm two scenarios -

1. Being able to call from a BizTalk process a service that uses the ws2007FederationHttpBinding (and requires that the caller provide a token issued by a specific STS)

2. Being able to expose a service in BizTalk that would use the ws2007FederationHttpBinding requiring the caller to provide such token.

If you followed my previous posts you would probably know that I already have a fairly extensive federated identity scenario – I have a custom STS built using the Geneva Framework, a few web sites and a test WCF service all use the STS for their authentication (and, indirectly, authorisation), so it is just a case of hooking BizTalk to all of that, and to start with I decided to try and consume that test service from a BizTalk process.

I’m using BizTalk 2009 Beta to keep things interesting, but I’m pretty sure it would all be exactly the same for R2.

The beginning was easy – in my BizTalk project I’ve used the “Consume WCF Service” wizard from the “Add Generated Items” menu to generate all the artifacts needed to consume my service; the generation went very smoothly and soon enough I had an orchestration that could receive a dummy trigger message, create the service request, receive the service response and deliver it to a send port for me to check it out.

I’ve deployed the project and then imported the binding file generated by the wizard to create the WCF send port.

Checking the port configuration, though, I found a few issues -

The port uses the WCF-Custom adapter, which was correctly configured with the service’s endpoint and the ws2007FederationHttpBinding; however – my STS endpoint is configured to use the ws2007HttpBinding and requires UserName credentials, but these settings were not copied over to the client configuration from the service's contract, the client configuration should have looked like -

<security mode="Message">
  <message algorithmSuite="Default" issuedKeyType="SymmetricKey"
    issuedTokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1"
    negotiateServiceCredential="true">
    <issuer address="[STS URL HERE]” binding="ws2007HttpBinding" bindingConfiguration="stsBinding">
      <identity>
        <dns value="STS"/>
      </identity>
    </issuer>
    <issuerMetadata address="[STS MEX ENDPOINT HERE]" />
  </message>
</security>

(with corresponding Ws2007HttpBinding named stsBinding with all the relevant configuration), but the binding attribute and the bindingConfiguration attribute were missing.

It is worth noting here that this problem is by no means BizTalk specific – exactly the same thing (missing configuration) happens when I add a reference to my service from a ny standard .net app.

Also worth noting that in my case, and I don’t know how representing this is, this resulted in WCF trying to open the CardSpace card selector when I tried running the process, resulting in an error - “The channel is configured to use interactive initializer 'System.ServiceModel.Security.InfocardInteractiveChannelInitializer', but the channel was Opened without calling DisplayInitializationUI.  Call DisplayInitializationUI before calling Open or other methods on this channel.”

Easy enough to fix, I thought, as I opened the adapter’s configuration for the send port finding that indeed there are the equivalent fields in the UI (the image shows them AFTER I have typed in the values I needed) -

image

However, after adding the missing two values and confirming the changes I kept getting the same error; it only took two minutes of head scratching to realise what was going on – opening the send port configuration again showed that the values I’ve carefully typed in have not been persisted, and are now gone again; this must be a bug, which I’ve since confirmed exists in BizTalk 2006 R2 as well;in fact – even the issuer address, which was previously there, was removed from the configuration when trying to apply my additions.

Luckily importing these settings through a bindings file does work (as was evident from the fact that the issuers address did exist initially), and so I’ve edited my bindings file manually to include the missing settings (as well as the issuer identity setting which I later found out was missing for my scenario) and imported it using the admin console; checking the send port configuration I could now see my values for the “binding” and “bindingConfiguration” properties.

This raised another question, though – how do I configure this binding? ws2007FederationHttpBinding is somewhat “special” in the sense that there’s effectively an endpoint inside an endpoint:

Using this binding you have your service’s endpoint and it’s binding configuration; then the message security element of the ws2007FederationHttpBinding has the issuer element which is effectively the endpoint of the STS with the address, the binding and the binding configuration (there is no need for a contract attribute as the contract is known – it is the wsTrust contract); this means that I now need to have another set of binding configuration in my WCF configuration – for the STS – which in my case uses ws2007HttpBinding, but there isn’t a way to add another binding through the send port configuration dialog directly.

Initially I tried to add the relevant configuration to the BizTalk configuration file (BTSNTSVC.exe.config), but it didn’t work – and I can’t quite explain why yet.; what did work, which is good enough for me for now, was to put that exact same configuration in the machine.config; no idea why, but it works.

Another options, described in the documentation  is to use the Import option or the ExplorerOM API.

And so – once I’ve done that, when I ran my process it called the send port going to my service, but the WCF adpater contacted my custom STS first, retrieved a security token from it, and then called my test service passing this token, which meant the service was allowed to execute.

I’m impressed!

There is one, fairly big, inefficiency here now, though – BizTalk does not appear to be caching service proxies, which means it will not cache anywhere the issued token, which in turn means a call to the STS must precede every call to my protected service; not ideal.

Luckily - one of the WCF samples provided by MS demonstrates how to create a behaviour that would cache such tokens locally; at some point (probably not right now, unfortunately) I will have to see how well this plugs into BizTalk (if at all), but I suspect it’ll work well; find that sample here.

Labels: , , ,

6 Comments:

  • Thank you, thank you, thank you! This post really helped me out.

    By Blogger Michael Brandt Lassen, at 30/06/2010 10:53  

  • :-)

    You're most welcomed. glad to hear!

    By Blogger Yossi Dahan, at 30/06/2010 12:03  

  • hi,
    i have a question.
    how can i implement identity delegation in your scenario?
    client call a WCF service that expose an Orchestration, then in orchestration we invoke a WCF service with client identity.
    how can i extract bootstrap token from inbound message?

    By Anonymous Anonymous, at 17/11/2010 20:36  

  • As much as I wanted to experiment, not so much with delegation necessarily, but with gaining access to the claims in the token within the BizTalk solution, I haven't quite managed to get the time unfortunately.
    At the moment I don't even know if accessing the ClaimsIdentity is possible within the receive pipeline, and I certainly don't expect it to be available after that point.
    If I was to investigate that's what I'd do, because if you can get to it in the receive pipeline, presumably you can bootstrap the token from it, and keep it with the message which would be the first step, right?

    By Blogger Yossi Dahan, at 18/11/2010 10:05  

  • Thank you

    By Anonymous Anonymous, at 18/11/2010 17:28  

  • Yossi,

    I am trying to consume a CRM 2011 wcf service that is using federation and certs.

    The binding file has a binding (CustomBinding_IOrganizationService) that has an issuer that uses customBinding/STSBinding. The binding file also has the binding STSBinding. There is also a endpoint behavior, ClientCertificateBehavior that specifies the x509 thumbprint.

    in a console app, i can consume the crm 2011 service. in a biztalk project i can generate the svc artifacts and deploy the project.

    when i run the biztalk app, i get the error about tyring to initialize a channel before UI. this is how i found your blog post.

    i noticed that the issuer address and issuer metadata address was wrong so i added it to biztalk xml binding file and re-imported. error continued. so i've also added the STSBinding section to the 32-bit .net 4.0319 machine config.

    the problem still continued. so i tried to add endpointbehavior (ClientCertificateBehavior) for the x509 cert, but the port won't save. I get an error because the port still can't see system.serviceModel/bindings/customBinding/STSBinding.

    Some help would be greatly appreciated.

    By Blogger Ahmed Agbabiaka, at 20/01/2014 20:46  

Post a Comment

<< Home