private static void VerifyAssertion(XmlElement xmlElement) { Console.Error.WriteLine("Verifying SAML assertion"); if (SAMLAssertionSignature.IsSigned(xmlElement)) { bool verified = SAMLAssertionSignature.Verify(xmlElement, x509Certificate); Console.Error.WriteLine("Verified: " + verified); } else { Console.Error.WriteLine("The SAML assertion isn't signed"); } }
static void Main(string[] args) { try { #if DOTNET45 // Register the SHA-256 cryptographic algorithm. // Only supported in .NET 4.5 and above. CryptoConfig.AddAlgorithm(typeof(RSAPKCS1SHA256SignatureDescription), "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"); #endif // Load the certificate and private key for signature generation. X509Certificate2 x509Certificate = new X509Certificate2("idp.pfx", "password"); // Create a basic SAML assertion and serialize it to XML. SAMLAssertion samlAssertion = new SAMLAssertion(); samlAssertion.Issuer = new Issuer("test"); XmlElement samlAssertionElement = samlAssertion.ToXml(); // Sign the SAML assertion using SHA-256 for the digest and signature algorithms. SAMLAssertionSignature.Generate(samlAssertionElement, x509Certificate.PrivateKey, x509Certificate, null, "http://www.w3.org/2001/04/xmlenc#sha256", "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"); Console.WriteLine("Signed SAML assertion: {0}", samlAssertionElement.OuterXml); // Verify the signature. bool verified = SAMLAssertionSignature.Verify(samlAssertionElement); Console.WriteLine("Signature verified: {0}", verified); // The HTTP-redirect doesn't use XML signatures so check it separately. // Create a basic authn request and serialize it to XML. AuthnRequest authnRequest = new AuthnRequest(); authnRequest.Issuer = new Issuer("test"); XmlElement authnRequestElement = authnRequest.ToXml(); // Create the HTTP-redirect URL included the SHA-256 signature. string url = HTTPRedirectBinding.CreateRequestRedirectURL("http://www.test.com", authnRequestElement, null, x509Certificate.PrivateKey, HTTPRedirectBinding.SignatureAlgorithms.RSA_SHA256); string relayState = null; bool signed = false; // Retrieve the authn request from the HTTP-redirect URL and verify the signature. HTTPRedirectBinding.GetRequestFromRedirectURL(url, out authnRequestElement, out relayState, out signed, x509Certificate.PublicKey.Key); } catch (Exception exception) { // If signature generation/verification fails then most likely the .NET CLR security update // hasn't been installed and configured correctly or the inbuilt .NET SHA-256 support hasn't been initialized. Console.WriteLine(exception.ToString()); } }
private static void SignAndVerify(X509Certificate2 x509Certificate, string digestMethod, string signatureMethod) { try { Console.WriteLine("Testing signature generation and verification using \"{0}\".", signatureMethod); // Create a basic SAML assertion and serialize it to XML. SAMLAssertion samlAssertion = new SAMLAssertion(); samlAssertion.Issuer = new Issuer("test"); XmlElement samlAssertionElement = samlAssertion.ToXml(); // Sign the SAML assertion using the specified digest and signature methods. SAMLAssertionSignature.Generate(samlAssertionElement, x509Certificate.PrivateKey, x509Certificate, null, digestMethod, signatureMethod); // Verify the signature. bool verified = SAMLAssertionSignature.Verify(samlAssertionElement); if (!verified) { throw new Exception("The XML signature failed to verify."); } // The HTTP-redirect doesn't use XML signatures so check it separately. // Create a basic authn request and serialize it to XML. AuthnRequest authnRequest = new AuthnRequest(); authnRequest.Issuer = new Issuer("test"); XmlElement authnRequestElement = authnRequest.ToXml(); // Create the HTTP-redirect URL included the signature. string url = HTTPRedirectBinding.CreateRequestRedirectURL("http://www.test.com", authnRequestElement, null, x509Certificate.PrivateKey, signatureMethod); string relayState = null; bool signed = false; // Retrieve the authn request from the HTTP-redirect URL and verify the signature. HTTPRedirectBinding.GetRequestFromRedirectURL(url, out authnRequestElement, out relayState, out signed, x509Certificate.PublicKey.Key); Console.WriteLine("Signature generation and verification using \"{0}\" was successful.", signatureMethod); } catch (Exception exception) { Console.WriteLine("Signature generation and verification using \"{0}\" failed.", signatureMethod); Console.WriteLine(exception.ToString()); } }
// Process a successful SAML response. private void ProcessSuccessSAMLResponse(SAMLResponse samlResponse, string relayState) { Trace.Write("SP", "Processing successful SAML response"); // Extract the asserted identity from the SAML response. // The SAML assertion may be signed or encrypted and signed. SAMLAssertion samlAssertion = null; if (samlResponse.GetUnsignedAssertions().Count > 0) { samlAssertion = samlResponse.GetUnsignedAssertions()[0]; } else if (samlResponse.GetSignedAssertions().Count > 0) { Trace.Write("SP", "Verifying assertion signature"); XmlElement samlAssertionXml = samlResponse.GetSignedAssertions()[0]; // Verify the assertion signature. The embedded signing certificate is used. if (!SAMLAssertionSignature.Verify(samlAssertionXml)) { throw new ArgumentException("The SAML assertion signature failed to verify."); } samlAssertion = new SAMLAssertion(samlAssertionXml); } else if (samlResponse.GetEncryptedAssertions().Count > 0) { Trace.Write("SP", "Decrypting assertion"); // Load the decryption key. X509Certificate2 x509Certificate = (X509Certificate2)Application[Global.SPX509Certificate]; // Decrypt the encrypted assertion. XmlElement samlAssertionXml = samlResponse.GetEncryptedAssertions()[0].DecryptToXml(x509Certificate.PrivateKey, null, null); if (SAMLAssertionSignature.IsSigned(samlAssertionXml)) { Trace.Write("SP", "Verifying assertion signature"); // Verify the assertion signature. The embedded signing certificate is used. if (!SAMLAssertionSignature.Verify(samlAssertionXml)) { throw new ArgumentException("The SAML assertion signature failed to verify."); } } samlAssertion = new SAMLAssertion(samlAssertionXml); } else { throw new ArgumentException("No assertions in response"); } // Get the subject name identifier. string userName = null; if (samlAssertion.Subject.NameID != null) { userName = samlAssertion.Subject.NameID.NameIdentifier; } if (string.IsNullOrEmpty(userName)) { throw new ArgumentException("The SAML assertion doesn't contain a subject name."); } // Create a login context for the asserted identity. Trace.Write("SP", "Automatically logging in user " + userName); FormsAuthentication.SetAuthCookie(userName, false); // Get the originally requested resource URL from the relay state, if any. string redirectURL = "~/"; RelayState cachedRelayState = RelayStateCache.Remove(relayState); if (cachedRelayState != null) { redirectURL = cachedRelayState.ResourceURL; } // Redirect to the originally requested resource URL, if any, or the default page. Trace.Write("SP", "Redirecting to " + redirectURL); Response.Redirect(redirectURL, false); Trace.Write("SP", "Processed successful SAML response"); }
public ActionResult UploadSaml(FormCollection formCollection) { var attributes = new List <SAMLAttribute>(); var errorMessages = new List <string>(); var xmlDoc = null as XmlDocument; SessionHelper.Set(SamlAttributesSessionKey, null); SessionHelper.Set(SamlErrorMessagesSessionKey, null); if (Request != null) { var file = Request.Files["SamlFile"]; if ((file != null) && (file.ContentLength > 0) && !string.IsNullOrEmpty(file.FileName)) { try { xmlDoc = new XmlDocument(); xmlDoc.Load(file.InputStream); var samlValidator = new SAMLValidator(); var isValid = samlValidator.Validate(xmlDoc); if (!isValid) { errorMessages.AddRange(samlValidator.Warnings.Select(warning => string.Format("Warning:, {0}", warning.Message))); errorMessages.AddRange(samlValidator.Errors.Select(error => error.Message)); } if (SAMLMessageSignature.IsSigned(xmlDoc.DocumentElement)) { if (!SAMLMessageSignature.Verify(xmlDoc.DocumentElement)) { errorMessages.Add(string.Format("Failed to verify SAML response signature. [{0}]", xmlDoc.OuterXml)); } } var samlResponse = new SAMLResponse(xmlDoc.DocumentElement); var assertions = samlResponse.GetAssertions(); var encryptedAssertions = samlResponse.GetEncryptedAssertions(); var signedAssertions = samlResponse.GetSignedAssertions(); var x509CertificateFilePath = Path.Combine(HttpRuntime.AppDomainAppPath, SAMLConfiguration.Current.ServiceProviderConfiguration.CertificateFile); var x509Certificate = new X509Certificate2(x509CertificateFilePath, SAMLConfiguration.Current.ServiceProviderConfiguration.CertificatePassword); encryptedAssertions.ForEach(a => { var decryptedAssertion = a.DecryptToXml(x509Certificate); assertions.Add(new SAMLAssertion(decryptedAssertion)); }); signedAssertions.ForEach(a => { if (SAMLAssertionSignature.IsSigned(a)) { if (!SAMLAssertionSignature.Verify(a)) { errorMessages.Add(string.Format("Failed to verify SAML assertion signature. [{0}]", a.OuterXml)); } } assertions.Add(new SAMLAssertion(a)); }); assertions.ForEach(a => { var nameId = a.GetNameID(); if (!string.IsNullOrEmpty(nameId)) { attributes.Add("NameId", nameId); } a.GetAttributeStatements().ForEach( s => attributes.AddRange(from object attribute in s.Attributes select attribute as SAMLAttribute)); }); } catch (Exception ex) { var saml = xmlDoc != null ? xmlDoc.OuterXml : string.Empty; _logger.Log(ex); errorMessages.Add(string.Format("{0} [{1}]", ex.Message, saml)); } } } SessionHelper.Set(SamlAttributesSessionKey, attributes.ToArray()); SessionHelper.Set(SamlErrorMessagesSessionKey, errorMessages); return(Redirect(TestTargetUrl)); }