Documentation

Introduction

Use this guide to enable the SecureAuth IdP Transformation Engine, which sends customized user information within SAML and WS-Federation assertions.

The Transformation Engine can modify the data within and / or the format of the Profile Properties that are mapped to directory attributes, and / or append static characters to the information. These customizations can be done as global adjustments or as a result of conditions met (if, then; when, otherwise; etc.).

Some common examples are to change the characters to all lowercase or uppercase letters (EXAMPLE; example), add a domain to the User ID (company\username; username@company.com), assert only specific characters from a property (last four digits of SSN), filter user's groups to present only those required, and provide missing information if not present in the property (if Aux ID 1 property contains "word1", then prepend Aux ID 1 with "word2").

The flexibility of this feature enables limitless, post-authentication data modification without requiring additional storage in the directory.

Prerequisites

1. Have general scripting, XSLT, and .NET knowledge

2. Create a New Realm or access an existing SAML or WS-Federation assertion realm in the SecureAuth IdP Web Admin

3. Configure the Data tab with an on-premises directory integration and the necessary directory attribute - Profile Property mapping

SecureAuth IdP Configuration Steps

 

1. In the Post Authentication section of the Post Authentication tab, select a SAML option or WS-Federation Assertion from the Authenticated User Redirect dropdown

User ID Mapping

 

2. Click Transformation Engine

Transformation Engine

 

3. Check Enable Transformation Engine

4. Add customization to the provided code, utilizing the SecureAuth IdP Profile Property values

The information saved here is not saved in the web.config file

Access the saved information (for realm duplication / movement purposes) at D:\SecureAuth\SecureAuth<realm>\PostAuthData\usersprofiledata.xslt

Click Save once the configurations have been completed and before leaving the Transformation Engine page to avoid losing changes

XSLT Attributes
 The default (out-of-the-box) code provided in the Web Admin
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/">
    <user>
      <!--xsl:if test="user/UserID='testuseridtoCheckfor'">
				<UserID>
				  BeginAppend<xsl:value-of select="user/UserID"/>@EndAppend.domain
				</UserID>
			</xsl:if-->
      <UserID>
        <xsl:value-of select="user/UserID" />
      </UserID>
      <Email1>
        <xsl:value-of select="user/Email1" />
      </Email1>
      <Email2>
        <xsl:value-of select="user/Email2" />
      </Email2>
      <Email3>
        <xsl:value-of select="user/Email3" />
      </Email3>
      <Email4>
        <xsl:value-of select="user/Email4" />
      </Email4>
      <AuxID1>
        <xsl:value-of select="user/AuxID1" />
      </AuxID1>
      <AuxID2>
        <xsl:value-of select="user/AuxID2" />
      </AuxID2>
      <AuxID3>
        <xsl:value-of select="user/AuxID3" />
      </AuxID3>
      <AuxID4>
        <xsl:value-of select="user/AuxID4" />
      </AuxID4>
      <AuxID5>
        <xsl:value-of select="user/AuxID5" />
      </AuxID5>
      <AuxID6>
        <xsl:value-of select="user/AuxID6" />
      </AuxID6>
      <AuxID7>
        <xsl:value-of select="user/AuxID7" />
      </AuxID7>
      <AuxID8>
        <xsl:value-of select="user/AuxID8" />
      </AuxID8>
      <AuxID9>
        <xsl:value-of select="user/AuxID9" />
      </AuxID9>
      <AuxID10>
        <xsl:value-of select="user/AuxID10" />
      </AuxID10>
      <FirstName>
        <xsl:value-of select="user/FirstName" />
      </FirstName>
      <LastName>
        <xsl:value-of select="user/LastName" />
      </LastName>
      <Phone1>
        <xsl:value-of select="user/Phone1" />
      </Phone1>
      <Phone2>
        <xsl:value-of select="user/Phone2" />
      </Phone2>
      <Phone3>
        <xsl:value-of select="user/Phone3" />
      </Phone3>
      <Phone4>
        <xsl:value-of select="user/Phone4" />
      </Phone4>
      <GroupList>
        <Groups>
          <xsl:for-each select="user/GroupList/Groups/Value">
            <Value>
              <xsl:value-of select="current()" />
            </Value>
          </xsl:for-each>
        </Groups>
      </GroupList>
    </user>
  </xsl:template>
</xsl:stylesheet>

XSLT and .NET Examples / Functions

Refer to the following for common use cases and formatting examples. The template includes XSLT and .NET functions to manipulate data, append static data, and enable conditional circumstances.

The fields within the XSLT are case-sensitive; be sure that when modifying the attributes, the values remain as formatted in the template

Data Manipulation

Data manipulation requires additional scripts that create rules to which the code calls. Customize the information contained in Profile Properties using .NET functions to achieve any preferred output.

Below is code with data manipulation examples, followed by explanations of what is presented.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:user="urn:my-scripts">
	<msxsl:script language="C#" implements-prefix="user">
		<msxsl:using namespace="System.Globalization"/>
		<![CDATA[
			public string LowerCase(string v)
			{
				return v.ToLower();
			}
			public string UpperCase(string v)
			{
				return v.ToUpper();
			}
			public string TitleCase(string v)
			{
				TextInfo textinfo = new CultureInfo("en-US",false).TextInfo;
				return textinfo.ToTitleCase(v);
			}
		]]>
	</msxsl:script>
	<xsl:template match="/">
		<user>
			<FirstName>
				<xsl:value-of select="user:UpperCase(user/FirstName)"/>
			</FirstName>
			<AuxID1>
				<xsl:value-of select="user:TitleCase(user/AuxID1)"/>
			</AuxID1>
			<LastName>
				<xsl:value-of select="user:LowerCase(user/LastName)"/>
			</LastName>
		</user>
	</xsl:template>
</xsl:stylesheet>
CodeFunctionExample Output
BeforeAfter

<![CDATA[
public string LowerCase(string v)
{
return v.ToLower();
}

public string UpperCase(string v)
{
return v.ToUpper();
}

public string TitleCase(string v)
{
TextInfo textinfo = new CultureInfo("en-US",false).TextInfo;
return textinfo.ToTitleCase(v);
}
]]>

Script created to manipulate the directory attribute data that is mapped to the SecureAuth IdP Profile Property, called out in code to produce preferred output

public string LowerCase(string v) – produces the Profile Property data in all lower case letters

public string UpperCase(string v) – produces the Profile Property data in all upper case letters

public string TitleCase(string v) – produces the Profile Property data with a capital letter at the beginning of each word

See Below Codes

<FirstName>
<xsl:value-of select="user:UpperCase(user/FirstName)"/>
</FirstName>

Call the UpperCase function to transform the current First Name Profile Property data to all uppercase lettersJohnJOHN

<AuxID1>
<xsl:value-of select="user:TitleCase(user/AuxID1)"/>
</AuxID1>

Call the TitleCase function to transform the current Aux ID Profile Property data to TitleCase format

 

example OF dAtaExample Of Data

<LastName>
<xsl:value-of select="user:LowerCase(user/LastName)"/>
</LastName>

Call the LowerCase function to transform the current Last Name Profile Property data to all lowercase lettersDoedoe

Static Appendage

Static appendage allows for characters to be added before or after Profile Properties for all user accounts accessing the realm.

Below is code with static appendage examples, followed by explanations of what is presented.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:template match="/">
		<user>
			<UserID>
				<xsl:value-of select="user/UserID"/>@company.com
			</UserID>
			<Phone1>
				+1 <xsl:value-of select="user/Phone1"/>
			</Phone1>
		</user>
	</xsl:template>
</xsl:stylesheet>
CodeFunctionExample Output
BeforeAfter
<UserID>
<xsl:value-of select="user/UserID"/>@company.com
</UserID>
Appends @company.com to the end of the User ID Profile Property data for every user accessing the realmjdoejdoe@company.com
<Phone1>
+1 <xsl:value-of select="user/Phone1"/>
</Phone1>
Appends +1 to the beginning of the Phone 1 Profile Property data for every user accessing the realm555-555-5555+1 555-555-5555

Conditional Circumstances

Conditional circumstances code enables SecureAuth IdP to alter the data being sent if the conditions outlined are met. Utilize "if, then", "choose", "when, otherwise", and other statements to create various outputs.

Below is code with conditional circumstances examples, followed by explanations of what is presented.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:user="urn:my-scripts">
<msxsl:script language="C#" implements-prefix="user">
<msxsl:using namespace="System.Globalization"/>
	<![CDATA[
	public string UpperCase(string v)
	{
		return v.ToUpper();
	}
	]]>
</msxsl:script>
<xsl:template match="/">
	<user>
		<xsl:if test="user/AuxID10='finance'">
			<AuxID10>
				accounting
			</AuxID10>
		</xsl:if>
		<GroupList>
			<Groups>
				<xsl:for-each select="user/GroupList/Groups/Value">
					<xsl:choose>
						<xsl:when test="current()='Domain Admins'">
							<Value>
								<xsl:value-of select="user:UpperCase(current())"/>
							</Value>
						</xsl:when>
						<xsl:otherwise>
							<Value>
								<xsl:value-of select="current()"/>
							</Value>    
						</xsl:otherwise>
					</xsl:choose> 
				</xsl:for-each>
			</Groups>
			<FullGroups>
				<xsl:for-each select="user/GroupList/FullGroups/Value">
					<Value>
						<xsl:value-of select="current()"/>
					</Value> 
				</xsl:for-each>
			</FullGroups>
		</GroupList>
	</user>
</xsl:template>
</xsl:stylesheet> 
CodeFunctionExample Output
BeforeAfter

<xsl:if test="user/AuxID10='finance'">
<AuxID10>
accounting
</AuxID10>
</xsl:if> 

If the Aux ID 10 Profile Property data equals finance, then change to accountingfinanceaccounting
<Groups>
<xsl:for-each select="user/GroupList/Groups/Value">
<xsl:choose>
<xsl:when test="current()='Domain Admins'">
<Value>
<xsl:value-of select="user:UpperCase(current())"/>
</Value>
</xsl:when>
<xsl:otherwise>
<Value>
<xsl:value-of select="current()"/>
</Value>    
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</Groups>
When the current "Value" (Group Name) is Domain Admins, change the format of the name to all uppercase (calling the UpperCase function – see the Data Manipulation section for more information); otherwise, leave the "Value" as currently formatted

Domain Admins; users01

DOMAIN ADMINS; users01

Additional Code (Not Conditional)FunctionOutput
<FullGroups>
<xsl:for-each select="user/GroupList/FullGroups/Value">
<Value>
<xsl:value-of select="current()"/>
</Value>
</xsl:for-each>
</FullGroups>
Send the group's Distinguished NameCN=Domain Admins,DC=company,DC=local
 Example of full code
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:user="urn:my-scripts">
<msxsl:script language="C#" implements-prefix="user">
<msxsl:using namespace="System.Globalization"/>
	<![CDATA[
		public string LowerCase(string v)
		{
			return v.ToLower();
		}
		public string UpperCase(string v)
		{
			return v.ToUpper();
		}
		public string TitleCase(string v)
		{
			TextInfo textinfo = new CultureInfo("en-US",false).TextInfo;
			return textinfo.ToTitleCase(v);
		}
	]]>
</msxsl:script>
	<xsl:template match="/">
		<user>
			<UserID>
				<xsl:value-of select="user/UserID"/>@company.com
			</UserID>
			<Email1>
				<xsl:value-of select="user/Email1" />
			</Email1>
			<Email2>
				<xsl:value-of select="user/Email2" />
			</Email2>
			<Email3>
				<xsl:value-of select="user/Email3" />
			</Email3>
			<Email4>
				<xsl:value-of select="user/Email4" />
			</Email4>
			<AuxID1>
				<xsl:value-of select="user:TitleCase(user/AuxID1)"/>
			</AuxID1>
			<AuxID2>
				<xsl:value-of select="user/AuxID2" />
			</AuxID2>
			<AuxID3>
				<xsl:value-of select="user/AuxID3" />
			</AuxID3>
			<AuxID4>
				<xsl:value-of select="user/AuxID4" />
			</AuxID4>
			<AuxID5>
				<xsl:value-of select="user/AuxID5" />
			</AuxID5>
			<AuxID6>
				<xsl:value-of select="user/AuxID6" />
			</AuxID6>
			<AuxID7>
				<xsl:value-of select="user/AuxID7" />
			</AuxID7>
			<AuxID8>
				<xsl:value-of select="user/AuxID8" />
			</AuxID8>
			<AuxID9>
				<xsl:value-of select="user/AuxID9" />
			</AuxID9>
			<xsl:if test="user/AuxID10='finance'">
				<AuxID10>
					accounting
				</AuxID10>
			</xsl:if>
			<FirstName>
				<xsl:value-of select="user:UpperCase(user/FirstName)"/>
			</FirstName>
			<LastName>
				<xsl:value-of select="user:LowerCase(user/LastName)"/>
			</LastName>
			<Phone1>
			+1<xsl:value-of select="user/Phone1"/>
			</Phone1>
			<Phone2>
				<xsl:value-of select="user/Phone2" />
			</Phone2>
			<Phone3>
				<xsl:value-of select="user/Phone3" />
			</Phone3>
			<Phone4>
				<xsl:value-of select="user/Phone4" />
			</Phone4>
			<GroupList>
				<Groups>
					<xsl:for-each select="user/GroupList/Groups/Value">
						<xsl:choose>
							<xsl:when test="current()='Domain Admins'">
								<Value>
									<xsl:value-of select="user:UpperCase(current())"/>
								</Value>
							</xsl:when>
							<xsl:otherwise>
								<Value>
									<xsl:value-of select="current()"/>
								</Value>    
							</xsl:otherwise>
						</xsl:choose> 
					</xsl:for-each>
				</Groups>
				<FullGroups>
					<xsl:for-each select="user/GroupList/FullGroups/Value">
						<Value>
							<xsl:value-of select="current()"/>
						</Value> 
					</xsl:for-each>
				</FullGroups>
			</GroupList>
		</user>
	</xsl:template>
</xsl:stylesheet>
  • No labels