/// <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); } }
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}"); } } } }
/// <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 }
/// <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); }
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 })); }
/// <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); }
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); }
/// <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); }
/// <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); }
/// <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; }