In AD FS 1.x, there is no built-in, easy method to send many security group names as claims to Resource Partners or applications. For example, using the built-in functionality, an administrator could create a Organization Claim of type Group with a value of Domain Admins by using the standard Organization Claim with a Group Claim Extraction from an Account Store and a Outgoing Group Claim Mapping to Resource Partners. The flow looks like this:

Organization Claim (Group) -> Group Claim Extraction from Account Store -> Appliation filter/Outgoing Group Claim Mapping to Resource Partner

While this works great for a few security groups, it does not scale well in scenarios where we need to utilize many security group names at the Resource Partner or in the application because we would need to create a mapping for each security group.


Sample solution

This sample solution includes a code sample that must be compiled, and this sample is being provided AS-IS with no warranties and confers no rights. For more information please visit http://www.microsoft.com/info/cpyright.mspx to find terms of use.


Overview

We will be utilizing a Organization Claim of type Custom, a Custom Claim Extraction from an Account Store, a Outgoing Custom Claim Mapping for a Resource Partner, and a custom claims Transform Module (the Transform Module is the code sample that must be compiled as a Class Library. The LDAP attribute we are extracting from is memberOf. The group names are returned from the LDAP query as distinguishedName (DN) like this:

CN=myGroup,CN=Users,DC=contoso,DC=com


Our custom Transform Module performs string manipulation on the DN value and will return only the short name of the security group like this:

myGroup

The returned value from the Transform Module will be sent to the Resource Partner as the custom claim type.


Steps

Organization Claim (Custom)

1.Launch the AD FS MMC console (ADFS.MSC)
2. Expand Federation Service > Trust Policy > My Organization
3. Right-click Organization Claims and select New > Organization Claim
4. Claim name: adfs1/Role
5. Please specify the claim type: Custom claim
6. Click OK






Custom Claim Extraction

1. Expand Account Stores
2. Right-click your account store (I am using Active Directory) and select New > Custom Claim Extraction
3. Attribute: memberOf
4. Map to this Organization Claim: adfs1/Role
5. Click OK





Outgoing Custom Claim Mapping

1. Expand Partner Organizations and Resource Partners
2. Right-click the the appropriate resource partner and select  New > Outgoing Custom Claim Mapping
3. Organization custom claims: adfs1/Role
4. Outgoing custom claim name: adfs1/Role
5. Click OK





Compile the sample code

1. Launch Visual Studio
2. Create a new Project as follows:
    a. Visual C# > Windows > Class Library
    b. Name: TestADFS1Module 
3. Copy the System.Web.Security.SingleSignOn.ClaimTransforms.dll file from the AD FS 1.x server to your Visual Studio machine
4. Add System.Web.Security.SingleSignOn.ClaimTransforms.dll as a reference to your project
5. Paste the sample code and make any modifications to the code you need:
using System;
using System.Collections.Generic;
using System.Text;
using System.Web.Security.SingleSignOn;
using System.Web.Security.SingleSignOn.Authorization;
 
namespace TestADFS1Module
{
    public class ClaimTransform : System.Web.Security.SingleSignOn.IClaimTransform
    {
        public void TransformClaims(ref SecurityPropertyCollection incomingClaims,
            ref SecurityPropertyCollection corporateClaims,
            ref SecurityPropertyCollection outgoingClaims,
            ClaimTransformStage transformStage,
            string issuer,
            string target)
        {
            switch (transformStage)
            {
                case ClaimTransformStage.PreProcessing:
                    {
                        foreach (SecurityProperty securityProperty in corporateClaims)
                        {
                            if ((securityProperty.ClaimType.Equals(WebSsoClaimType.Custom)) && (securityProperty.Name.Equals("adfs1/Role")))
                            {
                                string startString = securityProperty.Value;
                                char[] separators1 = { '=' };
                                string[] sep1String = startString.Split(separators1);
                                string midString = sep1String[1];
                                char[] separators2 = { ',' };
                                string[] sep2String = midString.Split(separators2);
                                string finalString = sep2String[0];
 
                                outgoingClaims.Add(SecurityProperty.CreateCustomClaimProperty(securityProperty.Name, finalString));
                            }
 
                        }
                        break;
                    }
                case ClaimTransformStage.PostProcessing:
                    {
                        foreach (SecurityProperty securityProperty in corporateClaims)
                        {
                            if ((securityProperty.ClaimType.Equals(WebSsoClaimType.Custom)) && (securityProperty.Name.Equals("adfs1/Role")))
                            {
                                string startString = securityProperty.Value;
                                char[] separators1 = { '=' };
                                string[] sep1String = startString.Split(separators1);
                                string midString = sep1String[1];
                                char[] separators2 = { ',' };
                                string[] sep2String = midString.Split(separators2);
                                string finalString = sep2String[0];
 
                                outgoingClaims.Add(SecurityProperty.CreateCustomClaimProperty(securityProperty.Name, finalString));
                            }
 
                        }
                        break;
                    }
 
            }
        }
    }
 
}

6. Build the solution and copy TestADFS1Module.dll to the AD FS 1.x server



Import and configure the module

1. Create a bin directory in the sts directory
    a. Windows Server 2008 and Windows Server 2008 R2 location: C:\Windows\SystemData\ADFS\
    b. Windows Server 2003 R2 location: C:\ADFS\
2. Copy TestADFS1Module.dll to the new bin directory
3. Copy the web.config file from the sts directory and paste it into the bin directory
4. Edit the web.config file in the bin directory, and add the following, bolded line:
    <assemblies>
        <add assembly="System.Web.Security.SingleSignOn, Version=1.0.0.0,.......(rest of line removed for brevity)
        <add assembly="System.Web.Security.SingleSignOn.ClaimTransforms, Version=1.0.0.0,.......(rest of line removed for brevity)
        <add assembly="TestADFS1Module, Version=1.0.0.0, Culture=neutral" />
    <assemblies>
5. In the AD FS MMC console, right-click Trust Policy and select Properties
6. Use the tab navigation arrows at the top right to move to the right
7. Select the Transform Module tab
8. Under DLL file, click Browse
9. Navigate to the bin directory and select TestADFS1Module.dll
10. Class name: TestADFS1Module.ClaimTransform
11. Click OK





Test
1. Sign in to AD FS as a user who is a member of some test groups
2. Use the AD FS debug logging or a HTTP capture tool to see the SAML assertion
    a. AD FS 2.0: How to use Fiddler Web Debugger to analyze a WS-Federation passive sign-in


More Information

For all of your AD FS 2.0 needs: AD FS 2.0 Content Map