UAG custom Form Login

Single Sign On is one of the most useful features UAG offers, and Form Login is a very unique and clever mechanism. For many applications, this SSO is simple and automatic, but FormLogin can be a little more challenging. This guide will discuss configuring custom FormLogin.

How it works

First, lets understand how UAG SSO works. UAG has three ways to do SSO:

1. 401 authentication
2. Form Login
3. AD FS

When UAG posts a request to a backend server on behalf of a user, the request is posted anonymously. Depending on the way the backend server is configured, it might respond with a 401 status message, or with a login form. If it’s a 401, UAG will repeat the request, this time with credentials, and with any luck, that will be the end of it, and the backend server would reply with the content requested (this could get a bit more complicated with regards to the authentication method, but that’s another topic).

If the server presents a form, then it’s up to UAG to handle it, and for that, UAG has an XML configuration file that contains details about various forms used by various applications. For example, UAG comes built-in with a definition for SharePoint, Citrix and a few others. As I will detail below, you can also create custom configurations for your own applications.

To be clear – as far as UAG is concerned, any page coming from a back end server MAY be a form, so UAG inspects every page to see if it matches it’s form definitions. The form definition includes the following parameters, which will be used to identify a form that is to be handled, and how to handle it:

1. The application TYPE
2. The URL
3. The Form Name
4. The name of the form fields that are to be filled (usually Username and Password input fields, but could be others as well)

If you need to create your own definitions for your own applications, you will need to create a custom XML file with the appropriate syntax. Below is the syntax, and you will need to collect the information above from your application, and update the text below with the appropriate information.

<WHLFILTFORMLOGIN ver="1.0"> <APPLICATION> <APPLICATION_TYPE>HelpDeskApp</APPLICATION_TYPE> <USAGE description="form_login"> <PRIMARY_HOST_URL> /helpdesk/login\.aspx</PRIMARY_HOST_URL> <SCRIPT_NAME source="data_definition">FormLoginSubmitStandard</SCRIPT_NAME> <USER_AGENT> <AGENT_TYPE search="group">all_supported</AGENT_TYPE> <POLICY>multiplatform</POLICY> <SCRIPT_NAME source="data_definition">FormLoginHandler</SCRIPT_NAME> </USER_AGENT> <LOGIN_FORM> <NAME>Login</NAME> <METHOD>POST</METHOD> <CONTROL handling="dummy_value"> <TYPE>USER_NAME</TYPE> <NAME>helpdeskusername</NAME> <DEF_VALUE>usr</DEF_VALUE> </CONTROL> <CONTROL handling="dummy_value"> <TYPE>PASSWORD</TYPE> <NAME>helpdeskpassword</NAME> <DEF_VALUE>whlpass</DEF_VALUE> </CONTROL> </LOGIN_FORM> </USAGE> </APPLICATION> </WHLFILTFORMLOGIN>

If you’re copying the above into your own server, keep an eye on the formatting so that you don’t miss any of the opening and closing tags, and that there are no extra spaces inside configuration elements.

As you can see above, the Primary Host URL is built using RegEx. This can be a timesaver, but can also be confusing for beginners. If not sure, simply put in the exact URL the application sends, starting from the root. Keep in mind that the combination of the URL and application type is what allows UAG to know a particular page IS the form it needs to handle, so make sure you get those right.

Assuming UAG correctly identifies the page, it will attempt to find the form, based on the form name you specified, and the form name specified in the HTML, and insert VALUE tags into the form INPUT tags. In the above sample, I specified the form name as “Login”, which would match a form such as this:

<form name=login method=post target=/login.aspx>

If the form was found, UAG will attempt to locate input fields matching the names you defined (helpdeskusername and helpdeskpassword in the example above), and if it finds them, it will inject a value item with special dummy values into them. The dummy values are not the real username and password, for security purposes. Once the form is submitted, UAG will replace the dummy values with the real values en-route. You can define additional values other than the username and password. For example, some apps require the domain value as well, and in that case, you would have something like this:

<CONTROL handling="dummy_value">     <TYPE>DOMAIN</TYPE>     <NAME>domain</NAME>     <DEF_VALUE>sitedomain</DEF_VALUE> </CONTROL>

This would fit in before or after the other input definitions that are bound in <control></control> above.

As I said above, UAG does come with a built-in set of definitions, so if you need to add yours, you’ll need to use UAG’s CustomUpdate framework. For this, you’ll need to create a new text file with the proper XML syntax following my examples above, and save the file as:

C:\Program Files\Microsoft Forefront Unified Access Gateway\von\Conf\WizardDefaults\FormLogin\CustomUpdate\FormLogin.xml

Then, when you activate the configuration, it will tell UAG to store the custom file and use the instructions in it to supplement the built-in definitions. This means that you’re not supposed to COPY the content of the default file…just create your own and UAG will process both the default one and your custom one. Also, if the definitions in the default file aren’t suitable, you can copy one or more of the definition sets into the custom file, and modify them, and they will override the default ones. This is useful for Citrix, where by default, the Domain field is not filled, but you might want to have it taken care of.

When FormLogin takes place, if UAG has identifies a specific page as a form, it will inject special JavaScripts into the page. These two scripts are the core engine that makes the form submit automatically (with the values that UAG injects into it). Normally, you would have nothing to do with these scripts, but identifying them is a good troubleshooting step. If you have configured a custom FormLogin, but it doesn’t seem to work, view the SOURCE of the form, and inspect it for these scripts. If they are NOT there, that means UAG hasn’t matched the application type and/or the URL properly, and doesn’t think this is a form.

Script 1:

function FormLoginSubmit() { formsCol = document.forms; if (formsCol.length == 1) { document.forms[0].submit(); } else { alert("more than one form"); } return false; }

Script 2: 

<SCRIPT language="JavaScript"> var gSafeOnload = new Array(); function FormLoginOnload() { for (var i=0; i < gSafeOnload.length; i ++) { gSafeOnload[i](); }// for i }// FormLoginOnload if (window.onload) { gSafeOnload[0] = window.onload; gSafeOnload[gSafeOnload.length] = FormLoginSubmit; window.onload = FormLoginOnload; } else { window.onload = FormLoginSubmit; } // if window.onload </SCRIPT>

Advanced form submission

The scripts I referenced above are generic, and designed to perform a simple submit for a simple form. The 1st script is designed to enumerate all forms on the page, and launch the “submit” button of the 1st one, or issue an error message if it found more than one form. The 2nd script uses the “window.onload” JavaScript method to run the other script as soon as the page is loaded in the browser.

Occasionally, these scripts will not perform their duties correctly. One such situation is where there are more forms on the page. Another could be if the form is designed in a way that’s different than usual (for example, it has no Submit form element). In such cases, you would need to create your own script.

The submit scripts are written in JavaScript, which is not an easy language. It’s beyond the scope of this blog to offer actual scripts, and I will discuss only how to have UAG use your script instead of the default ones.

Usually, if there’s a problem with the default scripts, it would be with the submit script (script 1 above), and rarely with the 2nd. If you do have a problem where the form gets filled but does not submit, start by inspecting the form and understanding how it might disrupt the script. If the page has other scripts that use the windows.onload method or the body onload HTML element, you might need to look at the 2nd script as well.

To use your own script or scripts, you will need to create them in a JS file (or files), and place them on the UAG server. Then, you’ll need to adjust your custom FormLogin.XML to use that script or scripts instead of the default ones. Here’s how:

1. Write your script or scripts

2. Save the script with a name of your choice, though avoid using UAG’s script names, or scripts that are used by your applications. This is important, because the browser loads all these scripts and if they conflict, it might try to run the wrong one. Script names you should avoid are:

createvirtdir.js
XCompress.js
Autosubmit.js
accesssrc.js
escapeplus.js
filelist.js
mtmcode.js
tablesort.js
ViewRightFrame.js
Install.js
Params.js
SSLVPNPage.js
SSLWrapperSessionRef.js
CacheClean.js
capsLock.js
detection.js
JSAnalyze.js
loginTimeout.js
logoff.js
PDA_logoff.js
PostValidate.js
rds.js
rdsbase.js
sslvpnJavaClient.js
timeout.js
whlowa2007.js
whlowa2010.js
whlsp14.js
whlsp2007.js
flogon.js
Toolbar.js
calendar2.js
chartControl.js
checkBoxGrouping.js
dates.js
dynamicCombo.js
expandCollapse.js
graphData.js
loadHandler.js
MonitorDataControl.js
MonitorLineControl.js
MonitorPageControl.js
sessionListsShared.js
SitesData.js
tableStringManipulation.js
threshold.js
UsersData.js
WindowsManager.js
LimitedPortal.js
ToolBarScript.js
TSG.js
WinCE_ToolBarScript.js
RSASoftToken.js

You should also avoid common scripts used by popular apps. For example, the following are used by SharePoint and Exchange OWA:

flogon.js
uglobal.js
startpage.js
uview.js
vlv.js
freadmsg.js
blank.js
init.js
msstring.js
ie55up.js
sp.core.js
sp.ui.dialog.js
core.js
sp.runtime.js
cui.js
sp.js
mediaplayer.js
search.js
inplview.js
sp.ribbon.js
SP.UI.MyLinksRibbon.js
Ratings.js

3. Save the file in the folder <UAG Path>\von\Conf\WebSites\<Your Trunk>\conf

4. Edit your custom FormLogin.XML, and change the reference for the script you’re using. If you’re replacing the Submit script, change the reference from:

<SCRIPT_NAME source="data_definition">FormLoginSubmitStandard</SCRIPT_NAME>

to:

<SCRIPT_NAME source=”file”><Your script name></SCRIPT_NAME>

For example:

<SCRIPT_NAME source=”file”>MyCustomSubmitScript.js</SCRIPT_NAME>

As you can see from the example, there’s no need to specify a path. If you’re changing the onload script, change the other reference (FormLoginHandler) using the same formatting. As usual, remember to perform an activation for things to take effect.

Props to my buddy Warren for his help with this article, and for his own terrific piece on this