public void Saml2SubjectExtensions_ToXElement_SubjectConfirmation()
        {
            var saml2SubjectConfirmation = new Saml2SubjectConfirmation(new Uri("urn:oasis:names:tc:SAML:2.0:cm:bearer"));

            var confirmation = saml2SubjectConfirmation.ToXElement();

            confirmation.Attribute("Method").Value.Should().Be("urn:oasis:names:tc:SAML:2.0:cm:bearer");
        }
        /// <summary>
        /// Initializes an instance of <see cref="Saml2Subject"/> from a <see cref="Saml2SubjectConfirmation"/>.
        /// </summary>
        /// <param name="subjectConfirmation">The <see cref="Saml2SubjectConfirmation"/> to use for initialization.</param>
        public Saml2Subject(Saml2SubjectConfirmation subjectConfirmation)
        {
            if (null == subjectConfirmation)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("subjectConfirmation");
            }

            this.subjectConfirmations.Add(subjectConfirmation);
        }
        /// <summary>
        /// Initializes an instance of <see cref="Saml2Subject"/> from a <see cref="Saml2SubjectConfirmation"/>.
        /// </summary>
        /// <param name="subjectConfirmation">The <see cref="Saml2SubjectConfirmation"/> to use for initialization.</param>
        public Saml2Subject(Saml2SubjectConfirmation subjectConfirmation)
        {
            if (null == subjectConfirmation)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("subjectConfirmation");
            }

            this.subjectConfirmations.Add(subjectConfirmation);
        }
        /// <summary>
        /// Writes the &lt;saml:SubjectConfirmation> element.
        /// </summary>
        /// <param name="writer">A <see cref="XmlWriter"/> to serialize the <see cref="Saml2SubjectConfirmation"/>.</param>
        /// <param name="data">The <see cref="Saml2SubjectConfirmation"/> to serialize.</param>
        protected virtual void WriteSubjectConfirmation(XmlWriter writer, Saml2SubjectConfirmation data)
        {
            if (null == writer)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer");
            }

            if (null == data)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("data");
            }

            if (null == data.Method)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("data.Method");
            }

            if (string.IsNullOrEmpty(data.Method.ToString()))
            {
                throw DiagnosticUtility.ThrowHelperArgumentNullOrEmptyString("data.Method");
            }

            // <SubjectConfirmation>
            writer.WriteStartElement(Saml2Constants.Elements.SubjectConfirmation, Saml2Constants.Namespace);

            // @Method - required
            writer.WriteAttributeString(Saml2Constants.Attributes.Method, data.Method.AbsoluteUri);

            // <NameID> 0-1
            if (null != data.NameIdentifier)
            {
                this.WriteNameId(writer, data.NameIdentifier);
            }

            // <SubjectConfirmationData> 0-1
            if (null != data.SubjectConfirmationData)
            {
                this.WriteSubjectConfirmationData(writer, data.SubjectConfirmationData);
            }

            // </SubjectConfirmation>
            writer.WriteEndElement();
        }
        /// <summary>
        /// Reads the &lt;SubjectConfirmation> element.
        /// </summary>
        /// <param name="reader">A <see cref="XmlReader"/> positioned at a <see cref="Saml2SubjectConfirmation"/> element.</param>
        /// <returns>An instance of <see cref="Saml2SubjectConfirmation"/> .</returns>
        protected virtual Saml2SubjectConfirmation ReadSubjectConfirmation(XmlReader reader)
        {
            if (null == reader)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader");
            }

            // throw if wrong element
            if (!reader.IsStartElement(Saml2Constants.Elements.SubjectConfirmation, Saml2Constants.Namespace))
            {
                reader.ReadStartElement(Saml2Constants.Elements.SubjectConfirmation, Saml2Constants.Namespace);
            }

            try
            {
                bool isEmpty = reader.IsEmptyElement;

                // @attributes

                // @xsi:type
                XmlUtil.ValidateXsiType(reader, Saml2Constants.Types.SubjectConfirmationType, Saml2Constants.Namespace);

                // @Method - required
                string method = reader.GetAttribute(Saml2Constants.Attributes.Method);
                if (string.IsNullOrEmpty(method))
                {
                    throw DiagnosticUtility.ThrowHelperXml(reader, SR.GetString(SR.ID0001, Saml2Constants.Attributes.Method, Saml2Constants.Elements.SubjectConfirmation));
                }

                if (!UriUtil.CanCreateValidUri(method, UriKind.Absolute))
                {
                    throw DiagnosticUtility.ThrowHelperXml(reader, SR.GetString(SR.ID0011, Saml2Constants.Attributes.Method, Saml2Constants.Elements.SubjectConfirmation));
                }

                // Construct the appropriate SubjectConfirmation based on the method
                Saml2SubjectConfirmation subjectConfirmation = new Saml2SubjectConfirmation(new Uri(method));

                // <elements>
                reader.Read();
                if (!isEmpty)
                {
                    // <NameID> | <EncryptedID> | <BaseID> 0-1
                    subjectConfirmation.NameIdentifier = this.ReadSubjectId(reader, Saml2Constants.Elements.SubjectConfirmation);

                    // <SubjectConfirmationData> 0-1
                    if (reader.IsStartElement(Saml2Constants.Elements.SubjectConfirmationData, Saml2Constants.Namespace))
                    {
                        subjectConfirmation.SubjectConfirmationData = this.ReadSubjectConfirmationData(reader);
                    }

                    reader.ReadEndElement();
                }

                return subjectConfirmation;
            }
            catch (Exception e)
            {
                if (System.Runtime.Fx.IsFatal(e))
                    throw;
                
                Exception wrapped = TryWrapReadException(reader, e);
                if (null == wrapped)
                {
                    throw;
                }
                else
                {
                    throw wrapped;
                }
            }
        }
        /// <summary>
        /// Creates a SAML2 subject of the assertion.
        /// </summary>
        /// <param name="tokenDescriptor">The security token descriptor to create the subject.</param>
        /// <exception cref="ArgumentNullException">Thrown when 'tokenDescriptor' is null.</exception>
        /// <returns>A Saml2Subject.</returns>
        protected virtual Saml2Subject CreateSamlSubject(SecurityTokenDescriptor tokenDescriptor)
        {
            if (null == tokenDescriptor)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("tokenDescriptor");
            }

            Saml2Subject saml2Subject = new Saml2Subject();

            // Look for name identifier claims
            string nameIdentifierClaim = null;
            string nameIdentifierFormat = null;
            string nameIdentifierNameQualifier = null;
            string nameIdentifierSpProviderId = null;
            string nameIdentifierSpNameQualifier = null;

            if (tokenDescriptor.Subject != null && tokenDescriptor.Subject.Claims != null)
            {
                foreach (Claim claim in tokenDescriptor.Subject.Claims)
                {
                    if (claim.Type == ClaimTypes.NameIdentifier)
                    {
                        // Do not allow multiple name identifier claim.
                        if (null != nameIdentifierClaim)
                        {
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ID4139)));
                        }

                        nameIdentifierClaim = claim.Value;

                        if (claim.Properties.ContainsKey(ClaimProperties.SamlNameIdentifierFormat))
                        {
                            nameIdentifierFormat = claim.Properties[ClaimProperties.SamlNameIdentifierFormat];
                        }

                        if (claim.Properties.ContainsKey(ClaimProperties.SamlNameIdentifierNameQualifier))
                        {
                            nameIdentifierNameQualifier = claim.Properties[ClaimProperties.SamlNameIdentifierNameQualifier];
                        }

                        if (claim.Properties.ContainsKey(ClaimProperties.SamlNameIdentifierSPNameQualifier))
                        {
                            nameIdentifierSpNameQualifier = claim.Properties[ClaimProperties.SamlNameIdentifierSPNameQualifier];
                        }

                        if (claim.Properties.ContainsKey(ClaimProperties.SamlNameIdentifierSPProvidedId))
                        {
                            nameIdentifierSpProviderId = claim.Properties[ClaimProperties.SamlNameIdentifierSPProvidedId];
                        }
                    }
                }
            }

            if (nameIdentifierClaim != null)
            {
                Saml2NameIdentifier nameIdentifier = new Saml2NameIdentifier(nameIdentifierClaim);

                if (nameIdentifierFormat != null && UriUtil.CanCreateValidUri(nameIdentifierFormat, UriKind.Absolute))
                {
                    nameIdentifier.Format = new Uri(nameIdentifierFormat);
                }

                nameIdentifier.NameQualifier = nameIdentifierNameQualifier;
                nameIdentifier.SPNameQualifier = nameIdentifierSpNameQualifier;
                nameIdentifier.SPProvidedId = nameIdentifierSpProviderId;

                saml2Subject.NameId = nameIdentifier;
            }

            // Add subject confirmation data
            Saml2SubjectConfirmation subjectConfirmation;
            if (null == tokenDescriptor.Proof)
            {
                subjectConfirmation = new Saml2SubjectConfirmation(Saml2Constants.ConfirmationMethods.Bearer);
            }
            else
            {
                subjectConfirmation = new Saml2SubjectConfirmation(Saml2Constants.ConfirmationMethods.HolderOfKey, new Saml2SubjectConfirmationData());
                subjectConfirmation.SubjectConfirmationData.KeyIdentifiers.Add(tokenDescriptor.Proof.KeyIdentifier);
            }

            saml2Subject.SubjectConfirmations.Add(subjectConfirmation);

            return saml2Subject;
        }
        protected override Saml2Subject CreateSamlSubject(SecurityTokenDescriptor tokenDescriptor)
        {
            Saml2SubjectConfirmation confirmation;
            if (tokenDescriptor == null)
            {
                throw new ArgumentNullException("tokenDescriptor");
            }
            Saml2Subject subject = new Saml2Subject();
            string name = null;
            string uriString = null;

            if ((tokenDescriptor.Subject != null) && (tokenDescriptor.Subject.Claims != null))
            {
                foreach (Claim claim in tokenDescriptor.Subject.Claims)
                {
                    if (claim.ClaimType == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier")
                    {
                        if (name != null)
                        {
                            throw new InvalidOperationException(
                                "No suitable Saml2NameIdentifier could be created for the SAML2:Subject because more than one Claim of type NameIdentifier was supplied.");
                        }
                        name = claim.Value;
                        if (claim.Properties.ContainsKey("http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/format"))
                        {
                            uriString = claim.Properties["http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/format"];
                        }                        
                    }
                }
            }
            if (name != null)
            {
                Saml2NameIdentifier identifier = new Saml2NameIdentifier(name);

                if ((uriString != null) && UriUtil.CanCreateValidUri(uriString, UriKind.Absolute))
                {
                    identifier.Format = new Uri(uriString);
                }
                subject.NameId = identifier;
            }

            // IGNORE SAML confirmation and just create the SenderVouches

            // GFIPM S2S 8.8.2.6.c
            confirmation = new Saml2SubjectConfirmation(Saml2Constants.ConfirmationMethods.SenderVouches);

            // SAML V2.0 Condition for Delegation Restriction Version 1.0
            // 2.5 Use of Identifiers Within <saml:SubjectConfirmation>
            string lastDelegateNameId = tokenDescriptor.Subject.Actor.Name;
            confirmation.NameIdentifier = new Saml2NameIdentifier(lastDelegateNameId);

            subject.SubjectConfirmations.Add(confirmation);

            return subject;
        }
        private Saml2Assertion NewAssertion()
        {
            var assertion = new Saml2Assertion(new Saml2NameIdentifier(certificate.Subject));
            assertion.Id = new Saml2Id();
            assertion.IssueInstant = DateTime.Now;

            assertion.Subject = new Saml2Subject(new Saml2NameIdentifier("CPS") { Value = "id3" });
            assertion.Statements.Add(new Saml2AttributeStatement(new Saml2Attribute("identifiantFacturation", "id1")));
            assertion.Statements.Add(new Saml2AttributeStatement(new Saml2Attribute("codeSpecialiteAMO", "id2")));

            var saml2SubjectConfirmation = new Saml2SubjectConfirmation(new Uri("urn:oasis:names:tc:SAML:2.0:cm:bearer"));
            saml2SubjectConfirmation.SubjectConfirmationData = new Saml2SubjectConfirmationData();
            saml2SubjectConfirmation.SubjectConfirmationData.Recipient = new Uri("http://identityserver3");
            saml2SubjectConfirmation.SubjectConfirmationData.NotOnOrAfter = DateTime.UtcNow;

            assertion.Subject.SubjectConfirmations.Add(saml2SubjectConfirmation);

            assertion.SigningCredentials = new X509SigningCredentials(certificate);
            return assertion;
        }
        private Saml2Assertion NewAssertion(X509Certificate2 x509Certificate2 = null, ClaimsIdentity id = null)
        {
            var cert = x509Certificate2 ?? certificate;
            var assertion = new Saml2Assertion(new Saml2NameIdentifier("b"));
            assertion.Id = new Saml2Id();
            assertion.IssueInstant = DateTime.Now;

            assertion.Subject = new Saml2Subject(new Saml2NameIdentifier("CPS") { Value = "id3" });
            assertion.Statements.Add(new Saml2AttributeStatement(new Saml2Attribute("identifiantFacturation", "id1")));
            assertion.Statements.Add(new Saml2AttributeStatement(new Saml2Attribute("codeSpecialiteAMO", "id2")));
            if (id != null)
            foreach (var claim in id.Claims)
            {
                assertion.Statements.Add(new Saml2AttributeStatement(new Saml2Attribute(claim.Type, claim.Value)));
            }


            var saml2SubjectConfirmation = new Saml2SubjectConfirmation(new Uri("urn:oasis:names:tc:SAML:2.0:cm:bearer"));
            saml2SubjectConfirmation.SubjectConfirmationData = new Saml2SubjectConfirmationData();
            saml2SubjectConfirmation.SubjectConfirmationData.Recipient = new Uri("http://allowed_recipient1");
            saml2SubjectConfirmation.SubjectConfirmationData.NotOnOrAfter = DateTime.UtcNow.AddHours(1); // valid for 1 hour

            assertion.Subject.SubjectConfirmations.Add(saml2SubjectConfirmation);

            assertion.Conditions = new Saml2Conditions();
            assertion.Conditions.AudienceRestrictions.Add(new Saml2AudienceRestriction(new Uri("http://audience")));

            assertion.SigningCredentials = new X509SigningCredentials(cert);
            return assertion;
        }