public void AuthnRequestObjectTest()
        {
            string xmlString = ReadFile(xmlFilename);

            Saml2Serializer saml         = new Saml2Serializer();
            AuthnRequest    authnRequest = saml.ConvertXMLToAuthnRequestObject(xmlString);

            Assert.AreEqual("https://stiamhub:8443/Hub/SAML/SSO/Browser", authnRequest.Destination);
            Assert.AreEqual("http://localhost:14545/", authnRequest.AssertionConsumerServiceURL);
            Assert.AreEqual("hybridissuer.ch", authnRequest.Issuer);
            //Assert.AreEqual("urn:oasis:names:tc:SAML:2.0:nameid-format:persistent", authnRequest.NameIDPolicy.Format);
        }
        public void ValidateResponseWithoutTimeValidTest()
        {
            Saml2Serializer  serializer       = new Saml2Serializer();
            SamlValidator    validator        = new SamlValidator();
            string           xml              = Encoding.UTF8.GetString(Convert.FromBase64String(ReadFile(responseFilename)));
            EntityDescriptor entityDescriptor = serializer.ConvertXMLToEntityDescriptorObject(ReadFile(xmlMetadataFile));
            AuthnRequest     authnRequest     = serializer.ConvertXMLToAuthnRequestObject(ReadFile(xmlAuthnRequestFile));

            Response response = serializer.ConvertXMLToResponseObject(xml);

            bool isValid = validator.ValidateResponse(response, xml, entityDescriptor, authnRequest, false);

            Assert.IsTrue(isValid);
        }
        /// <summary>
        /// Reads the given saml response and extracts the attributes
        /// </summary>
        /// <param name="samlResponse">saml response with or without encrypted assertion</param>
        /// <param name="relaystate">related state to saml response</param>
        /// <param name="responseAssertionAttributes">contains the extracted attributes from the assertion (if there were any)</param>
        /// <returns>true -> valid response -> else exception is thrown</returns>
        public bool ReadResponse(string samlResponse, string relaystate, out Dictionary <string, ResponseAssertionAttribute> responseAssertionAttributes)
        {
            if (!initialized)
            {
                throw new SamlCommunicationException("Init must be called first", SamlCommunicationType.SAMLCOMMUNICATION);
            }

            LogService.Log(LogService.LogType.Info, "ReadResponse called");
            responseAssertionAttributes = new Dictionary <string, ResponseAssertionAttribute>();

            try
            {
                LogService.Log(LogService.LogType.Info, "ReadResponse response: '" + samlResponse + "'; relatedstate: '" + relaystate + "'");
                // decode SAMLResponse first (base64)
                string responseXML = Encoding.UTF8.GetString(Convert.FromBase64String(samlResponse));

                // get response as object
                Response response = serializer.ConvertXMLToResponseObject(responseXML);

                // remove encrypted assertion if there is one
                if (response.EncryptedAssertion != null)
                {
                    RemoveEncryptedAssertion(response); // TODO should check first if response is valid or not (saving computation power)
                }
                // load metadata from issuer
                EntityDescriptor metadata = LoadMetadataFile(response.Issuer, metadataDirectoryPath);

                // load AuthnRequest from archiver
                string       authnRequestString = archiver.GetArchivedObject(response.Assertion.Subject.SubjectConfirmation.SubjectConfirmationData.InResponseTo);
                AuthnRequest authnRequest       = serializer.ConvertXMLToAuthnRequestObject(Encoding.UTF8.GetString(Convert.FromBase64String(authnRequestString)));

                // check if response is valid
                if (verifier.ValidateResponse(response, responseXML, metadata, authnRequest))
                {
                    LogService.Log(LogService.LogType.Info, "ReadResponse extract attributes from response");
                    responseAssertionAttributes = serializer.GetAttributes(response);
                    return(true);
                }

                throw new SamlCommunicationException("Response is not valid.");
            }
            catch (Exception e)
            {
                LogService.Log(LogService.LogType.FatalError, "ReadResponse failed", e);
                throw new SamlCommunicationException("ReadResponse failed", e, SamlCommunicationType.SAMLCOMMUNICATION);
            }
        }
        public void CreateAuthnRequstTest()
        {
            string            xmlString = ReadFile(xmlFilename);
            Saml2Serializer   saml      = new Saml2Serializer();
            Cryptography      crypto    = new Cryptography();
            Saml2AuthnRequest authn     = new Saml2AuthnRequest();

            AuthnRequest authnRequest = saml.ConvertXMLToAuthnRequestObject(xmlString);

            authn.AssertionConsumerServiceURL    = authnRequest.AssertionConsumerServiceURL;
            authn.AttributeConsumingServiceIndex = authnRequest.AttributeConsumingServiceIndex;
            authn.Destination  = authnRequest.Destination;
            authn.ForceAuthn   = authnRequest.ForceAuthn;
            authn.Issuer       = authnRequest.Issuer;
            authn.ProviderName = "HybridIssuer";

            TimeZone localZone = TimeZone.CurrentTimeZone;

            authn.IssueInstant = localZone.ToUniversalTime(DateTime.Now);
            authn.ID           = "65464-6546-6454889-3313";

            string original;
            string zipped = saml.Deflate(authn.ToXML(), out original);

            string sigAlg = "http://www.w3.org/2000/09/xmldsig#rsa-sha1";

            // SAMLResponse=value&RelayState=value&SigAlg=value
            string toSign = "SAMLRequest=" + HttpUtility.UrlEncode(zipped, Encoding.UTF8)
                            + "&RelayState=" + HttpUtility.UrlEncode("34bad366-f60b-4491-a462-230ea22423ad", Encoding.UTF8)
                            + "&SigAlg=" + HttpUtility.UrlEncode(sigAlg, Encoding.UTF8);

            //byte[] sig = saml.SignXML(xmlString);
            //string signature = Convert.ToBase64String(sig);

            string keystorePath     = AppDomain.CurrentDomain.BaseDirectory + "\\Keys\\hybridissuer.pfx";
            string keystorePassword = "******";
            string friendlyName     = "hybridissuer";
            SamlCertificateController certController = new SamlCertificateController();
            X509Certificate2          cert           = certController.GetCertificate(friendlyName, keystorePath, keystorePassword);

            string signature = crypto.SignString(toSign, cert, Cryptography.SigningAlgorithm.SHA1withRSA);
            string request   = authnRequest.Destination + "?" + toSign + "&Signature=" + HttpUtility.UrlEncode(signature, Encoding.UTF8);
        }
        public void ValidateResponseWithoutTimeInvalidTest()
        {
            Saml2Serializer  serializer       = new Saml2Serializer();
            SamlValidator    validator        = new SamlValidator();
            string           xml              = ReadFile(xmlResponseFilename);
            EntityDescriptor entityDescriptor = serializer.ConvertXMLToEntityDescriptorObject(ReadFile(xmlMetadataFile));
            AuthnRequest     authnRequest     = serializer.ConvertXMLToAuthnRequestObject(ReadFile(xmlAuthnRequestFile));

            Response response = serializer.ConvertXMLToResponseObject(xml);

            // wrong response.Status.StatusCode.Value
            try
            {
                response.Status.StatusCode.Value = "urn:oasis:names:tc:SAML:2.0:status:Requester";
                bool isValid = validator.ValidateResponse(response, xml, entityDescriptor, authnRequest, false);
            }
            catch (SamlCommunicationException e) { Assert.IsTrue(true); } // exception expected in this test
            catch (Exception e) { Assert.Fail(e.Message); }               // not this kind of exception expected

            // wrong response.Issuer
            try
            {
                response.Issuer = "wrongIssuer";
                bool isValid = validator.ValidateResponse(response, xml, entityDescriptor, authnRequest, false);
            }
            catch (SamlCommunicationException e) { Assert.IsTrue(true); } // exception expected in this test
            catch (Exception e) { Assert.Fail(e.Message); }               // not this kind of exception expected

            // wrong x509 certificate
            try
            {
                response.Signature.KeyInfo.X509Data.X509Certificate = response.Signature.KeyInfo.X509Data.X509Certificate + "s";
                bool isValid = validator.ValidateResponse(response, xml, entityDescriptor, authnRequest, false);
            }
            catch (SamlCommunicationException e) { Assert.IsTrue(true); } // exception expected in this test
            catch (Exception e) { Assert.Fail(e.Message); }               // not this kind of exception expected

            // response was changed / attack
            try
            {
                string attackedXML = ReadFile("ChangedSamlResponseSimpleSamlPHP.xml");

                response.Signature.KeyInfo.X509Data.X509Certificate = response.Signature.KeyInfo.X509Data.X509Certificate + "s";
                bool isValid = validator.ValidateResponse(response, attackedXML, entityDescriptor, authnRequest, false);
            }
            catch (SamlCommunicationException e) { Assert.IsTrue(true); } // exception expected in this test
            catch (Exception e) { Assert.Fail(e.Message); }               // not this kind of exception expected

            // wrong response.Destination
            try
            {
                response.Destination = "newdesinationaddress.com";
                bool isValid = validator.ValidateResponse(response, xml, entityDescriptor, authnRequest, false);
            }
            catch (SamlCommunicationException e) { Assert.IsTrue(true); } // exception expected in this test
            catch (Exception e) { Assert.Fail(e.Message); }               // not this kind of exception expected

            // wrong response.Assertion.Conditions.AudienceRestriction.Audience -> issuer
            try
            {
                response.Assertion.Conditions.AudienceRestriction.Audience = "otherIssuer";
                bool isValid = validator.ValidateResponse(response, xml, entityDescriptor, authnRequest, false);
            }
            catch (SamlCommunicationException e) { Assert.IsTrue(true); } // exception expected in this test
            catch (Exception e) { Assert.Fail(e.Message); }               // not this kind of exception expected

            // wrong response.InResponseTo
            try
            {
                response.InResponseTo = "InResponseTo";
                bool isValid = validator.ValidateResponse(response, xml, entityDescriptor, authnRequest, false);
            }
            catch (SamlCommunicationException e) { Assert.IsTrue(true); } // exception expected in this test
            catch (Exception e) { Assert.Fail(e.Message); }               // not this kind of exception expected

            // wrong response.Assertion.Subject.SubjectConfirmation.Method
            try
            {
                response.Assertion.Subject.SubjectConfirmation.Method = "urn:oasis:names:tc:SAML:2.0:cm:holder-of-key";
                bool isValid = validator.ValidateResponse(response, xml, entityDescriptor, authnRequest, false);
            }
            catch (SamlCommunicationException e) { Assert.IsTrue(true); } // exception expected in this test
            catch (Exception e) { Assert.Fail(e.Message); }               // not this kind of exception expected
        }