private DelegationRestrictionType ReadDelegates(XmlReader reader)
        {
            CustomTextTraceSource ts = new CustomTextTraceSource("CommercialVehicleCollisionWebservice.CustomSaml2SecurityTokenHandler.ReadDelegates",
                "MyTraceSource", SourceLevels.Information);

            DelegationRestrictionType delegate2 = null;

            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }
            bool requireDeclaration = false;
            if (reader.IsStartElement("Condition", "urn:oasis:names:tc:SAML:2.0:assertion"))
            {
                reader.Read();
                requireDeclaration = true;
            }
            else if (!reader.IsStartElement("Delegate", "urn:oasis:names:tc:SAML:2.0:conditions:delegation"))
            {
                reader.ReadStartElement("Delegate", "urn:oasis:names:tc:SAML:2.0:conditions:delegation");
            }

            try
            {
                XmlUtil.ValidateXsiType(reader, "DelegationRestrictionType", "urn:oasis:names:tc:SAML:2.0:conditions:delegation", requireDeclaration);

                if (reader.IsEmptyElement)
                {
                    string errorMsg = string.Format("The given element ('{0}','{1}') is empty.", reader.LocalName, reader.NamespaceURI);
                    throw DiagnosticUtil.ThrowHelperXml(reader, errorMsg);
                }

                List<DelegateType> delegates = new List<DelegateType>();

                ts.TraceInformation("Before while (reader.IsStartElement(Delegate, urn:oasis:names:tc:SAML:2.0:conditions:delegation)" );
                ts.TraceInformation("\treader: " + reader.Name);

                while (reader.IsStartElement("Delegate", "urn:oasis:names:tc:SAML:2.0:conditions:delegation"))
                {
                    ts.TraceInformation("Inside while (reader.IsStartElement(Delegate, urn:oasis:names:tc:SAML:2.0:conditions:delegation)");
                    ts.TraceInformation("\treader: " + reader.Name);

                    DelegateType delegateType = new DelegateType();

                    string attribute = reader.GetAttribute("DelegationInstant");
                    if (!string.IsNullOrEmpty(attribute))
                    {
                        delegateType.DelegationInstant = XmlConvert.ToDateTime(attribute, DateTimeFormats.Accepted);
                    }
                                        
                    reader.Read();
                    ts.TraceInformation("After reader.Read()");
                    ts.TraceInformation("\treader: " + reader.Name);

                    if (!reader.IsStartElement("NameID", "urn:oasis:names:tc:SAML:2.0:assertion"))
                    {
                        ts.TraceInformation("Inside !reader.IsStartElement(NameID, urn:oasis:names:tc:SAML:2.0:assertion)");
                        ts.TraceInformation("\treader: " + reader.Name);

                        reader.ReadStartElement("NameID", "urn:oasis:names:tc:SAML:2.0:assertion");
                    }

                    delegateType.Item = ReadSimpleUriElement(reader, UriKind.RelativeOrAbsolute, true);

                    ts.TraceInformation("Delegate NameID: " + delegateType.Item.ToString());


                    delegates.Add(delegateType);

                    reader.ReadEndElement();
                }

                DelegationRestrictionType delegate1 = new DelegationRestrictionType();
                delegate1.Delegate = delegates.ToArray();

                delegate2 = delegate1;
            }
            catch (Exception exception)
            {
                Exception exception2 = DiagnosticUtil.TryWrapReadException(reader, exception);
                if (exception2 == null)
                {
                    throw;
                }

                throw exception2;
            }

            return delegate2;
        }
        protected override Saml2Conditions CreateConditions(Microsoft.IdentityModel.Protocols.WSTrust.Lifetime tokenLifetime,
            string relyingPartyAddress, SecurityTokenDescriptor tokenDescriptor)
        {
            if (null == tokenLifetime && !string.IsNullOrEmpty(relyingPartyAddress))
            {
                return null;
            }

            Saml2ConditionsDelegateWrapper conditions = new Saml2ConditionsDelegateWrapper();

            conditions.NotBefore = tokenLifetime.Created;
            conditions.NotOnOrAfter = tokenLifetime.Expires;

            // GFIPM S2S 8.8.2.6.a
            string relyingPartyEntityID = _trustFabric.GetWspEntityIdFromEndpointAddress(relyingPartyAddress);

            // Make sure that the entity id is present in the <microsoft.identityModel><service><audienceUris> collection in the 
            // WSP configuration file
            conditions.AudienceRestrictions.Add(new Saml2AudienceRestriction(new Uri(relyingPartyEntityID, UriKind.RelativeOrAbsolute)));
            
            // check if the actors are set in the subject and create the delegates from the actors
            IClaimsIdentity currentDelegate = tokenDescriptor.Subject.Actor;

            List<DelegateType> delegates = new List<DelegateType>();

            while (currentDelegate != null)
            {
                DelegateType delegateType = CreateDelegate(currentDelegate.Claims[0].Value, currentDelegate.Claims[1].Value);

                delegates.Add(delegateType);

                // most recent delegate, synchronize token creation and delegationInstant
                if (currentDelegate.Actor == null)
                {
                    if (conditions.NotBefore.HasValue)
                    {
                        delegateType.DelegationInstant = conditions.NotBefore.Value;
                    }
                }

                currentDelegate = currentDelegate.Actor;
            }

            DelegationRestrictionType delegate1 = new DelegationRestrictionType();

            delegate1.Delegate = delegates.ToArray();

            conditions.Delegates = delegate1;

            return conditions;
        }
        // This is actually augmenting the claims in the subject. At the WSP, this should not return any claims!
        //public override ClaimsIdentityCollection ValidateToken(SecurityToken token)
        //{
        //    CustomTextTraceSource ts = new CustomTextTraceSource("CommercialVehicleCollisionWebservice.CustomSaml2SecurityTokenHandler.ValidateToken",
        //           "MyTraceSource", SourceLevels.Information);

        //    ClaimsIdentityCollection ret = null;


        //    SerializeTokenToStream(token as Saml2SecurityToken, ts, "ValidateToken");


        //    IClaimsIdentity claimsIdentity = null;

        //    if (token == null)
        //    {
        //        throw new ArgumentNullException("token");
        //    }
            
        //    Saml2SecurityToken token2 = token as Saml2SecurityToken;
        //    if (token2 == null)
        //    {
        //        throw new ArgumentNullException("null Saml2SecurityToken");
        //    }

        //    if (base.Configuration == null)
        //    {
        //        throw new InvalidOperationException("null Configuration");
        //    }
        //    Saml2Assertion assertion = token2.Assertion;

        //    //bool shouldEnforceAudienceRestriction = this.SamlSecurityTokenRequirement.ShouldEnforceAudienceRestriction(
        //    //    base.Configuration.AudienceRestriction.AudienceMode, token2);

        //    this.ValidateConditions(assertion.Conditions,
        //        this.SamlSecurityTokenRequirement.ShouldEnforceAudienceRestriction(base.Configuration.AudienceRestriction.AudienceMode, token2));

        //    //Saml2SubjectConfirmation confirmation = assertion.Subject.SubjectConfirmations[0];

        //    // certificate that signed the assertion internally!
        //    X509SecurityToken issuerToken = token2.IssuerToken as X509SecurityToken;
        //    if (issuerToken != null)
        //    {
        //        // Here we validate the Issuer certificate
        //        this.CertificateValidator.Validate(issuerToken.Certificate);
        //    }

        //    claimsIdentity = this.CreateClaims(token2);

        //    if (base.Configuration.DetectReplayedTokens)
        //    {
        //        this.DetectReplayedTokens(token2);
        //    }

        //    // This will be needed if chaining WSP/WSC 
        //    if (base.Configuration.SaveBootstrapTokens)
        //    {
        //        claimsIdentity.BootstrapToken = token;
        //    }

        //    // Debug
        //    ClaimsIdentityCollection ids = new ClaimsIdentityCollection();
        //    ids.Add(claimsIdentity);
        //    IClaimsPrincipal p = new ClaimsPrincipal(ids);
        //    ClaimsUtil.LogClaimsPrincipal(p, "CommercialVehicleCollisionWebservice.CustomSaml2SecurityTokenHandler.ValidateToken)");
                
        //    ret = new ClaimsIdentityCollection(new IClaimsIdentity[] { claimsIdentity });

        //    return ret;
        //}
        #endregion

        protected void ValidateDelegates(DelegationRestrictionType delegation)
        {
            CustomTextTraceSource ts = new CustomTextTraceSource("CommercialVehicleCollisionWebservice.CustomSaml2SecurityTokenHandler.ValidateDelegates",
               "MyTraceSource", SourceLevels.Information);

            // get all intermediaries IDs 
            List<string> wscEndityIds = new List<string>();

            foreach (DelegateType wscDelegate in delegation.Delegate)
            {
                ts.TraceInformation("Delegate NameID: " + wscDelegate.Item.ToString());

                wscEndityIds.Add(wscDelegate.Item.ToString());
            }

            // Here we verify that all the entityIDs are part of the trust fabric
            if (!_trustFabric.Contains(wscEndityIds))
            {
                throw new InvalidSecurityException("Not all of the intermediaries in the delegation chain are present in the Trust Fabric.");
            }
        }
        private DelegationRestrictionType ReadDelegates(XmlReader reader)
        {
            CustomAdsTextTraceSource ts = new CustomAdsTextTraceSource("IdpAds.OnBehalfOfSaml2SecurityTokenHandler.ReadDelegates",
                "AdsTraceSource", SourceLevels.Information);

            //DelegationRestrictionType delegate2 = null;

            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }

            bool requireDeclaration = false;
            if (reader.IsStartElement("Condition", "urn:oasis:names:tc:SAML:2.0:assertion"))
            {
                reader.Read();
                requireDeclaration = true;
            }
            else if (!reader.IsStartElement("Delegate", "urn:oasis:names:tc:SAML:2.0:conditions:delegation"))
            {
                reader.ReadStartElement("Delegate", "urn:oasis:names:tc:SAML:2.0:conditions:delegation");
            }
                        
            bool isEmptyElement = reader.IsEmptyElement;
            XmlUtil.ValidateXsiType(reader, "DelegationRestrictionType", "urn:oasis:names:tc:SAML:2.0:conditions:delegation", requireDeclaration);

            if (isEmptyElement)
            {
                string errorMsg = string.Format("The given element ('{0}','{1}') is empty.", reader.LocalName, reader.NamespaceURI);

                throw DiagnosticUtil.ThrowHelperXml(reader, errorMsg);
            }

            List<DelegateType> delegates = new List<DelegateType>();

            while (reader.IsStartElement("Delegate", "urn:oasis:names:tc:SAML:2.0:conditions:delegation"))
            {
                DelegateType delegateType = new DelegateType();

                string attribute = reader.GetAttribute("DelegationInstant");

                if (!string.IsNullOrEmpty(attribute))
                {
                    delegateType.DelegationInstant = XmlConvert.ToDateTime(attribute, DateTimeFormats.Accepted);
                }

                // What does this do?
                reader.Read();

                if (!reader.IsStartElement("NameID", "urn:oasis:names:tc:SAML:2.0:assertion"))
                {
                    reader.ReadStartElement("NameID", "urn:oasis:names:tc:SAML:2.0:assertion");
                }

                // TODO: Investgate the proper way to read this
                delegateType.Item = ReadSimpleUriElement(reader, UriKind.RelativeOrAbsolute, true);
                delegates.Add(delegateType);

                reader.ReadEndElement();
            }

            DelegationRestrictionType delegateRestriction = new DelegationRestrictionType();
            delegateRestriction.Delegate = delegates.ToArray();

            //delegate2 = delegate1;
            return delegateRestriction;
        

            //return delegate2;
        }