private static IEnumerable<Claim> ClaimsFromSubject(NameId subject, string issuer) { if (subject == null) yield break; if (subject.Value != null) { yield return new Claim("sub", subject.Value, ClaimValueTypes.String, issuer); // openid connect yield return new Claim(ClaimTypes.NameIdentifier, subject.Value, ClaimValueTypes.String, issuer); // saml } }
public void ThrowsExceptionWhenEmailInvalidForm() { // Arrange var nameId = new NameId { Format = Saml20Constants.NameIdentifierFormats.Email }; var validator = new Saml20NameIdValidator(); var invalidEmails = new[] { "thisisnotavalid.email@ ", "thisisnotavalidemail", "thisisnotavalidemail.com", "@thisisnotavalidemail.com", " @thisisnotavalidemail.com", "@ @thisisnotavalidemail.com", " @ @thisisnotavalidemail.com", " . @thisisnotavalidemail.com", @"\. @thisisnotavalidemail.com", @"\.\@thisisnotavalidemail.com", @"a.\@thisisnotavalidemail.com", @"<.>@thisisnotavalidemail.com", @"<*****@*****.**", "thisisnotavalid.email@", "thisisnotavalid.email@ @", "thisisnotavalid.email@ @ " }; foreach (var email in invalidEmails) { nameId.Value = email; try { // Act validator.ValidateNameId(nameId); // Assert Assert.Fail("Email address " + email + " is not supposed to be valid"); } catch (Saml20FormatException sfe) { Assert.AreEqual(sfe.Message, "Value of NameID is not a valid email address according to the IETF RFC 2822 specification"); } } }
public void ValidatesTransient() { var nameId = new NameId { Format = Saml20Constants.NameIdentifierFormats.Transient }; var validator = new Saml20NameIdValidator(); nameId.Value = new string('f', 256); validator.ValidateNameId(nameId); nameId.Value = new string('f', 16); validator.ValidateNameId(nameId); }
public void ValidatesPersistent() { var nameId = new NameId { Format = Saml20Constants.NameIdentifierFormats.Persistent, Value = new string('f', 256) }; var validator = new Saml20NameIdValidator(); validator.ValidateNameId(nameId); }
public void ValidatesKerberos() { // Arrange var nameId = new NameId { Format = Saml20Constants.NameIdentifierFormats.Kerberos, Value = "a@b" }; var validator = new Saml20NameIdValidator(); // Act validator.ValidateNameId(nameId); }
public void ValidatesEntity() { // Arrange var nameId = new NameId { Format = Saml20Constants.NameIdentifierFormats.Entity, Value = new string('f', 1024) }; var validator = new Saml20NameIdValidator(); // Act validator.ValidateNameId(nameId); }
public void ValidatesEmail() { // Arrange var nameId = new NameId { Format = Saml20Constants.NameIdentifierFormats.Email, Value = "*****@*****.**" }; var validator = new Saml20NameIdValidator(); // Act validator.ValidateNameId(nameId); }
public void ThrowsExceptionWhenX509SubjecNameValueEmpty() { // Arrange var nameId = new NameId { Format = Saml20Constants.NameIdentifierFormats.X509SubjectName, Value = string.Empty }; var validator = new Saml20NameIdValidator(); // Act validator.ValidateNameId(nameId); }
/// <summary> /// Performs the attribute query against the specified IdP endpoint and adds the resulting attributes to <c>Saml20Identity.Current</c>. /// </summary> /// <param name="context">The http context.</param> /// <param name="endPoint">The IdP to perform the query against.</param> /// <param name="nameIdFormat">The name id format.</param> public void PerformQuery(HttpContext context, IdentityProviderElement endPoint, string nameIdFormat) { Logger.DebugFormat("{0}.{1} called", GetType(), "PerformQuery()"); var builder = new HttpSoapBindingBuilder(context); var name = new NameId { Value = Saml20Identity.Current.Name, Format = nameIdFormat }; _attrQuery.Subject.Items = new object[] { name }; _attrQuery.SamlAttribute = _attributes.ToArray(); var query = new XmlDocument(); query.LoadXml(Serialization.SerializeToXmlString(_attrQuery)); XmlSignatureUtils.SignDocument(query, Id); if (query.FirstChild is XmlDeclaration) { query.RemoveChild(query.FirstChild); } Logger.DebugFormat(TraceMessages.AttrQuerySent, endPoint.Metadata.GetAttributeQueryEndpointLocation(), query.OuterXml); Stream s; try { s = builder.GetResponse(endPoint.Metadata.GetAttributeQueryEndpointLocation(), query.OuterXml, endPoint.AttributeQuery); } catch (Exception e) { Logger.Error(e.Message, e); throw; } var parser = new HttpSoapBindingParser(s); var status = parser.GetStatus(); if (status.StatusCode.Value != Saml20Constants.StatusCodes.Success) { Logger.ErrorFormat(ErrorMessages.AttrQueryStatusNotSuccessful, Serialization.SerializeToXmlString(status)); throw new Saml20Exception(status.StatusMessage); } bool isEncrypted; var xmlAssertion = Saml20SignonHandler.GetAssertion(parser.SamlMessage, out isEncrypted); if (isEncrypted) { var ass = new Saml20EncryptedAssertion((RSA)Saml2Config.GetConfig().ServiceProvider.SigningCertificate.GetCertificate().PrivateKey); ass.LoadXml(xmlAssertion); ass.Decrypt(); xmlAssertion = ass.Assertion.DocumentElement; } var assertion = new Saml20Assertion(xmlAssertion, null, Saml2Config.GetConfig().AssertionProfile.AssertionValidator, endPoint.QuirksMode); Logger.DebugFormat(TraceMessages.AttrQueryAssertionReceived, xmlAssertion == null ? string.Empty : xmlAssertion.OuterXml); if (!assertion.CheckSignature(Saml20SignonHandler.GetTrustedSigners(endPoint.Metadata.Keys, endPoint))) { Logger.Error(ErrorMessages.AssertionSignatureInvalid); throw new Saml20Exception(ErrorMessages.AssertionSignatureInvalid); } foreach (var attr in assertion.Attributes) { Saml20Identity.Current.AddAttributeFromQuery(attr.Name, attr); } }
public void ThrowsExceptionWhenPersistentLengthTooLong() { // Arrange var nameId = new NameId { Format = Saml20Constants.NameIdentifierFormats.Persistent, Value = new string('f', 257) }; var validator = new Saml20NameIdValidator(); // Act validator.ValidateNameId(nameId); }
public void ThrowsExceptionWhenKerberosLessThanThreecharacters() { // Arrange var nameId = new NameId { Format = Saml20Constants.NameIdentifierFormats.Kerberos, Value = @"b" }; var validator = new Saml20NameIdValidator(); // Act validator.ValidateNameId(nameId); }
public void ThrowsExceptionWhenKerberosInvalidFormat() { // Arrange var nameId = new NameId { Format = Saml20Constants.NameIdentifierFormats.Kerberos, Value = @"a\b" }; var validator = new Saml20NameIdValidator(); // Act validator.ValidateNameId(nameId); }
public void ThrowsExceptionWhenEntitySPProvidedId() { // Arrange var nameId = new NameId { Format = Saml20Constants.NameIdentifierFormats.Entity, Value = new string('f', 1024), SPProvidedID = "ksljdf" }; var validator = new Saml20NameIdValidator(); // Act validator.ValidateNameId(nameId); }
/// <summary> /// Validates the name ID. /// </summary> /// <param name="nameId">The name ID.</param> public void ValidateNameId(NameId nameId) { if (nameId == null) { throw new ArgumentNullException("nameId"); } if (string.IsNullOrEmpty(nameId.Format)) { return; } if (!Uri.IsWellFormedUriString(nameId.Format, UriKind.Absolute)) { throw new Saml20FormatException("NameID element has Format attribute which is not a wellformed absolute uri."); } // The processing rules from [SAML2.0 standard] section 8.3 are implemented here if (nameId.Format == Saml20Constants.NameIdentifierFormats.Email) { if (!Saml20Utils.ValidateRequiredString(nameId.Value)) { throw new Saml20FormatException("NameID with Email Format attribute MUST contain a Value that contains more than whitespace characters"); } try { new MailAddress(nameId.Value); } catch (FormatException fe) { throw new Saml20FormatException("Value of NameID is not a valid email address according to the IETF RFC 2822 specification", fe); } catch (IndexOutOfRangeException ie) { throw new Saml20FormatException("Value of NameID is not a valid email address according to the IETF RFC 2822 specification", ie); } } else if (nameId.Format == Saml20Constants.NameIdentifierFormats.X509SubjectName) { if (!Saml20Utils.ValidateRequiredString(nameId.Value)) { throw new Saml20FormatException("NameID with X509SubjectName Format attribute MUST contain a Value that contains more than whitespace characters"); } // TODO: Consider checking for correct encoding of the Value according to the // XML Signature Recommendation (http://www.w3.org/TR/xmldsig-core/) section 4.4.4 } else if (nameId.Format == Saml20Constants.NameIdentifierFormats.Windows) { // Required format is 'DomainName\UserName' but the domain name and the '\' are optional if (!Saml20Utils.ValidateRequiredString(nameId.Value)) { throw new Saml20FormatException("NameID with Windows Format attribute MUST contain a Value that contains more than whitespace characters"); } } else if (nameId.Format == Saml20Constants.NameIdentifierFormats.Kerberos) { // Required format is 'name[/instance]@REALM' if (!Saml20Utils.ValidateRequiredString(nameId.Value)) { throw new Saml20FormatException("NameID with Kerberos Format attribute MUST contain a Value that contains more than whitespace characters"); } if (nameId.Value.Length < 3) { throw new Saml20FormatException("NameID with Kerberos Format attribute MUST contain a Value with at least 3 characters"); } if (nameId.Value.IndexOf("@") < 0) { throw new Saml20FormatException("NameID with Kerberos Format attribute MUST contain a Value that contains a '@'"); } // TODO: Consider implementing the rules for 'name', 'instance' and 'REALM' found in IETF RFC 1510 (http://www.ietf.org/rfc/rfc1510.txt) here } else if (nameId.Format == Saml20Constants.NameIdentifierFormats.Entity) { if (!Saml20Utils.ValidateRequiredString(nameId.Value)) { throw new Saml20FormatException("NameID with Entity Format attribute MUST contain a Value that contains more than whitespace characters"); } if (nameId.Value.Length > 1024) { throw new Saml20FormatException("NameID with Entity Format attribute MUST have a Value that contains no more than 1024 characters"); } if (nameId.NameQualifier != null) { throw new Saml20FormatException("NameID with Entity Format attribute MUST NOT set the NameQualifier attribute"); } if (nameId.SPNameQualifier != null) { throw new Saml20FormatException("NameID with Entity Format attribute MUST NOT set the SPNameQualifier attribute"); } if (nameId.SPProvidedID != null) { throw new Saml20FormatException("NameID with Entity Format attribute MUST NOT set the SPProvidedID attribute"); } } else if (nameId.Format == Saml20Constants.NameIdentifierFormats.Persistent) { if (!Saml20Utils.ValidateRequiredString(nameId.Value)) { throw new Saml20FormatException("NameID with Persistent Format attribute MUST contain a Value that contains more than whitespace characters"); } if (nameId.Value.Length > 256) { throw new Saml20FormatException("NameID with Persistent Format attribute MUST have a Value that contains no more than 256 characters"); } } else if (nameId.Format == Saml20Constants.NameIdentifierFormats.Transient) { if (!Saml20Utils.ValidateRequiredString(nameId.Value)) { throw new Saml20FormatException("NameID with Transient Format attribute MUST contain a Value that contains more than whitespace characters"); } if (nameId.Value.Length > 256) { throw new Saml20FormatException("NameID with Transient Format attribute MUST have a Value that contains no more than 256 characters"); } if (!Saml20Utils.ValidateIdString(nameId.Value)) { throw new Saml20FormatException("NameID with Transient Format attribute MUST have a Value with at least 16 characters (the equivalent of 128 bits)"); } } }
public void ValidatesWindowsDomainQualifiedName() { // Arrange var nameId = new NameId { Format = Saml20Constants.NameIdentifierFormats.Windows }; var validator = new Saml20NameIdValidator(); // Act nameId.Value = "a"; validator.ValidateNameId(nameId); nameId.Value = "b\a"; validator.ValidateNameId(nameId); }
public void ThrowsExceptionWhenEmailValueContainsOnlyWhitespace() { // Arrange var nameId = new NameId { Format = Saml20Constants.NameIdentifierFormats.Email, Value = " " }; var validator = new Saml20NameIdValidator(); // Act validator.ValidateNameId(nameId); }
public void ThrowsExceptionWhenTransientValueTooShort() { // Arrange var nameId = new NameId { Format = Saml20Constants.NameIdentifierFormats.Transient, Value = new string('f', 15) }; var validator = new Saml20NameIdValidator(); // Act validator.ValidateNameId(nameId); }