/// <summary>
        /// Decrypts an assertion we received from "fælles-offentlige brugerstyring".
        /// </summary>
        private static void DecryptFOBSAssertion(string file)
        {
            string assertionBase64 = File.ReadAllText(file);

            byte[] assertionBytes = Convert.FromBase64String(assertionBase64);

            XmlDocument doc = new XmlDocument();

            doc.PreserveWhitespace = true;
            doc.Load(new MemoryStream(assertionBytes));

            XmlNodeList encryptedList =
                doc.GetElementsByTagName(EncryptedAssertion.ELEMENT_NAME, Saml20Constants.ASSERTION);

            Assert.That(encryptedList.Count == 1);

            // Do some mock configuration.
            FederationConfig config = FederationConfig.GetConfig();

            config.AllowedAudienceUris.Audiences.Add("https://saml.safewhere.net");

            SAML20FederationConfig descr = SAML20FederationConfig.GetConfig();

            descr.Endpoints.MetadataLocation = @"Saml20\Protocol\MetadataDocs\FOBS"; // Set it manually.
            Assert.That(Directory.Exists(descr.Endpoints.MetadataLocation));

            X509Certificate2         cert   = new X509Certificate2(@"Saml20\Certificates\SafewhereTest_SFS.pfx", "test1234");
            Saml20EncryptedAssertion encass =
                new Saml20EncryptedAssertion((RSA)cert.PrivateKey);

            encass.LoadXml((XmlElement)encryptedList[0]);
            encass.Decrypt();

            // Retrieve metadata
            Saml20Assertion assertion = new Saml20Assertion(encass.Assertion.DocumentElement, null, false);

            IDPEndPoint endp = descr.FindEndPoint(assertion.Issuer);

            Assert.IsNotNull(endp, "Endpoint not found");
            Assert.IsNotNull(endp.metadata, "Metadata not found");

            try
            {
                assertion.CheckValid(AssertionUtil.GetTrustedSigners(assertion.Issuer));
                Assert.Fail("Verification should fail. Token does not include its signing key.");
            } catch (InvalidOperationException)
            {}

            Assert.IsNull(assertion.SigningKey, "Signing key is already present on assertion. Modify test.");
            IEnumerable <string> validationFailures;

            Assert.That(assertion.CheckSignature(Saml20SignonHandler.GetTrustedSigners(endp.metadata.GetKeys(KeyTypes.signing), endp, out validationFailures)));
            Assert.IsNotNull(assertion.SigningKey, "Signing key was not set on assertion instance.");
        }
            public void CanDecryptFOBSAssertion()
            {
                // Arrange
                var doc           = AssertionUtil.LoadBase64EncodedXmlDocument(@"Assertions\fobs-assertion2");
                var encryptedList = doc.GetElementsByTagName(EncryptedAssertion.ElementName, Saml20Constants.Assertion);

                // Do some mock configuration.
                var config = Saml2Config.GetConfig();

                config.AllowedAudienceUris.Add(new AudienceUriElement {
                    Uri = "https://saml.safewhere.net"
                });
                config.IdentityProviders.MetadataLocation = @"Protocol\MetadataDocs\FOBS"; // Set it manually.
                Assert.That(Directory.Exists(config.IdentityProviders.MetadataLocation));

                var cert = new X509Certificate2(@"Certificates\SafewhereTest_SFS.pfx", "test1234");
                var encryptedAssertion = new Saml20EncryptedAssertion((RSA)cert.PrivateKey);

                encryptedAssertion.LoadXml((XmlElement)encryptedList[0]);

                // Act
                encryptedAssertion.Decrypt();

                // Retrieve metadata
                var assertion = new Saml20Assertion(encryptedAssertion.Assertion.DocumentElement, null, false);
                var endp      = config.IdentityProviders.FirstOrDefault(x => x.Id == assertion.Issuer);

                // Assert
                Assert.That(encryptedList.Count == 1);
                Assert.IsNotNull(endp, "Endpoint not found");
                Assert.IsNotNull(endp.Metadata, "Metadata not found");

                try
                {
                    assertion.CheckValid(AssertionUtil.GetTrustedSigners(assertion.Issuer));
                    Assert.Fail("Verification should fail. Token does not include its signing key.");
                }
                catch (InvalidOperationException)
                {
                }

                Assert.IsNull(assertion.SigningKey, "Signing key is already present on assertion. Modify test.");
                Assert.That(assertion.CheckSignature(Saml20SignonHandler.GetTrustedSigners(endp.Metadata.GetKeys(KeyTypes.Signing), endp)));
                Assert.IsNotNull(assertion.SigningKey, "Signing key was not set on assertion instance.");
            }
예제 #3
0
        /// <summary>
        /// Performs the attribute query against the specified IdP endpoint and adds the resulting attributes to Saml20Identity.Current.
        /// </summary>
        /// <param name="context">The http context.</param>
        /// <param name="endPoint">The IdP to perform the query against.</param>
        /// <param name="nameIdFormat">The nameid format.</param>
        public void PerformQuery(HttpContext context, IDPEndPoint endPoint, string nameIdFormat)
        {
            Trace.TraceMethodCalled(GetType(), "PerformQuery()");

            HttpSOAPBindingBuilder builder = new HttpSOAPBindingBuilder(context);

            NameID name = new NameID();

            name.Value  = Saml20Identity.Current.Name;
            name.Format = nameIdFormat;
            _attrQuery.Subject.Items = new object[] { name };

            _attrQuery.SamlAttribute = _attributes.ToArray();
            XmlDocument query = new XmlDocument();

            query.XmlResolver = null;
            query.LoadXml(Serialization.SerializeToXmlString(_attrQuery));

            var signingCertificate  = FederationConfig.GetConfig().SigningCertificate.GetCertificate();
            var shaHashingAlgorithm = SignatureProviderFactory.ValidateShaHashingAlgorithm(endPoint.ShaHashingAlgorithm);
            var signatureProvider   = SignatureProviderFactory.CreateFromShaHashingAlgorithmName(shaHashingAlgorithm);

            signatureProvider.SignAssertion(query, ID, signingCertificate);
            if (query.FirstChild is XmlDeclaration)
            {
                query.RemoveChild(query.FirstChild);
            }

            Stream s;

            if (Trace.ShouldTrace(TraceEventType.Information))
            {
                Trace.TraceData(TraceEventType.Information, string.Format(Tracing.SendAttrQuery, endPoint.metadata.GetAttributeQueryEndpointLocation(), query.OuterXml));
            }

            try
            {
                s = builder.GetResponse(endPoint.metadata.GetAttributeQueryEndpointLocation(), query.OuterXml,
                                        endPoint.AttributeQuery);
            }
            catch (Exception e)
            {
                Trace.TraceData(TraceEventType.Error, e.ToString());
                throw;
            }

            HttpSOAPBindingParser parser = new HttpSOAPBindingParser(s);

            Status status = parser.GetStatus();

            if (status.StatusCode.Value != Saml20Constants.StatusCodes.Success)
            {
                Trace.TraceData(TraceEventType.Error,
                                string.Format(Tracing.AttrQueryStatusError, Serialization.SerializeToXmlString(status)));
                throw new Saml20Exception(status.StatusMessage);
            }

            bool isEncrypted;

            XmlElement xmlAssertion = Saml20SignonHandler.GetAssertion(parser.SamlMessage, out isEncrypted);

            if (isEncrypted)
            {
                Saml20EncryptedAssertion ass =
                    new Saml20EncryptedAssertion(
                        (RSA)FederationConfig.GetConfig().SigningCertificate.GetCertificate().PrivateKey);
                ass.LoadXml(xmlAssertion);
                ass.Decrypt();
                xmlAssertion = ass.Assertion.DocumentElement;
            }

            Saml20Assertion assertion =
                new Saml20Assertion(xmlAssertion, null,
                                    AssertionProfile.Core, endPoint.QuirksMode);

            assertion.Validate(DateTime.UtcNow);

            if (Trace.ShouldTrace(TraceEventType.Information))
            {
                Trace.TraceData(TraceEventType.Information, string.Format(Tracing.AttrQueryAssertion, xmlAssertion == null ? string.Empty : xmlAssertion.OuterXml));
            }

            IEnumerable <string> validationFailures;

            if (!assertion.CheckSignature(Saml20SignonHandler.GetTrustedSigners(endPoint.metadata.Keys, endPoint, out validationFailures)))
            {
                Trace.TraceData(TraceEventType.Error, Resources.SignatureInvalid);
                throw new Saml20Exception(Resources.SignatureInvalid);
            }

            foreach (SamlAttribute attr in assertion.Attributes)
            {
                Saml20Identity.Current.AddAttributeFromQuery(attr.Name, attr);
            }
        }
예제 #4
0
        /// <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, IdentityProvider 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.Current.ServiceProvider.SigningCertificate.GetCertificate().PrivateKey);
                ass.LoadXml(xmlAssertion);
                ass.Decrypt();
                xmlAssertion = ass.Assertion.DocumentElement;
            }

            var assertion = new Saml20Assertion(xmlAssertion, null, Saml2Config.Current.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);
            }
        }