Export (0) Print
Expand All

Advanced Server-Side Authentication for Data Connections in InfoPath 2007 Web-Based Forms

Office 2007

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

Summary: Learn about server-side authentication scenarios for cross-domain data connections in Microsoft Office InfoPath 2007 form templates deployed to InfoPath Forms Services, as part of either Microsoft Office Forms Server 2007 or Microsoft Office SharePoint Server 2007. (9 printed pages)

Nick Dallett, Microsoft Corporation

Mark Roberts, Microsoft Corporation

September 2007

Applies to:Microsoft Office InfoPath 2007, Microsoft Office Forms Server 2007, Microsoft Office SharePoint Server 2007

Contents

Real-world enterprise applications are seldom restricted to a single server. Anyone who creates a multitier application in a Windows environment must work around the limitation that Integrated Windows authentication (NTLM) tokens cannot be delegated past the second tier. The following scenario describes this limitation:

  • When you log on to your workstation, you present Windows with primary evidence of your identity in the form of a user name and a secret—usually a password, but sometimes a certificate or a biometric identifier, such as a fingerprint.

  • When you connect to a Web application in a browser, your workstation contacts the Web server and passes your NTLM authentication token to the server to inform it of your identity. The server trusts the workstation because the workstation has primary evidence of your identity, but the server itself has only second-hand evidence.

  • When the application on the Web server attempts to connect to the data server, it is prevented from passing along your authentication token because the chain of trust is too long, and the connection is refused.

You don't have to worry about these issues when you use InfoPath 2003 to design form templates that connect to external data. The InfoPath 2003 client runs on tier 1 (your workstation), and the data connection for the database, Web service, or Microsoft Office SharePoint site on a tier-2 server trusts your workstation's first-hand evidence.

With Office InfoPath 2007, you now have the option of designing and deploying a form template to a server with InfoPath Forms Services that can be opened and run in a Web browser. In this situation, you need to think about authentication scenarios for data connections to tier 3 that are initiated from the browser.

There are a number of ways of handling authentication to tier 3 and beyond for form templates deployed to InfoPath Forms Services on Microsoft Office Forms Server 2007 or Microsoft Office SharePoint Server 2007. This article briefly describes two simple techniques for non-critical applications, and then it describes how to use two technologies that are specific to Microsoft Office Forms Server 2007 and Office SharePoint Server 2007 for enterprise-quality solutions.

Before discussing tier-3 authentication strategies, this article briefly describes how Office InfoPath 2007 and InfoPath Forms Services depend on Universal Data Connection (UDC) version 2.0 files to specify server-side data connection settings. A UDC file follows the schema defined for the UDC version 2.0 file format, which is based on the version 1.0 file format used by Microsoft Office FrontPage 2003 and Microsoft Office Excel 2003. For information about the elements and attributes in a UDC v2.0 file, see Universal Data Connection v2.0 Reference and Schema.

The basic premise behind UDC files is that data connection settings can live outside the form template in one of these files, and both Office InfoPath 2007 and InfoPath Forms Services retrieve the current connection settings from this file at run time before making the connection. The UDC file itself is retrieved from a URL relative to the root of the site collection where the form was opened. This enables features such as the following:

  • Multiple forms can share the data connection settings defined in a single UDC file, and if you need to move your data source, you need to update only the settings in the UDC file.

  • You can pre-deploy test and production versions of your data connection settings to your staging and production environments so that you do not need to update the form template with new data connection settings when you go live.

By default, a server-based form template with the security level set to Domain cannot connect to a data source in another domain unless the data connection is defined by using a UDC (.udcx) file. Additionally, the UDC file must be located in either a data connection library (DCL) or in the centrally managed connection library (CMCL) on Microsoft Office Forms Server 2007 or Microsoft Office SharePoint Server 2007.

For more information about UDC files and data connection libraries, see the following articles:

You can use the following authentication techniques in InfoPath form templates for noncritical applications.

  • Anonymous Connections

    For noncritical data connections, such as looking up a list of items to populate a Drop-Down List Box control, you can simply allow anonymous users to access your data. This removes the need to authorize users, and it is no longer a problem that their identities cannot be authenticated on tier 3.

  • HTTP Basic and Digest Authentication

    With Basic authentication (or Digest authentication, which is a slightly more secure version of the same protocol), the browser prompts the user to enter a user name and password. These are then passed to the Web server in cleartext (for Basic authentication) or as an MD5 hash value (for Digest authentication). The Web server now has primary evidence of the user's identity, so that the data server can trust that evidence.

    You can set up Internet Information Services (IIS) on the server running Office SharePoint Server to use Basic or Digest authentication instead of Integrated Windows authentication. Although this is a quick way to address the tier-3 authentication problem, it presents an awkward user experience on the intranet. This method is better suited to the extranet, where being prompted for additional credentials is a more familiar experience. When you are using this method, be sure to set up the Secure Sockets Layer (SSL) on the server so that users are required to use secure connections (HTTPS), and their credentials are encrypted on the wire. Otherwise, anybody monitoring your server traffic can read the passwords as they pass by.

Security noteSecurity Note

It is common practice when creating Web applications to connect to a database by using a SQL username and password embedded in the connection string. However, because this requires putting a password in cleartext in a configuration file, it is not a secure method of authentication. By default, user form templates on the server are not allowed to use embedded SQL credentials.

For more information about the built-in security and authentication features of IIS 6.0, see Security in IIS 6.0.

For information about configuring authentication in Office SharePoint Server 2007, see Configure authentication (Office SharePoint Server).

The rest of this article describes how to use two technologies that are features of Microsoft Office SharePoint Server 2007 and Microsoft Office Forms Server 2007: the single sign-on (SSO) service and the Proxy Web service.

Office SharePoint Server 2007 provides a Single Sign-on (SSO) service, which was created to help applications that are running on the server overcome authentication delegation issues. At its heart, the SSO service is a database that stores encrypted username and password pairs. An application that is running on the server can obtain a username and password associated with a known SSO application definition and can then use those credentials to log on to Windows and make a trusted connection to a data source. A form template that is running on the server can use the SSO service to connect to external data by using a UDC v2.0 file that specifies an SSO application ID and authentication method.

For example, the following code from a UDC file shows an SSO element that specifies an application ID MyApp that uses Windows Integrated authentication (NTLM) as the authentication method.

<udc:Authentication>
   <udc:SSO AppId="MyApp" CredentialType="NTLM"></udc:SSO>
</udc:Authentication>

You can set up the account type that the server uses for authenticating an SSO application definition in one of three ways:

  • Individual (each user has an account).

  • Group (all users share the same group account).

  • Group using restricted credentials.

The application definition for an InfoPath form template that is published to the server can use the first two kinds of account types. However, to use individual credentials, the SSO database must contain a separate username and password for each user who connects to the form.

If you want to use individual credentials, but you do not want to require the administrator to enter account information for every user into the SSO database, you can create a custom ASP.NET page that checks whether connecting users have credentials in the SSO database. If users do not have credentials, the page redirects them to a credentials management page where they can enter their credentials. Although InfoPath Forms Services does not do this generically for forms that use SSO, you can implement such a solution for an individual form or a set of forms in the same way as an Office Server application by using the Pluggable SSO API. For information about how to implement such a solution, see Appendix: Creating an ASP.NET Page to Redirect Users Who Are Not in the SSO Database later in this article.

For information about how to configure Microsoft Office SharePoint Server 2007 and Microsoft Office Forms Server 2007 to use single sign-on (SSO), see Configure single sign-on (Office SharePoint Server).

InfoPath Forms Services includes the Proxy Web service, which can forward SOAP requests from a form template to a Web service to enable authorization for a data query. The Proxy Web service makes the Web service request by using the identity that is associated with the current SharePoint application. The premise is simple—the Proxy Web service runs under an account that is trusted by the external Web service. The external Web service authenticates the trusted account. The Proxy Web service also sends the identity of the calling user in the SOAP header by using a Web Services Security (WS-Security) UsernameToken. The external Web service can then use the provided identity to determine what data to return from the query.

Setting up a connection to use the Proxy Web service proxy is straightforward. First, the connection must use settings from a UDC v2.0 file on the server. The UseFormsServiceProxy attribute on the ServiceUrl element in the UDC file determines whether InfoPath and Forms Services forward the Web service request by using the proxy.

<udc:ServiceUrl UseFormsServiceProxy="true">
   http://myserver/proxydemo/service.asmx
</udc:ServiceUrl>

Everything else on this end is automatic. It is a little more interesting on the Web service end.

It is tempting to consider using the WSE 2.0 library to consume the UsernameToken from the Web service request. WSE 2.0 has methods to automatically consume WS-Security headers. However, the default behavior of WSE 2.0 is to attempt to log on by using the credentials in the UsernameToken. You can override the default behavior by specifying an alternate UsernameTokenHandler. There is a more straightforward approach.

First, declare an array of type SoapUnknownHeader at class scope in your service.

public SoapUnknownHeader[] unknownHeaders;

Then declare a SoapHeader attribute for the Web method.

[WebMethod]
[SoapHeader("unknownHeaders")]
public ExpenseInfo[] GetMyExpenses()

In your Web method, look for the Username element in the header array, which is returned as an XML Document.

if (null != unknownHeaders && unknownHeaders.Length > 0)
{
   // Look for a userNameToken and return the username if present.
   try
   {
      strUserName = unknownHeaders[0].Element.CreateNavigator().
         SelectSingleNode("//*[local-name(.)='Username']").Value;
   }
   catch (Exception ex)
   {
      throw new Exception(ex.Message)
   }
}

In the previous example, the code searches for a Username element anywhere in the headers. To be more precise, the Username element is within a UsernameToken element, which is in turn under a Security header in the WS-Security namespace. The following example shows the entire SOAP header that is sent by the proxy.

<SOAP-ENV:Header.xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis/security-secext-1.0.xsd">
      <wsse:UsernameToken>
        <wsse:Username>DOMAIN\username</wsse:Username>
      </wsse:UsernameToken>
   </wsse:Security>
</SOAP-ENV:Header>

Add the code to get the username in a custom utility function named GetUserName. The GetUserName function first looks for the UsernameToken element. If this is not present, it gets the current Windows user. In either case, the function strips off the domain portion of the identifier and returns the unadorned username.

private string GetUserName(SoapUnknownHeader[] unknownHeaders)
{
   bool fUserFound = false;
   string strUserName = string.Empty;
   if (null != unknownHeaders && unknownHeaders.Length > 0)
   {
   // Look for a UsernameToken and return the username if present.
      try
      {
         strUserName = unknownHeaders[0].Element.CreateNavigator().
            SelectSingleNode("//*[local-name(.)='Username']").Value;
      }
      catch (Exception ex)
      {
         throw new Exception(ex.Message)
      }
      if (string.Empty != strUserName)
      {
         fUserFound = true; 
      }
   }
   if (!fUserFound)
   {
      // Return the current Windows identity.
      strUserName = WindowsIdentity.GetCurrent().Name;
   }
   // Trim off the domain string if present.
   int nDomainStringIndex = strUserName.IndexOf('\\');
   if (nDomainStringIndex > 0)
   {
      strUserName = strUserName.Substring(nDomainStringIndex + 1);
   }
   return strUserName;
}

To retrieve data, use the identity as part of the query against the database. The following example shows the entire Web method. The code assumes that you have an Expense database that contains the tables Expenses and Employee. One column of the Employee table contains the Windows username of the employee who filed the expense.

[WebMethod]
[SoapHeader("unknownHeaders")]
public ExpenseInfo[] GetMyExpenses()
{
   ExpenseInfo[] oReturn = null;
   DataSet oDS = new DataSet();
   string strQuery = string.Format("SELECT ExpenseID, Description, Date, Amount FROM Expenses WHERE Employee = '{0}'", GetUserName(unknownHeaders));
   try
   {
      m_Connection.Open();
      m_Adapter = new SqlDataAdapter(strQuery, m_Connection);
      m_Adapter.Fill(oDS, "Expenses");
      int cRows = oDS.Tables["Expenses"].Rows.Count;
      oReturn = new ExpenseInfo[cRows];
      for (int nRowIterator = 0; nRowIterator < cRows; nRowIterator++)
      {
         oRow = oDS.Tables["Expenses"].Rows[nRowIterator];
         oReturn[nRowIterator] = new ExpenseInfo();
         oReturn[nRowIterator].Amount = oRow["Amount"].ToString();
         oReturn[nRowIterator].ExpenseID = 
            oRow["ExpenseID"].ToString();
         oReturn[nRowIterator].Date = oRow["Date"].ToString();
         oReturn[nRowIterator].Description = 
            oRow["Description"].ToString();
      }
   }
   catch (Exception ex)
   {
         throw new Exception(ex.Message)
   }
   if (m_Connection.State != ConnectionState.Closed)
   {
      m_Connection.Close();
   }
   return oReturn;
}

You can take several approaches to handle authenticating cross-domain data connections from InfoPath 2007 form templates deployed to InfoPath Forms Services. This article describes two simple approaches that require minimal back-end configuration, and also two more complex approaches that use the single sign-on (SSO) service or Proxy Web service. It also provides an appendix that describes how to create an ASP.NET application that works in conjunction with the SSO service to enable users to enter their own credentials if they are not already in the SSO database.

  • InfoPath Developer Portal

    Information about InfoPath developer resources.

  • SharePoint Server Developer Center

    Information about SharePoint Server developer resources.

  • InfoPath Developer Reference for Managed Code

    Overviews, programming tasks, and class library reference information to help you build Office InfoPath 2007 form templates that contain business logic written in Microsoft Visual Basic or Microsoft Visual C#.

  • Microsoft Office InfoPath Home Page

    Microsoft Office Online site that provides information about InfoPath form design, declarative logic, and other features that are available through the InfoPath user interface.

  • InfoPath Team Blog

    Tips and tricks, best practices, and other information about getting the most out of InfoPath 2003 and InfoPath 2007 from members of the InfoPath product team.

To use individual credentials from SSO, InfoPath Forms Services requires that credentials for all users already exist in the SSO database. The simplest way to ensure that users succeed is to build functionality into your application that enables them to enter their credentials into the SSO database if the credentials do not already exist.

In this scenario, users link to an ASP.NET page rather than directly to the form template. The ASP.NET page tries to get the user's credentials from the SSO database. Based on the result, the page either redirects to the form or to a credentials management page where users can enter their credentials.

The following code examples assume that you have done the following:

  • Defined an SSO application definition named MyApp, and ensured that the application is configured to use individual credentials for authentication.

  • Deployed an administrator-approved form template named myform.xsn that is activated on the site collection.

  • Designed the form template to use one or more data connections that reference the MyApp application ID.

To use SSO to make the data connection, you must use data connection settings in a UDC file on the server. To add the reference to the MyApp application definition, you add an NTLM Authentication element to the UDC file. The Authentication element must be the last subelement of the ConnectionInfo element, as shown in this example.

<udc:Authentication>
   <udc:SSO AppId="MyApp" CredentialType="NTLM"></udc:SSO>
</udc:Authentication>

To create the redirector page, you must first add a new ASP.NET page to the root site of the server that is running Office SharePoint Server. To find the home directory of your root site, open Internet Services Manager and check the Home Directory page of the properties page for the Web application. Open this Web application in Microsoft Visual Studio and add a new ASP.NET page. In the properties for the page, enable session state. Finally, add a reference to the Microsoft.SharePoint.Portal.SingleSignon namespace.

The new page should look like this.

<%@ Page Language="C#"
   AutoEventWireup="true"
   CodeFile="SingleSignonRedirector.aspx.cs"
   Inherits="SingleSignonRedirector" EnableSessionState="True" %>
<%@ Import Namespace="Microsoft.SharePoint.Portal.SingleSignon" %>

Open the code file for the page, and add a using statement for the Microsoft.SharePoint.Portal.SingleSignon namespace.

using Microsoft.SharePoint.Portal.SingleSignon;

The code itself is relatively straightforward. Use the GetSsoProvider method of the SsoProviderFactory class to get a reference to the installed SSO provider.

ISsoProvider provider = SsoProviderFactory.GetSsoProvider();
Important noteImportant

This call fails if no provider is installed, or if the SSO service is not running.

Your page runs under the credentials of the user who is trying to access the form, so when you call the GetCredentials method, SSO returns credentials for that user, or throws SingleSignonCredsNotFoundException if the credentials do not exist.

try
{
   SsoCredentials credentials = provider.GetCredentials("MyApp");
}
catch (SingleSignonCredsNotFoundException)

If the credentials are not found, you can use the GetCredentialManagementURL method to get the URL of the credentials management page for the installed provider.

Uri CredentialsManagementUrl = 
   provider.GetCredentialManagementURL("MyApp");

At this point, you could simply redirect to the credentials management URL. However, you would miss part of the magic of the credentials management page. The credentials management page that is supplied with the Office single sign-on provider redirects back to the referring page after the user has entered valid credentials. The following code handles this by presenting a link that enables the user to click through to the credentials management page.

Response.Write("<P>Before you can access this form, you must enter credentials to access backend data.</P>");
Response.Write("<P><A href=\"" + CredentialsManagementUrl.ToString() + "\">Click here to enter your credentials</A></P>");
Response.End();

Another approach might be to add the HTTP Referer header to the response before performing a redirect. Either way, after the user enters the credentials, the redirector page is called again. This time, the GetCredentials method call succeeds, and the page redirects on to the form.

The following example shows the complete code-behind for the page.

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using Microsoft.SharePoint.Portal.SingleSignon;
 
public partial class SingleSignonRedirector : System.Web.UI.Page
{
   protected void Page_Load(object sender, EventArgs e)
   {
      ISsoProvider provider = SsoProviderFactory.GetSsoProvider();
      try
      {
         SsoCredentials credentials = provider.GetCredentials("MyApp");
      }
      catch (SingleSignonCredsNotFoundException)
      {
         Uri CredentialsManagementUrl = 
            provider.GetCredentialManagementURL("MyApp");
         Response.Write("<P>Before you can access this form, you must enter credentials to access backend data.</P>");
         Response.Write("<P><A href=\"" + CredentialsManagementUrl.ToString() + "\">Click here to enter your credentials</A></P>");
         Response.End();
      }
      catch (Exception ex)
      {
         Response.Write("<P>Single Sign-on returned an error: " + ex.Message + "</P>");
         Response.End();
      }
 
   // Redirect user to the form
   Response.Redirect( "http://myserver/formservertemplates/myform.xsn?openin=browser" );

   }
}

Possible Refinements

For a real-world application, you might add a few more things to this page to round out the implementation. Depending on the needs of the specific application, one or more of the following might apply:

  • Loop through multiple Application IDs to allow the user to enter credentials for each.

  • Attempt to log the user on by using the SSO credentials to verify that the credentials are valid and have not expired.

  • Use this code in a page that hosts the form template by using the XmlFormView control.

  • Create a generic page that takes the URL to the form and the Application ID as query parameters.

With a little bit of ingenuity, you can use this approach to create a seamless end-to-end experience to satisfy almost any scenario.

Show:
© 2014 Microsoft