Tuesday, March 20, 2012

InfoPath 2010 - Using the User Profile Service with Claims Based Authentication


Introduction

One usage for the User Profile Service in SharePoint is to inform InfoPath, it allows you to pass the current users identity and retrieve profile information, such as manager, department, and position.  If you use Classic Mode Authentication (as opposed to Claims Based Authentication), then following the process outlined here:

http://claytoncobb.wordpress.com/2009/06/21/userprofileservice-extended/

will allow you to use that service to retrieve the information.

However, if you migrate the form to an environment that uses Claims Based Authentication, any attempt to use the User Profile Service on a web enabled template will result in a 5566 error message, and an error message in the SharePoint logs that indicates an unauthorized user, most likely with a user account that includes strange characters such as "i:0#.w|[domain]\[user]".

This issue does not occur if you use an InfoPath Filler based template, so if that is an option in your environment, then you have no further modifications necessary.  If however, you are in an environment where the web enabled template is required, such as environment where not all client computers will have InfoPath Form Filler 2010, then you will have to modify the way your form queries the User Profile Service to correctly pass the current users information.

This post covers those modifications as well as confirming IIS and Central Admin configuration needed to allow the service to authenticate correctly.

This post specifically covers Standard Windows Claims based authentication, and discusses working with Forms Authenticated user claims. It does not cover any other claims formats. If a different claims format returns the appropriate credentials for the user profile service, it may also be possible to use that format as well???


Check Central Admin

A quick check of the Central Administration console confirms that the process outlined in this post is the one you need.

In SharePoint Central Administration, Application Management Section, click Manage Web Applications.

Click the name of your main site web application (or the one hosting your InfoPath form that you are attempting to configure if you have more than one web application):




And select "Authentication Providers".  If you see:


Then the procedure outlined in this post applies.


Ensure IIS Authentication is Correctly Configured

Another common barrier to using the UPS in CBA is the misconfiguration of IIS authentication.  Anonymous access settings that have no effect on UPS in Classic Mode Authentication will prevent authentication in a Claims Based environment. 


Ensure that anonymous and impersonation authentication are disabled, and that only the authentication methods used on your web server for this site are those used on your site, in this case Forms and Windows Authentication:




Determine Claims Based Token Format

Before we can modify the form, we first want to find out what the format of the value returned by the username() function is in InfoPath.  Create a new blank form in InfoPath, add a single text box, and populate that textbox with the username() function.  Ensure your form is browser enabled, and publish your form to the CBA based environment.  Open the form, and see what value is in the field populated by username().  If Standard Windows Claims are used, it will look something like:

i:0#.w|[domain]\[user]

where [domain] and [user] are the current users domain and login name.

This information includes the claim information associated with that user account, the format adheres to this standard:


(For more information on Claims Based Authentication refer to the source of this image, Wictor Wilén's blog post on this area)

What we are specifically looking for here is the number of pipe ("|") delimiters, one or two.  You will need to account for that in the upcoming expression that extracts the domain and username from the account provided by the username() function.

Although not encountered in this scenario, I have also seen blog posts where the username() function only returned the username, no domain information. In this case, the "concat" function in InfoPath is used to generate the AccountName for the user profile service, concat("[Domain]\", username()). Use the same process as outlined below, but replace the pipe delimiter handling with this handling.


Update the InfoPath Form

These steps assume the following:

1. You have an InfoPath form that uses the User Profile Service, and it works using InfoPath filler enabled templates on your Claims Based authentication site.  This ensures the User Profile Service is functioning, and that your data connections are configured correctly.
2.  You have disabled anonymous and impersonation based authentication methods in IIS.

Open your form in InfoPath Designer, and first ensure that the user profile service data connection does not query data on form open:


We are going to manually set the value used by the User Profile Service, the value passed as a query parameter in the User Profile Service data connection (for reference, no action required here):


At some point in your form rules (usually form load if the values are populated immediately), you will have a rule that queries the user profile service, and sets a series of values on your form based on the values returned. Just before that query, insert new step to set the AccountName value for the UPS.  For "Action", choose "set a fields value".  In the configuration screen that opens. field section, select the UPS connection referred to earlier, and choose the query parameter "AcccountName":


Click Ok to return to the configuration screen.  Now set the Account Name in the value section by first clicking the function (fx) button.  Choose "Insert Function".  Select the function category "text", and choose "substring-after".  For the first value, enter in the "username()" function.  If you have a single pipe delimeter (see Determine Claims Based Token Format) then, in the second value, put "|".  Click OK.  Your configuration screen should look like:




If you have the two pipe delimeter format (from forms based authentication), you will need to extract the username from after the second pipe, and then concatinate the domain to the front of the AccountName before it is passed.

Click ok to close the rule configuration box.  Your new rule should run just before the form uses the user profile service data connection to retrieve user profile values.  This way, the query parameter used by the user profile service is set to the correct user with the correct domain/account name format for the service.



Publish your form and test.