Пример #1
0
        /// <summary>
        /// Определяет соответствует ли значение объекта класса T условию заданному в фильтре.
        /// </summary>
        /// <typeparam name="TValue">Тип свойства указанного в фильтре.</typeparam>
        /// <param name="value1">Значение заданное в фильтре.</param>
        /// <param name="value2">Значение свойства для текущего объекта.</param>
        /// <param name="condition">Тип сравнения.</param>
        /// <returns>true если соответсвует, false если нет.</returns>
        private bool _ComparerCore <TValue>(string value1, TValue value2, ConditionsType condition) where TValue : IComparable
        {
            var _comparigValue = (TValue)Convert.ChangeType(value1, typeof(TValue));

            switch (condition)
            {
            case ConditionsType.Equal:
                return(value2.CompareTo(_comparigValue) == 0);

            case ConditionsType.Less:
                return(value2.CompareTo(_comparigValue) < 0);

            case ConditionsType.More:
                return(value2.CompareTo(_comparigValue) > 0);

            case ConditionsType.NotEqual:
                return(value2.CompareTo(_comparigValue) != 0);

            case ConditionsType.Like:
                return(typeof(TValue) == typeof(string) && new Func <bool>(() => {
                    return new Regex(string.Format("^{0}$", _comparigValue.ToString().ToUpper().Replace("%", ".*"))).IsMatch(value2.ToString().ToUpper());
                })());

            default:
                return(false);
            }
        }
Пример #2
0
        public static void ValidateConditions(ConditionsType conditions, ServiceProviderModel serviceProvider)
        {
            if (conditions.NotBefore == default(DateTime) || conditions.NotOnOrAfter == default(DateTime))
            {
                throw new Exception($"{nameof(conditions.NotBefore)} or {nameof(conditions.NotOnOrAfter)} is invalid");
            }

            if (conditions.NotBefore >= conditions.NotOnOrAfter)
            {
                throw new Exception($"{nameof(conditions.NotBefore)} should be lesser than {nameof(conditions.NotOnOrAfter)}");
            }

            foreach (ConditionAbstractType condition in conditions.Items)
            {
                if (conditions.Items.Count() <= 0)
                {
                    throw new Exception($"{nameof(conditions.Items)} array cannnot be empty");
                }

                if (condition is AudienceRestrictionType audienceRestrictionType)
                {
                    if (!audienceRestrictionType.Audience.Any(a => a == serviceProvider.Name))
                    {
                        throw new Exception($"{audienceRestrictionType.Audience} does not mention {serviceProvider.Name}");
                    }
                }
            }
        }
Пример #3
0
        /// <summary>
        /// Must be evaluated when assessing the validity of and/or when using the assertion.
        /// </summary>
        /// <param name="notBefore">Specifies the earliest time instant at which the assertion is valid.</param>
        /// <param name="notOnOrAfter">Specifies the time instance at which the assertion has expired.</param>
        /// <param name="callback"></param>
        /// <returns></returns>
        public AssertionBuilder SetConditions(DateTime?notBefore, DateTime?notOnOrAfter, Action <ConditionsBuilder> callback)
        {
            var conditions = new ConditionsType();

            if (notBefore != null)
            {
                conditions.NotBeforeSpecified = true;
                conditions.NotBefore          = notBefore.Value;
            }

            if (notOnOrAfter != null)
            {
                conditions.NotOnOrAfterSpecified = true;
                conditions.NotOnOrAfter          = notOnOrAfter.Value;
            }

            var builder = new ConditionsBuilder(conditions);

            callback(builder);
            _assertion.Conditions = conditions;
            return(this);
            // AttributeStatement
        }
Пример #4
0
        /// <summary>
        /// Creates a Version 1.1 Saml Assertion
        /// </summary>
        /// <param name="issuer">Issuer</param>
        /// <param name="subject">Subject</param>
        /// <param name="attributes">Attributes</param>
        /// <returns>returns a Version 1.1 Saml Assertion</returns>
        private static AssertionType CreateSamlAssertion(string issuer, string recipient, string domain, string subject, Dictionary <string, string> attributes)
        {
            // Here we create some SAML assertion with ID and Issuer name.
            AssertionType assertion = new AssertionType();

            assertion.ID = "_" + Guid.NewGuid().ToString();

            NameIDType issuerForAssertion = new NameIDType();

            issuerForAssertion.Value = issuer.Trim();

            assertion.Issuer  = issuerForAssertion;
            assertion.Version = "2.0";

            assertion.IssueInstant = System.DateTime.UtcNow;

            //Not before, not after conditions
            ConditionsType conditions = new ConditionsType();

            conditions.NotBefore             = DateTime.UtcNow;
            conditions.NotBeforeSpecified    = true;
            conditions.NotOnOrAfter          = DateTime.UtcNow.AddMinutes(5);
            conditions.NotOnOrAfterSpecified = true;

            AudienceRestrictionType audienceRestriction = new AudienceRestrictionType();

            audienceRestriction.Audience = new string[] { domain.Trim() };

            conditions.Items = new ConditionAbstractType[] { audienceRestriction };

            //Name Identifier to be used in Saml Subject
            NameIDType nameIdentifier = new NameIDType();

            nameIdentifier.NameQualifier = domain.Trim();
            nameIdentifier.Value         = subject.Trim();

            SubjectConfirmationType     subjectConfirmation     = new SubjectConfirmationType();
            SubjectConfirmationDataType subjectConfirmationData = new SubjectConfirmationDataType();

            subjectConfirmation.Method = "urn:oasis:names:tc:SAML:2.0:cm:bearer";
            subjectConfirmation.SubjectConfirmationData = subjectConfirmationData;
            //
            // Create some SAML subject.
            SubjectType samlSubject = new SubjectType();

            AttributeStatementType attrStatement = new AttributeStatementType();
            AuthnStatementType     authStatement = new AuthnStatementType();

            authStatement.AuthnInstant = DateTime.UtcNow;
            AuthnContextType context = new AuthnContextType();

            context.ItemsElementName   = new ItemsChoiceType5[] { ItemsChoiceType5.AuthnContextClassRef };
            context.Items              = new object[] { "AuthnContextClassRef" };
            authStatement.AuthnContext = context;

            samlSubject.Items = new object[] { nameIdentifier, subjectConfirmation };

            assertion.Subject = samlSubject;

            IPHostEntry ipEntry =
                Dns.GetHostEntry(System.Environment.MachineName);

            SubjectLocalityType subjectLocality = new SubjectLocalityType();

            subjectLocality.Address = ipEntry.AddressList[0].ToString();

            attrStatement.Items = new AttributeType[attributes.Count];
            int i = 0;

            // Create userName SAML attributes.
            foreach (KeyValuePair <string, string> attribute in attributes)
            {
                AttributeType attr = new AttributeType();
                attr.Name              = attribute.Key;
                attr.NameFormat        = "urn:oasis:names:tc:SAML:2.0:attrname-format:basic";
                attr.AttributeValue    = new object[] { attribute.Value };
                attrStatement.Items[i] = attr;
                i++;
            }
            assertion.Conditions = conditions;

            assertion.Items = new StatementAbstractType[] { authStatement, attrStatement };

            return(assertion);
        }
Пример #5
0
 private bool _CompareCore(Type valueType, string value1, object value2, ConditionsType condition)
 {
     return((bool)typeof(SortedBindingList <T>).GetMethod("_ComparerCore", BindingFlags.NonPublic | BindingFlags.Instance).MakeGenericMethod(new Type[] { valueType }).Invoke(this, new object[] { value1, value2, condition }));
 }
Пример #6
0
        /// <summary>
        /// Creates a SAML 2.0 Assertion Segment for a Response
        /// Simple implmenetation assuming a list of string key and value pairs
        /// </summary>
        /// <param name="Issuer"></param>
        /// <param name="AssertionExpirationMinutes"></param>
        /// <param name="Audience"></param>
        /// <param name="Subject"></param>
        /// <param name="Recipient"></param>
        /// <param name="Attributes">Dictionary of string key, string value pairs</param>
        /// <returns>Assertion to sign and include in Response</returns>
        private static AssertionType CreateSAML20Assertion(string Issuer,
                                                           int AssertionExpirationMinutes,
                                                           string Audience,
                                                           string Subject,
                                                           string Recipient,
                                                           Dictionary <string, string> Attributes)
        {
            AssertionType NewAssertion = new AssertionType()
            {
                Version      = "2.0",
                IssueInstant = DateTime.Now,//DateTime.UtcNow,
                ID           = "_" + System.Guid.NewGuid().ToString()
            };

            // Create Issuer
            NewAssertion.Issuer = new NameIDType()
            {
                Value = Issuer.Trim()
            };

            // Create Assertion Subject
            SubjectType subject = new SubjectType();
            NameIDType  subjectNameIdentifier = new NameIDType()
            {
                Value = Subject.Trim(), Format = "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
            };
            SubjectConfirmationType subjectConfirmation = new SubjectConfirmationType()
            {
                Method = "urn:oasis:names:tc:SAML:2.0:cm:bearer", SubjectConfirmationData = new SubjectConfirmationDataType()
                {
                    NotOnOrAfter = DateTime.Now.AddMinutes(AssertionExpirationMinutes), Recipient = Recipient
                }
            };                                                                                                                                                                                                                                                                                           //{ NotOnOrAfter = DateTime.UtcNow.AddMinutes(AssertionExpirationMinutes), Recipient = Recipient } };

            subject.Items        = new object[] { subjectNameIdentifier, subjectConfirmation };
            NewAssertion.Subject = subject;

            // Create Assertion Conditions
            ConditionsType conditions = new ConditionsType();

            conditions.NotBefore             = DateTime.Now;                                        //DateTime.UtcNow;
            conditions.NotBeforeSpecified    = true;
            conditions.NotOnOrAfter          = DateTime.Now.AddMinutes(AssertionExpirationMinutes); //DateTime.UtcNow.AddMinutes(AssertionExpirationMinutes);
            conditions.NotOnOrAfterSpecified = true;
            conditions.Items = new ConditionAbstractType[] { new AudienceRestrictionType()
                                                             {
                                                                 Audience = new string[] { Audience.Trim() }
                                                             } };
            NewAssertion.Conditions = conditions;

            // Add AuthnStatement and Attributes as Items
            AuthnStatementType authStatement = new AuthnStatementType()
            {
                AuthnInstant = DateTime.Now, SessionIndex = NewAssertion.ID
            };                                                                                                                           //{ AuthnInstant = DateTime.UtcNow, SessionIndex = NewAssertion.ID };
            AuthnContextType context = new AuthnContextType();

            context.ItemsElementName   = new ItemsChoiceType5[] { ItemsChoiceType5.AuthnContextClassRef };
            context.Items              = new object[] { "urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified" };
            authStatement.AuthnContext = context;

            AttributeStatementType attributeStatement = new AttributeStatementType();

            attributeStatement.Items = new AttributeType[Attributes.Count];
            int i = 0;

            foreach (KeyValuePair <string, string> attribute in Attributes)
            {
                attributeStatement.Items[i] = new AttributeType()
                {
                    Name           = attribute.Key,
                    AttributeValue = new object[] { attribute.Value },
                    NameFormat     = "urn:oasis:names:tc:SAML:2.0:attrname-format:basic"
                };
                i++;
            }

            NewAssertion.Items = new StatementAbstractType[] { authStatement, attributeStatement };

            return(NewAssertion);
        }
Пример #7
0
        private static AssertionType CreateSamlAssertion(AuthnRequestType samlAuthRequest, string username)
        {
            var assertion = new AssertionType
            {
                Version      = "2.0",
                IssueInstant = DateTime.UtcNow,
                ID           = "_" + Guid.NewGuid(),
                Issuer       = new NameIDType()
                {
                    Value = $"{_context.Request.Scheme}://{_context.Request.Host}{_context.Request.PathBase}"
                }
            };

            //Assertion Subject
            var subject = new SubjectType();
            var subjectNameIdentifier = new NameIDType()
            {
                Value = username, Format = Saml2Constants.NameIdentifierFormats.Unspecified
            };
            var subjectConfirmation = new SubjectConfirmationType()
            {
                Method = Saml2Constants.SubjectConfirmationMethods.HolderOfKey,
                SubjectConfirmationData = new SubjectConfirmationDataType()
                {
                    NotOnOrAfter = DateTime.UtcNow.AddMinutes(ASSERTION_TIMEOUT_IN_MINUTES),
                    Recipient    = samlAuthRequest.AssertionConsumerServiceURL,
                    InResponseTo = samlAuthRequest.ID
                }
            };

            subject.Items     = new object[] { subjectNameIdentifier, subjectConfirmation };
            assertion.Subject = subject;

            //Assertion Conditions
            var conditions = new ConditionsType
            {
                NotBefore             = DateTime.UtcNow,
                NotBeforeSpecified    = true,
                NotOnOrAfter          = DateTime.UtcNow.AddMinutes(ASSERTION_TIMEOUT_IN_MINUTES),
                NotOnOrAfterSpecified = true,
                //TODO: samlAuthRequest.Issuer.Value should be replaced with
                Items = new ConditionAbstractType[] { new AudienceRestrictionType()
                                                      {
                                                          Audience = new string[] { samlAuthRequest.Issuer.Value }
                                                      } }
            };

            assertion.Conditions = conditions;

            //Assertion AuthnStatement
            var authStatement = new AuthnStatementType()
            {
                AuthnInstant = DateTime.UtcNow, SessionIndex = assertion.ID
            };
            var context = new AuthnContextType();

            context.ItemsElementName   = new[] { ItemsChoiceType5.AuthnContextClassRef };
            context.Items              = new object[] { "urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified" };
            authStatement.AuthnContext = context;

            //Assertion AttributeStatement
            var attributeStatement = new AttributeStatementType();

            attributeStatement.Items = new AttributeType[]
            {
                //Add as many attributes as you want here, these are the user details that service provider wants, we can customise the attributes required
                // on the basis of service provider that requires this assertion
                new AttributeType {
                    Name = "username", AttributeValue = username, NameFormat = "urn:oasis:names:tc:SAML:2.0:attrname-format:basic"
                }
            };
            assertion.Items = new StatementAbstractType[] { authStatement, attributeStatement };

            return(assertion);
        }
Пример #8
0
        /// <summary>
        /// Creates a SAML 2.0 Assertion Segment for a Response
        /// Simple implmenetation assuming a list of string key and value pairs
        /// </summary>
        /// <param name="issuer"></param>
        /// <param name="assertionExpirationMinutes"></param>
        /// <param name="audience"></param>
        /// <param name="subject"></param>
        /// <param name="recipient"></param>
        /// <param name="attributes">Dictionary of string key, string value pairs</param>
        /// <returns>Assertion to sign and include in Response</returns>
        private static AssertionType CreateSaml20Assertion(string issuer,
                                                           int assertionExpirationMinutes,
                                                           string audience,
                                                           string subject,
                                                           string recipient,
                                                           Dictionary <string, string> attributes)
        {
            AssertionType newAssertion = new AssertionType
            {
                Version      = "2.0",
                IssueInstant = DateTime.UtcNow,
                ID           = "_" + Guid.NewGuid(),
                Issuer       = new NameIDType {
                    Value = issuer.Trim()
                }
            };

            // Create Issuer

            // Create Assertion Subject
            SubjectType subjectType           = new SubjectType();
            NameIDType  subjectNameIdentifier = new NameIDType {
                Value = subject.Trim(), Format = "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
            };
            SubjectConfirmationType subjectConfirmation = new SubjectConfirmationType {
                Method = "urn:oasis:names:tc:SAML:2.0:cm:bearer", SubjectConfirmationData = new SubjectConfirmationDataType {
                    NotOnOrAfter = DateTime.UtcNow.AddMinutes(assertionExpirationMinutes), Recipient = recipient
                }
            };

            subjectType.Items    = new object[] { subjectNameIdentifier, subjectConfirmation };
            newAssertion.Subject = subjectType;

            // Create Assertion Conditions
            ConditionsType conditions = new ConditionsType
            {
                NotBefore             = DateTime.UtcNow,
                NotBeforeSpecified    = true,
                NotOnOrAfter          = DateTime.UtcNow.AddMinutes(assertionExpirationMinutes),
                NotOnOrAfterSpecified = true,
                Items = new ConditionAbstractType[] { new AudienceRestrictionType {
                                                          Audience = new[] { audience.Trim() }
                                                      } }
            };

            newAssertion.Conditions = conditions;

            // Add AuthnStatement and Attributes as Items
            AuthnStatementType authStatement = new AuthnStatementType {
                AuthnInstant = DateTime.UtcNow, SessionIndex = newAssertion.ID
            };
            AuthnContextType context = new AuthnContextType
            {
                ItemsElementName = new[] { ItemsChoiceType5.AuthnContextClassRef },
                Items            = new object[] { "urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified" }
            };

            authStatement.AuthnContext = context;

            AttributeStatementType attributeStatement = new AttributeStatementType
            {
                Items = new object[attributes.Count]
            };
            int i = 0;

            foreach (KeyValuePair <string, string> attribute in attributes)
            {
                attributeStatement.Items[i] = new AttributeType
                {
                    Name           = attribute.Key,
                    AttributeValue = new object[] { attribute.Value },
                    NameFormat     = "urn:oasis:names:tc:SAML:2.0:attrname-format:basic"
                };
                i++;
            }

            newAssertion.Items = new StatementAbstractType[] { authStatement, attributeStatement };

            return(newAssertion);
        }
Пример #9
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="UUID"></param>
        /// <param name="Destination"></param>
        /// <param name="ConsumerServiceURL"></param>
        /// <param name="certFile"></param>
        /// <param name="certPassword"></param>
        /// <param name="storeLocation"></param>
        /// <param name="storeName"></param>
        /// <param name="findType"></param>
        /// <param name="findValue"></param>
        /// <param name="signatureType"></param>
        /// <returns></returns>
        public static string BuildPostSamlRequest(string UUID, string Destination, string ConsumerServiceURL, int SecurityLevel,
                                                  string certFile, string certPassword,
                                                  StoreLocation storeLocation, StoreName storeName,
                                                  X509FindType findType, object findValue, SigningHelper.SignatureType signatureType, string IdentityProvider, int Enviroment)
        {
            AuthnRequestType MyRequest = new AuthnRequestType
            {
                ID      = UUID,
                Version = "2.0"
            };
            DateTime now         = DateTime.UtcNow;
            DateTime after       = now.AddMinutes(10);
            string   nowString   = String.Empty;
            string   afterString = String.Empty;

            if (IdentityProvider.Contains("sielte"))
            {
                // SIELTE
                nowString   = now.AddMinutes(-2).ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'");
                afterString = after.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'");
            }
            else
            {
                // POSTE - TIM - INFOCERT
                nowString   = now.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'");
                afterString = after.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'");
            }
            MyRequest.IssueInstant = nowString;
            if (SecurityLevel > 1)
            {
                MyRequest.ForceAuthn          = true;
                MyRequest.ForceAuthnSpecified = true;
            }
            MyRequest.Destination = Destination;
            MyRequest.AssertionConsumerServiceIndex           = (ushort)Enviroment;
            MyRequest.AssertionConsumerServiceIndexSpecified  = true;
            MyRequest.AttributeConsumingServiceIndex          = 1;
            MyRequest.AttributeConsumingServiceIndexSpecified = true;

            NameIDType IssuerForRequest = new NameIDType
            {
                Value         = ConsumerServiceURL.Trim(),
                Format        = "urn:oasis:names:tc:SAML:2.0:nameid-format:entity",
                NameQualifier = ConsumerServiceURL
            };

            MyRequest.Issuer = IssuerForRequest;

            NameIDPolicyType NameIdPolicyForRequest = new NameIDPolicyType
            {
                Format               = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient",
                AllowCreate          = true,
                AllowCreateSpecified = true
            };

            MyRequest.NameIDPolicy = NameIdPolicyForRequest;

            ConditionsType Conditional = new ConditionsType();

            if (IdentityProvider.Contains("sielte"))
            {
                // SIELTE
                Conditional.NotBefore = nowString;
            }
            else
            {
                // POSTE - TIM - INFOCERT
                Conditional.NotBefore = now.AddMinutes(-2).ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'");
            }

            Conditional.NotBeforeSpecified    = true;
            Conditional.NotOnOrAfter          = afterString;
            Conditional.NotOnOrAfterSpecified = true;
            MyRequest.Conditions = Conditional;

            RequestedAuthnContextType RequestedAuthn = new RequestedAuthnContextType
            {
                Comparison          = AuthnContextComparisonType.minimum,
                ComparisonSpecified = true,
                ItemsElementName    = new ItemsChoiceType7[] { ItemsChoiceType7.AuthnContextClassRef },
                Items = new string[] { "https://www.spid.gov.it/SpidL" + SecurityLevel.ToString() }
            };

            MyRequest.RequestedAuthnContext = RequestedAuthn;

            XmlSerializerNamespaces ns = new XmlSerializerNamespaces();

            ns.Add("saml2p", "urn:oasis:names:tc:SAML:2.0:protocol");
            //ns.Add("saml2", "urn:oasis:names:tc:SAML:2.0:assertion");

            XmlSerializer responseSerializer = new XmlSerializer(MyRequest.GetType());

            StringWriter      stringWriter = new StringWriter();
            XmlWriterSettings settings     = new XmlWriterSettings
            {
                OmitXmlDeclaration = true,
                Indent             = true,
                Encoding           = Encoding.UTF8
            };

            XmlWriter responseWriter = XmlTextWriter.Create(stringWriter, settings);

            responseSerializer.Serialize(responseWriter, MyRequest, ns);
            responseWriter.Close();

            string samlString = string.Empty;

            samlString = stringWriter.ToString();

            stringWriter.Close();

            XmlDocument doc = new XmlDocument();

            doc.LoadXml(samlString);
            X509Certificate2 cert = null;

            if (System.IO.File.Exists(certFile))
            {
                cert = new X509Certificate2(certFile, certPassword);
            }
            else
            {
                X509Store store = new X509Store(storeName, storeLocation);
                store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
                X509Certificate2Collection CertCol = store.Certificates;

                X509Certificate2Collection coll = store.Certificates.Find(findType, findValue.ToString(), false);

                if (coll.Count < 1)
                {
                    throw new ArgumentException("Unable to locate certificate");
                }
                cert = coll[0];
                store.Close();
            }

            XmlElement signature = SigningHelper.SignDoc(doc, cert, UUID);

            doc.DocumentElement.InsertBefore(signature, doc.DocumentElement.ChildNodes[1]);

            string responseStr = doc.OuterXml;

            //byte[] base64EncodedBytes =
            //    Encoding.UTF8.GetBytes(responseStr);

            //string returnValue = System.Convert.ToBase64String(
            //    base64EncodedBytes);

            return("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + responseStr);
        }
Пример #10
0
        /// <summary>
        /// Creates a Version 1.1 Saml Assertion
        /// </summary>
        /// <param name="issuer">Issuer</param>
        /// <param name="subject">Subject</param>
        /// <param name="attributes">Attributes</param>
        /// <returns>returns a Version 1.1 Saml Assertoion</returns>
        private static AssertionType CreateSaml11Assertion(string issuer, string domain, string subject, Dictionary <string, string> attributes)
        {
            // Create some SAML assertion with ID and Issuer name.
            AssertionType assertion = new AssertionType();

            assertion.AssertionID  = "_" + Guid.NewGuid().ToString();
            assertion.Issuer       = issuer.Trim();
            assertion.MajorVersion = "1";
            assertion.MinorVersion = "1";
            assertion.IssueInstant = System.DateTime.UtcNow;

            //Not before, not after conditions
            ConditionsType conditions = new ConditionsType();

            conditions.NotBefore             = DateTime.UtcNow;
            conditions.NotBeforeSpecified    = true;
            conditions.NotOnOrAfter          = DateTime.UtcNow.AddMinutes(10);
            conditions.NotOnOrAfterSpecified = true;
            //Name Identifier to be used in Saml Subject
            NameIdentifierType nameIdentifier = new NameIdentifierType();

            nameIdentifier.NameQualifier = domain.Trim();
            nameIdentifier.Value         = subject.Trim();

            SubjectConfirmationType subjectConfirmation = new SubjectConfirmationType();

            subjectConfirmation.ConfirmationMethod = new string[] { "urn:oasis:names:tc:SAML:1.0:cm:bearer" };
            //
            // Create some SAML subject.
            SubjectType samlSubject = new SubjectType();

            AttributeStatementType      attrStatement = new AttributeStatementType();
            AuthenticationStatementType authStatement = new AuthenticationStatementType();

            authStatement.AuthenticationMethod  = "urn:oasis:names:tc:SAML:1.0:am:password";
            authStatement.AuthenticationInstant = System.DateTime.UtcNow;

            samlSubject.Items = new object[] { nameIdentifier, subjectConfirmation };

            attrStatement.Subject = samlSubject;
            authStatement.Subject = samlSubject;

            IPHostEntry ipEntry =
                Dns.GetHostEntry(System.Environment.MachineName);

            SubjectLocalityType subjectLocality = new SubjectLocalityType();

            subjectLocality.IPAddress = ipEntry.AddressList[0].ToString();

            authStatement.SubjectLocality = subjectLocality;

            attrStatement.Attribute = new AttributeType[attributes.Count];
            int i = 0;

            // Create userName SAML attributes.
            foreach (KeyValuePair <string, string> attribute in attributes)
            {
                AttributeType attr = new AttributeType();
                attr.AttributeName         = attribute.Key;
                attr.AttributeNamespace    = domain;
                attr.AttributeValue        = new object[] { attribute.Value };
                attrStatement.Attribute[i] = attr;
                i++;
            }
            assertion.Conditions = conditions;

            assertion.Items = new StatementAbstractType[] { authStatement, attrStatement };

            return(assertion);
        }
        private static void InterpretResponse(ResponseType response, EAuthResponseModel model)
        {
            model.RequestId = response.InResponseTo;

            // Пример за грешка:
            // <samlp:Status>
            //   <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Responder"><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:AuthnFailed" /></samlp:StatusCode>
            //   <samlp:StatusMessage>NOT_DETECTED_QES ***ИЛИ*** Некоректни данни</samlp:StatusMessage>
            // </samlp:Status>
            // Пример за успех:
            // <samlp:Status>
            //   <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
            //   <samlp:StatusMessage>Успешен отговор на заявката</samlp:StatusMessage>
            // </samlp:Status>
            StatusType status = response.Status;

            if (status != null)
            {
                bool isSuccessful = status.StatusCode?.Value.EndsWith("Success") ?? false;

                string statusMessage = status.StatusMessage;
                // Ако в заявката към еАвт не е подаден сертификат, системата вместо съобщение за грешка връща код NOT_DETECTED_QES
                // ИЛИ съобщение "STS Exception: STSToken exception: bg.egov.mtits.eauthn.delegate.exceptions.STSDelegateException : null".
                if (statusMessage == "NOT_DETECTED_QES" || statusMessage != null && statusMessage.Contains("STSDelegateException"))
                {
                    model.NotDetectedQes = true;
                    model.Errors.Add(ClientCertNotSelected);
                }
                else if (!isSuccessful)  // Съобщението за успех не се пази.
                {
                    if (!string.IsNullOrEmpty(statusMessage))
                    {
                        model.Errors.Add(statusMessage);
                    }

                    XmlElement[] details = status.StatusDetail?.Any;
                    if (details != null)
                    {
                        model.Errors.AddRange(details.Select(e => e.OuterXml));
                    }
                }
            }

            if (response.Items?[0] is AssertionType assertion)
            {
                ConditionsType conditions = assertion.Conditions;
                if (conditions != null && conditions.NotOnOrAfterSpecified)
                {
                    model.ExpirationDateTime = conditions.NotOnOrAfter;
                }

                // Пример за ЕГН:
                // <saml2:Subject>
                //   <saml2:NameID Format="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" NameQualifier="urn:egov:bg:eauth:1.0:attributes:eIdentifier:EGN">8012311234</saml2:NameID>
                //   <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:sender-vouches"><saml2:SubjectConfirmationData /></saml2:SubjectConfirmation>
                // </saml2:Subject>
                NameIDType nameId = assertion.Subject?.Items?.OfType <NameIDType>().FirstOrDefault();
                if (nameId != null)
                {
                    model.PidTypeCode      = nameId.NameQualifier?.Split(':').Last(); // Към 2018-02 е известен само вид "EGN".
                    model.PersonIdentifier = nameId.Value;
                }

                // Пример за име и контакти:
                // <saml2:AttributeStatement>
                //   <saml2:Attribute Name="urn:egov:bg:eauth:1.0:attributes:personNamesLatin" NameFormat="urn:egov:bg:eauth:1.0:attributes:personNamesLatin">
                //     <saml2:AttributeValue xsi:type="xs:string">Ivan Dilyanov Dilov</saml2:AttributeValue>
                //   </saml2:Attribute>
                //   <saml2:Attribute Name="urn:egov:bg:eauth:1.0:attributes:eMail" NameFormat="urn:egov:bg:eauth:1.0:attributes:eMail">
                //     <saml2:AttributeValue xsi:type="xs:string">[email protected]</saml2:AttributeValue>
                //   </saml2:Attribute>
                //   <saml2:Attribute Name="urn:egov:bg:eauth:1.0:attributes:phone" NameFormat="urn:egov:bg:eauth:1.0:attributes:phone">
                //     <saml2:AttributeValue xsi:type="xs:string">+359 888476663</saml2:AttributeValue>
                //   </saml2:Attribute>
                // </saml2:AttributeStatement>
                if (assertion.Items != null)
                {
                    foreach (AttributeStatementType attributes in assertion.Items.OfType <AttributeStatementType>())
                    {
                        if (attributes.Items != null)
                        {
                            foreach (AttributeType attribute in attributes.Items.OfType <AttributeType>())
                            {
                                string type  = attribute.Name?.Split(':').Last().ToLower();
                                string value = attribute.AttributeValue != null?string.Join(Environment.NewLine, attribute.AttributeValue.Where(v => v != null)) : null;

                                if (type == "personnameslatin")
                                {
                                    model.PersonNamesLatin = value;
                                }
                                else if (type == "email")
                                {
                                    model.Email = value;
                                }
                                else if (type == "phone")
                                {
                                    model.Phone = value;
                                }
                            }
                        }
                    }
                }
            }
        }
 internal ConditionsBuilder(ConditionsType conditions)
 {
     _conditions = conditions;
 }