public static void Main(string[] args) { Console.WriteLine(" # start"); SecurityPropertyCollection incomingClaims = new SecurityPropertyCollection(); SecurityPropertyCollection corporateClaims = new SecurityPropertyCollection(); SecurityPropertyCollection outgoingClaims = new SecurityPropertyCollection(); ClaimTransformStage transformStage = ClaimTransformStage.PostProcessing; string strIssuer = null; string strTargetURI = null; corporateClaims.Add(SecurityProperty.CreateGroupProperty("Administrators")); ClaimTransformer o = new ClaimTransformer(); o.TransformClaims(ref incomingClaims, ref corporateClaims, ref outgoingClaims, transformStage, strIssuer, strTargetURI); o.displayClaims(outgoingClaims); Console.WriteLine(" # end"); }
public void TransformClaims( ref SecurityPropertyCollection incomingClaims, ref SecurityPropertyCollection corporateClaims, ref SecurityPropertyCollection outgoingClaims, ClaimTransformStage transformStage, string issuer, string target) { // Create the SamlBridge CTM's trace listener. TextWriterTraceListener twtlSamlBridgeCtmTraceListener = new TextWriterTraceListener(Constants.PATH_SAML_BRIDGE_CTM_TRACE_FILE); if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo) { Fujitsu.SamlBridge.Cct.Trace.WriteLine( Constants.TRCI_CLAIM_TRANSFORMATION_MODULE_ENTERED); } // We only perform any mapping action in the pre-processing stage, so return // immediately if we are not at this stage. if (transformStage != ClaimTransformStage.PreProcessing) { if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo) { Fujitsu.SamlBridge.Cct.Trace.WriteLine( Constants.TRCI_NOT_PREPROCESSING_STAGE); } return; } // If incomingClaims is null, then there is nothing to map. corporateClaims is // probably populated, in which case ADFS has previously authenticated the user and // is reusing the already-mapped SAML assertion from the user's cookie. if ((incomingClaims != null) && (incomingClaims.Count > 0)) { if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo) { Fujitsu.SamlBridge.Cct.Trace.WriteLine( Constants.TRCI_INCOMING_CLAIMS_FOUND); } // Validate that the SAML is as expected, i.e. that we have a UPN in the // incoming claims. int iUpnClaimIndex = FindClaim(incomingClaims, WebSsoClaimType.Upn); if (iUpnClaimIndex == -1) { if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceError) { Fujitsu.SamlBridge.Cct.Trace.WriteLine( Constants.TRCE_NO_INCOMING_UPN_CLAIM_FOUND); } throw new SamlBridgeCctException(Constants.EXC_NO_INCOMING_UPN_CLAIM); } SecurityProperty spUpnClaim = incomingClaims[iUpnClaimIndex]; // Read out the UID from the UPN claim string sUid = spUpnClaim.Value; if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo) { Fujitsu.SamlBridge.Cct.Trace.WriteLine( Constants.TRCI_INCOMING_UPN_CLAIM_VALUE, sUid); } // Remove the UPN claim from the collection - we will replace it with the real // UPN claim later. incomingClaims.RemoveAt(iUpnClaimIndex); #region ADFS AMPERSAND WORKAROUND // At the time of writing there appears to be a problem in ADFS whereby any // ampersand, less than, greater than, quote or apostrophe character contained // in the value of a claim in the authenticated SAML causes the ADFS Web Agent // to throw an exception. // // The following temporary workaround replaces any such characters in custom // claim values with a plain text equivalent, or, in the case of the quote and // apostrophe, nothing. for (int i = 0; i < incomingClaims.Count; i++) { SecurityProperty spThisClaim = incomingClaims[i]; string sThisClaimValue = spThisClaim.Value; if (sThisClaimValue.IndexOf("&") != -1) { if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo) { Fujitsu.SamlBridge.Cct.Trace.WriteLine( Constants.TRCI_PERFORMING_CLAIM_VALUE_SUBSTITUTION, "&", spThisClaim.Name); } sThisClaimValue = sThisClaimValue.Replace("&", "and"); } if (sThisClaimValue.IndexOf("<") != -1) { if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo) { Fujitsu.SamlBridge.Cct.Trace.WriteLine( Constants.TRCI_PERFORMING_CLAIM_VALUE_SUBSTITUTION, "<", spThisClaim.Name); } sThisClaimValue = sThisClaimValue.Replace("<", "lessthan"); } if (sThisClaimValue.IndexOf(">") != -1) { if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo) { Fujitsu.SamlBridge.Cct.Trace.WriteLine( Constants.TRCI_PERFORMING_CLAIM_VALUE_SUBSTITUTION, ">", spThisClaim.Name); } sThisClaimValue = sThisClaimValue.Replace(">", "greaterthan"); } if (sThisClaimValue.IndexOf("\"") != -1) { if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo) { Fujitsu.SamlBridge.Cct.Trace.WriteLine( Constants.TRCI_PERFORMING_CLAIM_VALUE_SUBSTITUTION, "\"", spThisClaim.Name); } sThisClaimValue = sThisClaimValue.Replace("\"", ""); } if (sThisClaimValue.IndexOf("'") != -1) { if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo) { Fujitsu.SamlBridge.Cct.Trace.WriteLine( Constants.TRCI_PERFORMING_CLAIM_VALUE_SUBSTITUTION, "'", spThisClaim.Name); } sThisClaimValue = sThisClaimValue.Replace("'", ""); } if (spThisClaim.Value != sThisClaimValue) { SecurityProperty spNewProperty = SecurityProperty.CreateCustomClaimProperty( spThisClaim.Name, sThisClaimValue); incomingClaims[i] = spNewProperty; } } #endregion // Determine how the user's UPN should be obtained. If the SamlBridge registry // value ResourceDomainDirectoryPath exists and has a non-empty value, then the // UPN is obtained by performing a local LDAP search based on the path defined // by the value of ResourceDomainDirectoryPath for a user whose UID corresponds // to the UID extracted from the incoming claim, and taking the UPN of this // user. // // Otherwise, if ResourceDomainDirectoryPath does not exist or has an empty // value, then the value of registry value ResourceDomainUpnSuffix is used to // create the UPN directly from the UID. If ResourceDomainUpnSuffix exists and // has a non-empty value, the UPN is generated by appending an ampersand // followed by the value of ResourceDomainUpnSuffix to the UID. If // ResourceDomainUpnSuffix does not exist or is empty, the unadorned UID is used // as the UPN. string sUpn = string.Empty; if (ResourceDomainDirectoryPath.Length != 0) { if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo) { Fujitsu.SamlBridge.Cct.Trace.WriteLine( Constants.TRCI_UPN_BY_DIRECTORY_LOOKUP); } sUpn = GetUpnByUid(sUid, incomingClaims); } else { if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo) { Fujitsu.SamlBridge.Cct.Trace.WriteLine( Constants.TRCI_UPN_BY_UID_SUFFIXING, ResourceDomainUpnSuffix); } if (ResourceDomainUpnSuffix.Length != 0) { sUpn = string.Format( Universal.SFMT_USER_PRINCIPAL_NAME, sUid, Universal.UPN_SUFFIX_PREFIX, ResourceDomainUpnSuffix); } else { sUpn = sUid; } } if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo) { Fujitsu.SamlBridge.Cct.Trace.WriteLine( Constants.TRCI_OUTGOING_RESOURCE_DOMAIN_UPN, sUpn); } // Insert a new UPN claim into the incoming claims collection, containing the // newly generated UPN. incomingClaims.Add(SecurityProperty.CreateUserPrincipalNameProperty(sUpn)); } else { if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceWarning) { Fujitsu.SamlBridge.Cct.Trace.WriteLine( Constants.TRCW_NO_INCOMING_CLAIMS_FOUND); } } }