Introduction

Storing passwords or other credentials hard-coded in mappings, registry or external files is unsafe, and cumbersome at best. The Enterprise SSO is the best place for credentials to be stored safely, and this article will show you how.This article shows a simple wrapper and examples of how it can be used in an orchestration with least privileges, and corresponding SSO application and mapping files.

Problem

Your outgoing business message needs credentials in a message body, not in the port authentication properties.

For example, a third-party has a web service where you identify yourself with a username and a password in a separate Authenticate method. The Authenticate method does not use Basic Http Authentication; instead, you have to send the username and password in plain text in the request to the Authentication method. You don’t want to store the password somewhere in plain text.

Solution

The BizTalk standard solution is to store passwords in the Enterprise Single Sign-On, and this article describes how to use it from an orchestration.

This article first describes the SSO and the wrapper code, and then shows an example of how it can be used.

The source code for this article can be downloaded from Code Gallery: BizTalk 2010: Call SSO from Orchestration

SSOLookup Wrapper

This is really the heart of this article. There are three interfaces to the SSO:

Of these three, only the ISSOLookup1 interface requires that the account running the orchestration host instance is a member of the groups listed in the SSO affiliate application’s Application Users box. The two latter ones (ISSOAdmin and ISSOConfigStore) requires administration privileges, i.e. the account running the orchestration host instance must be a member of a group listed in the SSO affiliate application’s Administrators box.

Serving as a good example, the built-in FTP adapter uses the ISSOLookup1 interface.

SSO Lookup Wrapper Code

The ISSOLookup1 interface isn’t complicated, but it returns an array, so in order to use it in an orchestration or in a custom mapping functoid, a wrapper helps writing clear code.

This article will not go into details on how to create new projects in solutions etc. The reader is assumed to have basic knowledge on Visual Studio, BizTalk, and C#. If you already have a C# library in your BizTalk repertoire, just add this class to that library.

Start by adding a reference to the BizTalk SSO Client Interop library (C:\Program Files\Common Files\Enterprise Single Sign-On\Microsoft.BizTalk.Interop.SSOClient.dll – this path is the same regardless whether you are using a 32- or 64-bit operating system), and if you prefer, add a using line:

using Microsoft.BizTalk.SSOClient.Interop;

Use a namespace of your choice. Since this is a wrapper intended for use in orchestrations and custom mapper functoids, the class and its methods are static.

namespace SSOPasswordSample.SSOLookupSample
{
    public static class SSOLookup
    {

Declare a struct (or make it a class if you prefer) for the returned credentials:

        /// <summary>
        /// Struct to hold username+password credentials.
        /// </summary>
        [Serializable]
        public struct Credentials
        {
            public string Username;
            public string Password;
        }

Don’t forget to decorate the struct as [Serializable], otherwise the orchestration cannot be dehydrated (serialized to the database) and you will be forced to use the wrapper in an atomic scope.

The core GetCredentials() method, which takes an SSO affiliate application name as parameter and returns the struct with credentials filled in:

        /// <summary>
        /// Retrieves the credentials to use.
        /// </summary>
        /// <param name="appName">The name of the affiliate application.</param>
        /// <returns>Credentials to use.</returns>
        public static Credentials GetCredentials(string appName)
        {
            Credentials credentials;
            try
            {
                Microsoft.BizTalk.SSOClient.Interop.ISSOLookup1 ssoLookup = (Microsoft.BizTalk.SSOClient.Interop.ISSOLookup1)new Microsoft.BizTalk.SSOClient.Interop.SSOLookup();
                string[] passwords;
                passwords = ssoLookup.GetCredentials(appName, 0, out credentials.Username);
                credentials.Password = passwords[0];
            }
            catch (Exception e)
            {
                System.Diagnostics.Trace.WriteLine(e.Message);
                throw;
            }
            return credentials;
        }

The wrapper’s GetCredentials() method first instantiates an ISSOLookup1 typed instance of BizTalk’s SSOClient.Interop.SSOLookup object. Then, it calls the SSOLookup1.GetCredentials() to retrieve the credentials from SSO. Note that ISSOLookup1.GetCredentials() both has an out parameter and returns a value; the out parameter returns the username, and the return value is an array of strings. The wrapper code simply takes the first element in the array as the password.

SSO Affiliate Application Name

In the example below, the SSO affiliate application name is hard-coded in the orchestration code. In a production environment this might not suffice, a more dynamic or generic solution is needed.

One possibility is to use the receive location or receive port name as SSO affiliate application name, and read that message context value in the orchestration. Another possibility is to create a custom receive pipeline component that takes an SSO affiliate application name as parameter and promotes its value into the message context (according to a custom property schema), which the orchestration then reads from the context. A third possibility is, if you have control over the received message schemas, to retrieve the SSO affiliate application name from the message itself, pushing the configuration out from BizTalk into the sender’s system. There are other possibilities too numerous to list here; choose what’s appropriate for your production environment and your maintenance requirements.

This article will not go into depths on how to create, configure and manage an SSO affiliate application. Sample XML files is provided in the Sample part of this article.

Sample BizTalk Orchestration

The sample used in this article assumes that an ERP system wants to send a business message to the external third-party system. The third-party system requires a separate Authenticate call that returns a ticket for subsequent calls, if the authentication succeeds.

The orchestration picks up a business message sent from the ERP system. It then starts the processing by authenticating with the third-party, and if authentication succeeds, it proceeds with the business processing.  If authentication fails, error handling must be applied, but that’s out of scope for this article.

Authentication

The first, and for this article, most important step is the GetCredentials shape. It calls the wrapper which returns credentials for the given SSO Affiliate Application name:

varCredentials = SSOPasswordSample.SSOLookupSample.SSOLookup.GetCredentials("SSOPasswordSample");

The rest is pretty much regular code.

In the Authentication construct message shape, create the Authenticate message:
Instantiate : Instantiate an Authenticate message from a template using a temporary XMLDocument instance:

vartmpAuthenticate = new System.Xml.XmlDocument();
vartmpAuthenticate.LoadXml("<ns0:Credentials xmlns:ns0='http://ssopasswordsample.ssopasswordretrievalsample.authenticate/'><Username /><Password /></ns0:Credentials>");
msgAuthenticate = vartmpAuthenticate;

SetCredentials: On the Authenticate message, assign the Username and Password elements from the retrieved credentials:

msgAuthenticate.Username = varCredentials.Username;
msgAuthenticate.Password = varCredentials.Password;

Finally, send the Authenticate message and receive the response.

Business processing

The business processing in this example is only a placeholder for your actual processing; it solely creates a business message by copying the input message, and sets the business message’s Ticket value using the value from the authentication response:

msgBusinessOut = msgBusinessIn;
msgBusinessOut.Authentication.Ticket = msgAuthenticateResponse.Ticket;

Then, send the outbound business message and receive the response.

To keep the sample easy to follow, relevant message elements have been set as distinguished fields and messages are not made multi-part.

Sample Files

Source Code

All of this sample can be found and downloaded in Microsoft Code Gallery:

SSO Files

The SSO files are included in the source code link above, but are displayed here for completeness:

SSO Application definition file

<?xml version="1.0" ?>
<SSO>
  <application name="SSOPasswordSample">
    <description />
    <contact />
    <appUserAccount>DOMAIN\BizTalk Application Users; DOMAIN\BizTalkHostUser</appUserAccount>
    <appAdminAccount>DOMAIN\SSO Affiliate Administrators; DOMAIN\BizTalk Application Users; DOMAIN\BizTalkHostUser</appAdminAccount>
    <field ordinal="0" label="User ID" masked="no" />
    <field ordinal="1" label="Password" masked="yes" />
    <flags groupApp="yes" configStoreApp="no" allowTickets="yes" validateTickets="yes" allowLocalAccounts="no" timeoutTickets="yes" adminAccountSame="no" enableApp="yes" />
  </application>
</SSO>

SSO Mappings file

<?xml version="1.0" ?>
<SSO>
  <mapping>
    <windowsDomain>DOMAIN</windowsDomain>
    <windowsUserId>BizTalkHostUser</windowsUserId>
    <externalApplication>SSOPasswordSample</externalApplication>
    <externalUserId>UserID-at-thirdparty</externalUserId>
  </mapping>
</SSO>

Applies to

This article applies to BizTalk Server 2004 through BizTalk Server 2013.

See also

Read suggested related topics:
Another important place to find an extensive amount of BizTalk related articles is the TechNet Wiki itself. The best entry point is BizTalk Server Resources on the TechNet Wiki.