/// <summary> /// This method is used to build the SAML Assertion and send the HTTPWebRequest to get back the /// cookie sent by the ISI. This cookie is not stored (can be), and is passed back to send along /// with the follow up GET request to conduct a search or retrieve operation. /// </summary> /// <returns>Cookie Container used for the follow up GET request.</returns> public CookieContainer SendSamlRequest(X509Certificate2 cert, AttributeHolder attr) { SamlBuilder sb = new SamlBuilder(cert); String samlAssertion = sb.BuildSamlAssertion(attr); GetMiseCookieFromSamlAssertion(cert, samlAssertion); //This loads the _Cookies object return(_Cookies); }
public String BuildSamlAssertion(AttributeHolder attributes) { XmlDocument xmlDoc = new XmlDocument(); //required by World Wide Web Consortium (W3C) for digitial signatures xmlDoc.PreserveWhitespace = true; #region Build the SAML 2.0 Root Element XElement root = new XElement(saml2 + "Assertion", new XAttribute(XNamespace.Xmlns + "saml2", saml2.ToString()), new XAttribute(XNamespace.Xmlns + "xs", xs.ToString()), new XAttribute("ID", attributes.Id), new XAttribute("IssueInstant", attributes.IssueInstant), new XAttribute("Version", "2.0")); XElement issuer = new XElement(saml2 + "Issuer", new XAttribute("Format", "urn:oasis:names:tc:SAML:2.0:nameid-format:entity"), attributes.ElectronicEntityId); root.Add(issuer); xmlDoc.Load(root.CreateReader()); #endregion #region Build the Conditions Block /*.Net seems to process much quicker than JAVA, and so we set the NotBefore condition back by * 10 seconds so that when the request is sent we don't run into problems of not meeting our own * conditions on the ISI. This was a problem found during testing, and this seems to have resolved * the issue. */ TimeSpan ts = new TimeSpan(0, 0, 10); XElement conditions = new XElement(saml2 + "Conditions", new XAttribute("NotBefore", DateTime.Now.Subtract(ts).ToUniversalTime()), new XAttribute("NotOnOrAfter", DateTime.Now.AddMonths(12).ToUniversalTime())); XElement restrictions = new XElement(saml2 + "AudienceRestriction"); XElement audience = new XElement(saml2 + "Audience", "urn:mise:all"); restrictions.Add(new XElement(audience)); conditions.Add(new XElement(restrictions)); XmlNode conditionNode = xmlDoc.ReadNode(conditions.CreateReader()); xmlDoc.DocumentElement.AppendChild(conditionNode); #endregion #region Build the Attribute Statement Block XElement attributeHolder = new XElement(saml2 + "AttributeStatement"); attributeHolder.Add(this.AssertionBuilder("ElectronicIdentityId", "mise:1.2:user:ElectronicIdentityId", "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified", attributes.ElectronicEntityId)); attributeHolder.Add(this.AssertionBuilder("FullName", "mise:1.2:user:FullName", "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified", attributes.FullName)); attributeHolder.Add(this.AssertionBuilder("CitizenshipCode", "mise:1.2:user:CitizenshipCode", "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified", attributes.CitizenCodes)); attributeHolder.Add(this.AssertionBuilder("Scope", "mise:1.2:user:Scope", "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified", attributes.Scope)); attributeHolder.Add(this.AssertionBuilder("LawEnforcementIndicator", "mise:1.2:user:LawEnforcementIndicator", "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified", attributes.LEI.ToString())); attributeHolder.Add(this.AssertionBuilder("PrivacyProtectedIndicator", "mise:1.2:user:PrivacyProtectedIndicator", "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified", attributes.PPI.ToString())); attributeHolder.Add(this.AssertionBuilder("COIIndicator", "mise:1.2:user:COIIndicator", "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified", attributes.COI.ToString())); XmlNode attrNode = xmlDoc.ReadNode(attributeHolder.CreateReader()); xmlDoc.DocumentElement.AppendChild(attrNode); #endregion //need to sign after all other nodes have been created #region Build the Signature Block SignedXml signedXml = new SignedXml(xmlDoc); signedXml.SigningKey = _privateCert.PrivateKey; Reference reference = new Reference(); reference.Uri = ""; XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform(true); env.Algorithm = SignedXml.XmlDsigEnvelopedSignatureTransformUrl; reference.AddTransform(env); //With respect to the trustfabric the transform c14t with comments are required //for the interoperability between c# and java XmlDsigC14NWithCommentsTransform c14t = new XmlDsigC14NWithCommentsTransform(); c14t.Algorithm = SignedXml.XmlDsigC14NWithCommentsTransformUrl; reference.AddTransform(c14t); KeyInfo keyInfo = new KeyInfo(); KeyInfoX509Data keyInfoData = new KeyInfoX509Data(_privateCert); keyInfo.AddClause(keyInfoData); signedXml.KeyInfo = keyInfo; signedXml.AddReference(reference); signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl; signedXml.ComputeSignature(); XmlElement assignedSignature = signedXml.GetXml(); //insert the cert in the correct document location (not necassary will work if appendchild is used) xmlDoc.DocumentElement.InsertBefore(xmlDoc.ImportNode(assignedSignature, true), conditionNode); #endregion return(xmlDoc.OuterXml); }