public static void VerifyDetachedSignature() { string tenant = "azureadb2ctests"; string policy = "B2C_1A_SAMLAPP_demopolicy_signup_signin"; string destination = string.Format("https://{0}.b2clogin.com/{0}.onmicrosoft.com/{1}/samlp/sso/login", tenant, policy); string relayStateInput = "1234"; string signatureAlogrithm = "SHA1"; // following can be thumbpritn or subject string certSubject = "CN=samlsp.cpim.localhost.net, OU=AAD, C=US"; string certIdentifier = "84BDDFCC2BC9BB3B3E3AC594EBED3FDB1A49BD75"; certIdentifier = certSubject; string samlPayLoad = "<samlp:AuthnRequest AssertionConsumerServiceURL=\"https://samltestapp2.azurewebsites.net/SP/AssertionConsumer\" Destination=\"https://login.microsoftonline.com/te/azureadb2ctests.onmicrosoft.com/B2C_1A_SAMLAPP_demopolicy_signup_signin/samlp/sso/login\" ForceAuthn=\"false\" ID=\"_1314190418\" IsPassive=\"false\" IssueInstant=\"{0}\" ProtocolBinding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST\" Version=\"2.0\" xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\"> <saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">https://samltestapp2.azurewebsites.net</saml:Issuer><samlp:NameIDPolicy AllowCreate=\"true\" Format=\"urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress\" SPNameQualifier=\"https://samltestapp2.azurewebsites.net\" xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\"/></samlp:AuthnRequest>"; DateTime issueInstant = DateTime.UtcNow; samlPayLoad = string.Format(samlPayLoad, issueInstant.ToString("yyyy-MM-ddTHH:mm:ssZ")); UrlBuilder signedRedirectUrl = SignMessage.GetSamlSignedRedirectUrl(destination, samlPayLoad, relayStateInput, signatureAlogrithm, certIdentifier); if (VerifyRedirectSignature.IsRedirectSignatureValid(signedRedirectUrl, certIdentifier)) { Console.WriteLine("VerifyDetachedSignature Signature is valid"); } else { Console.WriteLine("VerifyDetachedSignature Signature is invalid"); } }
internal static bool VerifyDetachedSignature( string detachedSignature, string detachedSignatureAlgorithm, string signedQueryString, string certIdentifier ) { if (string.IsNullOrWhiteSpace(detachedSignature)) { throw new ArgumentException("DetachedSignature not mentioned"); } // Check that we have a signature algorithm, if not throw error if (string.IsNullOrWhiteSpace(detachedSignatureAlgorithm)) { throw new ArgumentException("DetachedSignature not mentioned"); } X509Certificate2 samlEncryptionAndSigningKey = SignMessage.GetSamlEncryptionAndSigningKey(certIdentifier); X509Certificate2Collection publicKeys = new X509Certificate2Collection(); publicKeys.Add(samlEncryptionAndSigningKey); object hashAlgorithmProvider = GetAlgorithmProvider(detachedSignatureAlgorithm); try { // Now verify return(IsValidDetachedSignature( signedQueryString, hashAlgorithmProvider, detachedSignature, publicKeys)); } finally { IDisposable hashAlgorithmProviderDisp = hashAlgorithmProvider as IDisposable; if (hashAlgorithmProviderDisp != null) { hashAlgorithmProviderDisp.Dispose(); } } }
/// <summary> /// Gets SamlSigned RedirectUrl /// </summary> /// <param name="destination"></param> /// <param name="samlPayLoad"></param> /// <param name="relayStateInput"></param> /// <param name="signatureAlogrithm"></param> /// <param name="certSubject"></param> /// <returns></returns> public static UrlBuilder GetSamlSignedRedirectUrl ( string destination, string samlPayLoad, string relayStateInput, string signatureAlogrithm, string certSubject ) { UrlBuilder redirectUrl = new UrlBuilder() { Uri = new Uri(destination) }; // Add the request parameters to the URL builder redirectUrl.AddOrUpdateParameter("SAMLRequest", samlPayLoad.RedirectEncode()); if (!string.IsNullOrWhiteSpace(relayStateInput)) { redirectUrl.AddOrUpdateParameter("RelayState", relayStateInput.RedirectEncode()); } // Save signature algorithm SignMessage.SignatureAlgorithm sigAlgorithm = (SignMessage.SignatureAlgorithm)Enum.Parse(typeof(SignMessage.SignatureAlgorithm), signatureAlogrithm, true); AddSignatureToRequest(redirectUrl, sigAlgorithm); X509Certificate2 samlEncryptionAndSigningKey = SignMessage.GetSamlEncryptionAndSigningKey(certSubject); string signature = SignMessage.SignDetached(redirectUrl.GetQueryString(), samlEncryptionAndSigningKey, sigAlgorithm); redirectUrl.AddOrUpdateParameter("Signature", signature); string signedSamlRedirectMessage = redirectUrl.ToString(); return(redirectUrl); }