예제 #1
0
        public void AcsCommand_Run_Response_ThrowsOnNoStoredNorConfiguredReturnUrl()
        {
            var response =
                @"<saml2p:Response xmlns:saml2p=""urn:oasis:names:tc:SAML:2.0:protocol""
                xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion""
                ID = """ + MethodBase.GetCurrentMethod().Name + @""" Version=""2.0"" IssueInstant=""2013-01-01T00:00:00Z""
                InResponseTo=""InResponseToId"">
                <saml2:Issuer>
                    https://idp.example.com
                </saml2:Issuer>
                <saml2p:Status>
                    <saml2p:StatusCode Value=""urn:oasis:names:tc:SAML:2.0:status:Success"" />
                </saml2p:Status>
                <saml2:Assertion
                Version=""2.0"" ID=""" + MethodBase.GetCurrentMethod().Name + @"_Assertion""
                IssueInstant=""2013-09-25T00:00:00Z"">
                    <saml2:Issuer>https://idp.example.com</saml2:Issuer>
                    <saml2:Subject>
                        <saml2:NameID>SomeUser</saml2:NameID>
                        <saml2:SubjectConfirmation Method=""urn:oasis:names:tc:SAML:2.0:cm:bearer"" />
                    </saml2:Subject>
                    <saml2:Conditions NotOnOrAfter=""2100-01-01T00:00:00Z"" />
                </saml2:Assertion>
            </saml2p:Response>";

            var formValue = Convert.ToBase64String(Encoding.UTF8.GetBytes(
                                                       SignedXmlHelper.SignXml(response)));

            var r = new HttpRequestData(
                "POST",
                new Uri("http://localhost"),
                "/ModulePath",
                new KeyValuePair <string, IEnumerable <string> >[]
            {
                new KeyValuePair <string, IEnumerable <string> >("SAMLResponse", new string[] { formValue })
            },
                new StoredRequestState(new EntityId("https://idp.example.com"), null, new Saml2Id("InResponseToId"), null));

            var options = StubFactory.CreateOptions();

            options.SPOptions.ReturnUrl = null;

            new AcsCommand().Invoking(a => a.Run(r, options))
            .ShouldThrow <ConfigurationErrorsException>().WithMessage(AcsCommand.SpInitiatedMissingReturnUrl);
        }
예제 #2
0
        public void Federation_RejectsTamperedMetadataWhenConfiguredWithKeys()
        {
            var options = StubFactory.CreateOptions();

            var metadataLocation = "http://localhost:13428/federationMetadataSignedTampered";

            var subject = new Federation(
                metadataLocation,
                true,
                options,
                new List <X509Certificate2>()
            {
                SignedXmlHelper.TestCert
            });

            subject.LastMetadataLoadException.As <InvalidSignatureException>()
            .Message.Should().Match("*tampered*");
        }
예제 #3
0
        public void IdentityProvider_CreateAuthenticateRequest_IncludesSigningCertificate_ForConfigAlways()
        {
            var options   = StubFactory.CreateOptions();
            var spOptions = options.SPOptions;

            spOptions.AuthenticateRequestSigningBehavior = SigningBehavior.Always;
            spOptions.ServiceCertificates.Add(new ServiceCertificate
            {
                Certificate = SignedXmlHelper.TestCert
            });

            var idp  = options.IdentityProviders.Default;
            var urls = StubFactory.CreateSaml2Urls();

            var subject = idp.CreateAuthenticateRequest(urls);

            subject.SigningCertificate.Thumbprint.Should().Be(SignedXmlHelper.TestCert.Thumbprint);
        }
예제 #4
0
        public void SPOptionsExtensions_CreateMetadata_WithServiceCertificateConfiguredAndPostLogoutEnabled()
        {
            var options = StubFactory.CreateOptions();

            options.SPOptions.ServiceCertificates.Add(new ServiceCertificate {
                Certificate = SignedXmlHelper.TestCert2
            });
            options.SPOptions.Compatibility.EnableLogoutOverPost = true;

            var metadata   = options.SPOptions.CreateMetadata(StubFactory.CreateSaml2Urls());
            var spMetadata = metadata.RoleDescriptors.OfType <SpSsoDescriptor>().Single();

            var sloPost = spMetadata.SingleLogoutServices.Single(
                slo => slo.Binding == Saml2Binding.HttpPostUri);

            sloPost.Location.Should().Be("http://localhost/Saml2/Logout");
            sloPost.ResponseLocation.Should().BeNull();
        }
예제 #5
0
        public void Saml2RedirectBinding_Unbind_ThrowsOnWeakSignatureAlgorithm()
        {
            var url = CreateAndBindMessageWithSignature().Location;

            var request = new HttpRequestData("GET", url);

            var options = StubFactory.CreateOptions();

            options.SPOptions.MinIncomingSigningAlgorithm = SecurityAlgorithms.RsaSha384Signature;

            // Check that the created url indeed is signed with SHA256.
            url.OriginalString.Should().Contain("sha256");

            var actual = Saml2Binding.Get(request)
                         .Invoking(b => b.Unbind(request, options))
                         .Should().Throw <InvalidSignatureException>()
                         .WithMessage("*weak*");
        }
예제 #6
0
        public void LogoutCommand_Run_LocalLogoutIfLogoutRequestDisabled()
        {
            var user = new ClaimsPrincipal(
                new ClaimsIdentity(new Claim[]
            {
                new Claim(Saml2ClaimTypes.LogoutNameIdentifier, ",,,,NameId", null, "https://idp.example.com"),
                new Claim(Saml2ClaimTypes.SessionIndex, "SessionId", null, "https://idp.example.com")
            }));

            var options = StubFactory.CreateOptions();

            options.SPOptions.ServiceCertificates.Add(SignedXmlHelper.TestCert);

            var idpEntityId = new EntityId("https://idp.example.com");

            options.IdentityProviders[idpEntityId].DisableOutboundLogoutRequests = true;

            LogoutCommand_Run_LocalLogout(options, user);
        }
예제 #7
0
        public void SPOptionsExtensions_CreateMetadata_MultipleServiceCertificate()
        {
            var options = StubFactory.CreateOptions();

            options.SPOptions.ServiceCertificates.Add(new ServiceCertificate {
                Certificate = SignedXmlHelper.TestCert2, Use = CertificateUse.Encryption
            });
            options.SPOptions.ServiceCertificates.Add(new ServiceCertificate {
                Certificate = SignedXmlHelper.TestCert2, Use = CertificateUse.Signing
            });
            var metadata = options.SPOptions.CreateMetadata(StubFactory.CreateSaml2Urls());

            var spMetadata = metadata.RoleDescriptors.OfType <SpSsoDescriptor>().Single();

            spMetadata.Should().NotBeNull();
            spMetadata.Keys.Count.Should().Be(2);
            spMetadata.Keys.Where(k => k.Use == KeyType.Encryption).Count().Should().Be(1);
            spMetadata.Keys.Where(k => k.Use == KeyType.Signing).Count().Should().Be(1);
        }
예제 #8
0
        public void LogoutCommand_Run_ThrowsOnUnknownMessageRecevied()
        {
            var msg = new Saml2MessageImplementation
            {
                MessageName        = "SAMLRequest",
                SigningCertificate = SignedXmlHelper.TestCert,
                DestinationUrl     = new Uri("http://localhost"),
                XmlData            = $"<Unknown><Issuer xmlns=\"{Saml2Namespaces.Saml2Name}\">https://idp.example.com</Issuer></Unknown>"
            };

            var url = Saml2Binding.Get(Saml2BindingType.HttpRedirect)
                      .Bind(msg).Location;

            var request = new HttpRequestData("GET", url);

            CommandFactory.GetCommand(CommandFactory.LogoutCommandName)
            .Invoking(c => c.Run(request, StubFactory.CreateOptions()))
            .Should().Throw <NotImplementedException>();
        }
        public void LogoutCommand_Run_ReturnsLogoutRequest()
        {
            Thread.CurrentPrincipal = new ClaimsPrincipal(
                new ClaimsIdentity(new Claim[]
            {
                new Claim(ClaimTypes.NameIdentifier, "NameId", null, "https://idp.example.com"),
                new Claim(AuthServicesClaimTypes.SessionIndex, "SessionId", null, "https://idp.example.com")
            }, "Federation"));

            var request = new HttpRequestData("GET", new Uri("http://sp-internal.example.com/AuthServices/Logout"));

            var options = StubFactory.CreateOptions();

            options.SPOptions.ServiceCertificates.Add(SignedXmlHelper.TestCert);
            options.SPOptions.PublicOrigin = new Uri("https://sp.example.com/");

            var actual = CommandFactory.GetCommand(CommandFactory.LogoutCommandName)
                         .Run(request, options);

            var expected = new CommandResult
            {
                HttpStatusCode        = HttpStatusCode.SeeOther,
                TerminateLocalSession = true,
                // Deliberately not comparing Location.
                // Deliberately not comparing SetCookieName.
                RequestState = new StoredRequestState(
                    new EntityId("https://idp.example.com"),
                    new Uri("https://sp.example.com/"),
                    null,
                    null)
            };

            actual.ShouldBeEquivalentTo(expected, opt => opt
                                        .Excluding(cr => cr.Location)
                                        .Excluding(cr => cr.SetCookieName)
                                        .Excluding(cr => cr.RequestState.MessageId));

            var relayState = HttpUtility.ParseQueryString(actual.Location.Query)["RelayState"];

            actual.SetCookieName.Should().Be("Kentor." + relayState);
            actual.Location.GetLeftPart(UriPartial.Path).Should().Be("https://idp.example.com/logout");
        }
예제 #10
0
        public void IdentityProvider_CreateLogoutRequest()
        {
            var options = StubFactory.CreateOptions();

            options.SPOptions.ServiceCertificates.Add(new ServiceCertificate()
            {
                Certificate = SignedXmlHelper.TestCert
            });

            var subject = options.IdentityProviders[0];

            var logoutNameIdClaim = new Claim(
                Saml2ClaimTypes.LogoutNameIdentifier, ",,urn:nameIdFormat,,NameId", null, subject.EntityId.Id);

            var user = new ClaimsPrincipal(new ClaimsIdentity(
                                               new Claim[]
            {
                logoutNameIdClaim,
                new Claim(Saml2ClaimTypes.SessionIndex, "SessionId", null, subject.EntityId.Id)
            }, "Federation"));

            // Grab a datetime both before and after creation to handle case
            // when the second part is changed during excecution of the test.
            // We're assuming that the creation does not take more than a
            // second, so two values will do.
            var beforeTime = DateTime.UtcNow.ToSaml2DateTimeString();
            var actual     = subject.CreateLogoutRequest(user);
            var aftertime  = DateTime.UtcNow.ToSaml2DateTimeString();

            actual.Issuer.Id.Should().Be(options.SPOptions.EntityId.Id);
            actual.Id.Value.Should().NotBeEmpty();
            actual.IssueInstant.Should().Match(i => i == beforeTime || i == aftertime);
            actual.SessionIndex.Should().Be("SessionId");
            actual.SigningCertificate.Thumbprint.Should().Be(SignedXmlHelper.TestCert.Thumbprint);

            var expectedNameId = new Saml2NameIdentifier("NameId")
            {
                Format = new Uri("urn:nameIdFormat")
            };

            actual.NameId.Should().BeEquivalentTo(expectedNameId);
        }
예제 #11
0
        public void Federation_RejectsTooWeakMetadataSignatureAlgorithmWhenConfiguredWithKeys()
        {
            var options = StubFactory.CreateOptions();

            options.SPOptions.MinIncomingSigningAlgorithm = SignedXml.XmlDsigRSASHA512Url;

            var metadataLocation = "http://localhost:13428/federationMetadataSigned";

            var subject = new Federation(
                metadataLocation,
                true,
                options,
                new List <X509Certificate2>()
            {
                SignedXmlHelper.TestCert
            });

            subject.LastMetadataLoadException.As <InvalidSignatureException>()
            .Message.Should().Match("*algorithm*256*weak*512*");
        }
예제 #12
0
        public void Federation_LoadInCommonMetadata()
        {
            // InCommon is the large US university federation. To test that
            // Saml2 handles some real world metadata, the metadata from
            // the InCommon federation is used.

            var options = StubFactory.CreateOptions();

            var path            = "~/Metadata/InCommonMetadata.xml";
            var idpInFederation = new EntityId("https://shibboleth.umassmed.edu/idp/shibboleth");

            Action a = () => new Federation(path, true, options);

            a.ShouldNotThrow();

            IdentityProvider idp;

            options.IdentityProviders.TryGetValue(idpInFederation, out idp)
            .Should().BeTrue();
        }
예제 #13
0
        public void LogoutCommand_Run_ThrowsOnMissingIssuerInReceivedMessage()
        {
            var msg = new Saml2MessageImplementation
            {
                MessageName        = "SAMLRequest",
                SigningCertificate = SignedXmlHelper.TestCert,
                DestinationUrl     = new Uri("http://localhost"),
                XmlData            = "<Xml />"
            };

            var url = Saml2Binding.Get(Saml2BindingType.HttpRedirect)
                      .Bind(msg).Location;

            var request = new HttpRequestData("GET", url);

            CommandFactory.GetCommand(CommandFactory.LogoutCommandName)
            .Invoking(c => c.Run(request, StubFactory.CreateOptions()))
            .Should().Throw <InvalidSignatureException>()
            .WithMessage("There is no Issuer element in the message, so there is no way to know what certificate to use to validate the signature.");
        }
예제 #14
0
        public void Federation_LoadSambiTestMetadata()
        {
            // Sambi is the Swedish health care federation. To test that Saml2
            // handles some real world metadata, the metadadata from Sambi's test
            // environment is used.

            var options = StubFactory.CreateOptions();

            var path            = "~/Metadata/SambiMetadata.xml";
            var idpInFederation = new EntityId("http://idp-acc.test.ek.sll.se/neas");

            Action a = () => new Federation(path, true, options);

            a.ShouldNotThrow();

            IdentityProvider idp;

            options.IdentityProviders.TryGetValue(idpInFederation, out idp)
            .Should().BeTrue();
        }
예제 #15
0
        public void Federation_LoadSkolfederationMetadata()
        {
            // Skolfederation is the Swedish national school federation. To test that
            // Saml2 handles some real world metadata, the metadata from the
            // skolfederation federation is used.

            var options = StubFactory.CreateOptions();

            var path            = "~/Metadata/SkolfederationMetadata.xml";
            var idpInFederation = new EntityId("http://fs.ale.se/adfs/services/trust");

            Action a = () => new Federation(path, true, options);

            a.ShouldNotThrow();

            IdentityProvider idp;

            options.IdentityProviders.TryGetValue(idpInFederation, out idp)
            .Should().BeTrue();
        }
예제 #16
0
        public void LogoutCommand_Run_DoNotCalls_NotificationForRelativeUrl()
        {
            var relativeUri = HttpUtility.UrlEncode("/");
            var request     = new HttpRequestData("GET", new Uri($"http://sp.example.com/Saml2/Logout?ReturnUrl={relativeUri}"));
            var options     = StubFactory.CreateOptions();

            var validateAbsoluteReturnUrlCalled = false;

            options.Notifications.ValidateAbsoluteReturnUrl =
                (url) =>
            {
                validateAbsoluteReturnUrlCalled = true;
                return(true);
            };

            Action a = () => CommandFactory.GetCommand(CommandFactory.LogoutCommandName).Run(request, options);

            a.Should().NotThrow <InvalidOperationException>("the ReturnUrl is relative");
            validateAbsoluteReturnUrlCalled.Should().BeFalse("the ValidateAbsoluteReturnUrl notification should not have been called");
        }
예제 #17
0
        public void LogoutCommand_Run_Calls_NotificationForAbsoluteUrl()
        {
            var absoluteUri = HttpUtility.UrlEncode("http://google.com");
            var request     = new HttpRequestData("GET", new Uri($"http://sp.example.com/AuthServices/Logout?ReturnUrl={absoluteUri}"));
            var options     = StubFactory.CreateOptions();

            var validateAbsoluteReturnUrlCalled = false;

            options.Notifications.ValidateAbsoluteReturnUrl =
                (url) =>
            {
                validateAbsoluteReturnUrlCalled = true;
                return(true);
            };

            Action a = () => CommandFactory.GetCommand(CommandFactory.LogoutCommandName).Run(request, options);

            a.ShouldNotThrow <InvalidOperationException>("the ValidateAbsoluteReturnUrl notification returns true");
            validateAbsoluteReturnUrlCalled.Should().BeTrue("the ValidateAbsoluteReturnUrl notification should have been called");
        }
예제 #18
0
        public void LogoutCommand_Run_PreservesReturnUrl()
        {
            Thread.CurrentPrincipal = new ClaimsPrincipal(
                new ClaimsIdentity(new Claim[]
            {
                new Claim(ClaimTypes.NameIdentifier, "NameId", null, "https://idp.example.com"),
                new Claim(AuthServicesClaimTypes.SessionIndex, "SessionId", null, "https://idp.example.com")
            }, "Federation"));

            var request = new HttpRequestData("GET", new Uri("http://sp.example.com/AuthServices/Logout?ReturnUrl=%2FLoggedOut"));

            var options = StubFactory.CreateOptions();

            options.SPOptions.ServiceCertificates.Add(SignedXmlHelper.TestCert);

            var actual = CommandFactory.GetCommand(CommandFactory.LogoutCommandName)
                         .Run(request, options);

            actual.RequestState.ReturnUrl.OriginalString.Should().Be("http://sp.example.com/LoggedOut");
        }
예제 #19
0
        public void SignInCommand_Run_Calls_CommandResultCreated_OnRedirectToDS()
        {
            var options = StubFactory.CreateOptions();
            var idp     = options.IdentityProviders.Default;

            options.SPOptions.DiscoveryServiceUrl.Should().NotBeNull("this test assumes a non-null DS url");

            var request = new HttpRequestData("GET",
                                              new Uri("http://sp.example.com"));

            CommandResult notifiedCommandResult = null;

            options.Notifications.SignInCommandResultCreated = (cr, r) =>
            {
                notifiedCommandResult = cr;
            };

            SignInCommand.Run(null, null, request, options, null)
            .Should().BeSameAs(notifiedCommandResult);
        }
예제 #20
0
        public void Federation_ValidatesCertificateWhenConfigured()
        {
            var options = StubFactory.CreateOptions();

            options.SPOptions.ValidateCertificates = true;

            var metadataLocation = "http://localhost:13428/federationMetadataSigned";

            var subject = new Federation(
                metadataLocation,
                true,
                options,
                new List <X509Certificate2>()
            {
                SignedXmlHelper.TestCert
            });

            subject.LastMetadataLoadException.As <InvalidSignatureException>()
            .Message.Should().Match("*verification*certificate*failed*");
        }
예제 #21
0
        public void IdentityProvider_CreateAuthenticateRequest_SigningBehaviorNever_OverridesIdpWantsRequestsSigned()
        {
            var options   = StubFactory.CreateOptions();
            var spOptions = options.SPOptions;

            spOptions.AuthenticateRequestSigningBehavior = SigningBehavior.Never;
            spOptions.ServiceCertificates.Add(new ServiceCertificate
            {
                Certificate = SignedXmlHelper.TestCert
            });

            var subject = new IdentityProvider(new EntityId("http://idp.example.com"), spOptions)
            {
                WantAuthnRequestsSigned = true
            };
            var urls = StubFactory.CreateSaml2Urls();

            var actual = subject.CreateAuthenticateRequest(urls).SigningCertificate;

            actual.Should().BeNull();
        }
        public void SPOptionsExtensions_CreateMetadata_WithServiceCertificateConfigured()
        {
            var options = StubFactory.CreateOptions();
            options.SPOptions.ServiceCertificates.Add(new ServiceCertificate { Certificate = SignedXmlHelper.TestCert2 });
            var metadata = options.SPOptions.CreateMetadata(StubFactory.CreateAuthServicesUrls());

            var spMetadata = metadata.RoleDescriptors.OfType<ServiceProviderSingleSignOnDescriptor>().Single();
            spMetadata.Should().NotBeNull();
            spMetadata.Keys.Count.Should().Be(1);
            spMetadata.Keys.Single().Use.Should().Be(KeyType.Unspecified);

            // When there is a service certificate, expose SLO endpoints.
            var sloRedirect = spMetadata.SingleLogoutServices.Single(
                slo => slo.Binding == Saml2Binding.HttpRedirectUri);
            sloRedirect.Location.Should().Be("http://localhost/AuthServices/Logout");
            sloRedirect.ResponseLocation.Should().BeNull();
            var sloPost = spMetadata.SingleLogoutServices.Single(
                slo => slo.Binding == Saml2Binding.HttpPostUri);
            sloPost.Location.Should().Be("http://localhost/AuthServices/Logout");
            sloPost.ResponseLocation.Should().BeNull();
        }
예제 #23
0
        private void LogoutCommand_Run_LocalLogout()
        {
            var subject = CommandFactory.GetCommand(CommandFactory.LogoutCommandName);

            var options = StubFactory.CreateOptions();

            options.SPOptions.SigningServiceCertificate.Should().BeNull("this helper is used for test of behaviour when no certificate is configured");

            var actual = subject.Run(
                new HttpRequestData("GET", new Uri("http://localhost/Logout?ReturnUrl=LoggedOut")),
                options);

            var expected = new CommandResult()
            {
                HttpStatusCode        = HttpStatusCode.SeeOther,
                Location              = new Uri("http://localhost/LoggedOut"),
                TerminateLocalSession = true
            };

            actual.ShouldBeEquivalentTo(expected);
        }
예제 #24
0
        public void Saml2PostBinding_Unbind_Request()
        {
            var requestData = Convert.ToBase64String(Encoding.UTF8.GetBytes("<data/>"));

            var request = new HttpRequestData(
                "POST",
                new Uri("http://something"),
                "/path",
                new KeyValuePair <string, string[]>[]
            {
                new KeyValuePair <string, string[]>("SAMLRequest", new[] { requestData })
            },
                null,
                null);

            var actual = Saml2Binding.Get(request).Unbind(request, StubFactory.CreateOptions());

            actual.Data.Should().BeEquivalentTo(XmlHelpers.XmlDocumentFromString("<data/>").DocumentElement);
            actual.RelayState.Should().BeNull();
            actual.TrustLevel.Should().Be(TrustLevel.None);
        }
예제 #25
0
        public void SignInCommand_Run_DoNotCalls_NotificationForRelativeUrl()
        {
            var defaultDestination = Options.FromConfiguration.IdentityProviders.Default.SingleSignOnServiceUrl;
            var relativeUri        = HttpUtility.UrlEncode("~/Secure");
            var httpRequest        = new HttpRequestData("GET", new Uri($"http://localhost/signin?ReturnUrl={relativeUri}"));
            var validateAbsoluteReturnUrlCalled = false;

            var options = StubFactory.CreateOptions();

            options.Notifications.ValidateAbsoluteReturnUrl =
                (url) =>
            {
                validateAbsoluteReturnUrlCalled = true;
                return(true);
            };

            Action a = () => new SignInCommand().Run(httpRequest, options);

            a.Should().NotThrow <InvalidOperationException>("the ReturnUrl is relative");
            validateAbsoluteReturnUrlCalled.Should().BeFalse("the ValidateAbsoluteReturnUrl notification should not have been called");
        }
예제 #26
0
        public void Saml2ArtifactBinding_Unbind_FromGetUsesIdpFromNotification()
        {
            var issuer   = new EntityId("https://idp.example.com");
            var artifact = Uri.EscapeDataString(
                Convert.ToBase64String(
                    Saml2ArtifactBinding.CreateArtifact(issuer, 0x1234)));

            var relayState = "relayState";

            var relayData = new Dictionary <string, string>
            {
                { "key", "value" }
            };

            var r = new HttpRequestData(
                "GET",
                new Uri($"http://example.com/path/acs?SAMLart={artifact}&RelayState={relayState}"),
                null,
                null,
                new StoredRequestState(issuer, null, null, relayData));

            var options = StubFactory.CreateOptions();

            var idp = options.IdentityProviders.Default;

            options.IdentityProviders.Remove(idp.EntityId);

            var getIdentityProviderCalled = false;

            options.Notifications.GetIdentityProvider = (ei, rd, opt) =>
            {
                getIdentityProviderCalled = true;
                rd["key"].Should().Be("value");
                return(idp);
            };

            var result = Saml2Binding.Get(Saml2BindingType.Artifact).Unbind(r, options);

            getIdentityProviderCalled.Should().BeTrue();
        }
예제 #27
0
        public void SignInCommand_Run_CarriesOverRelayStateOnReturnFromDS()
        {
            var options = StubFactory.CreateOptions();
            var idp     = options.IdentityProviders.Default;

            var relayData = new Dictionary <string, string>
            {
                { "key", "value" }
            };
            var relayState         = "RelayState";
            var returnUrl          = new Uri("/SignedIn", UriKind.Relative);
            var storedRequestState = new StoredRequestState(
                null,
                returnUrl,
                null,
                relayData);

            var uri = new Uri("http://sp.example.com/Saml2/SignIn?RelayState="
                              + relayState
                              + "&idp="
                              + Uri.EscapeDataString(idp.EntityId.Id));

            var request = new HttpRequestData("GET",
                                              uri,
                                              "/Saml2",
                                              null,
                                              storedRequestState)
            {
                RelayState = relayState
            };

            var subject = CommandFactory.GetCommand(CommandFactory.SignInCommandName);

            var actual = subject.Run(request, options);

            actual.ClearCookieName.Should().Be(StoredRequestState.CookieNameBase + relayState, "cookie should be cleared");
            actual.RequestState.ReturnUrl.Should().Be(returnUrl);
            actual.RequestState.Idp.Id.Should().Be(idp.EntityId.Id);
            actual.RequestState.RelayData.ShouldBeEquivalentTo(relayData);
        }
예제 #28
0
        public void Saml2ArtifactBinding_Unbind_FromGet_SignsArtifactResolve()
        {
            var issuer   = new EntityId("https://idp.example.com");
            var artifact = Uri.EscapeDataString(
                Convert.ToBase64String(
                    Saml2ArtifactBinding.CreateArtifact(issuer, 0x1234)));

            var r = new HttpRequestData(
                "GET",
                new Uri($"http://example.com/path/acs?SAMLart={artifact}"));

            var options = StubFactory.CreateOptions();

            options.SPOptions.ServiceCertificates.Add(new ServiceCertificate
            {
                Certificate = SignedXmlHelper.TestCert
            });

            var result = Saml2Binding.Get(Saml2BindingType.Artifact).Unbind(r, options);

            StubServer.LastArtifactResolutionWasSigned.Should().BeTrue();
        }
예제 #29
0
        public void LogoutCommand_Run_DetectsSignatureInLogoutRequestReceivedThroughPostBinding()
        {
            var request = new Saml2LogoutRequest()
            {
                DestinationUrl     = new Uri("http://sp.example.com/path/Saml2/logout"),
                Issuer             = new EntityId("https://idp.example.com"),
                SigningCertificate = SignedXmlHelper.TestCert,
                NameId             = new Saml2NameIdentifier("NameId"),
                SessionIndex       = "SessionID",
                SigningAlgorithm   = SecurityAlgorithms.RsaSha256Signature
            };

            var xml = XmlHelpers.XmlDocumentFromString(request.ToXml());

            xml.Sign(SignedXmlHelper.TestCert);

            var requestData = Convert.ToBase64String(Encoding.UTF8.GetBytes(xml.OuterXml));

            var httpRequest = new HttpRequestData(
                "POST",
                new Uri("http://something"),
                "/path",
                new KeyValuePair <string, IEnumerable <string> >[]
            {
                new KeyValuePair <string, IEnumerable <string> >("SAMLRequest", new[] { requestData })
            },
                null,
                null);

            var options = StubFactory.CreateOptions();

            options.SPOptions.ServiceCertificates.Add(SignedXmlHelper.TestCert);

            var actual = CommandFactory.GetCommand(CommandFactory.LogoutCommandName)
                         .Run(httpRequest, options);

            HttpUtility.ParseQueryString(actual.Location.Query)
            .Keys.Should().Contain("SAMLResponse", "if the request was properly detected a response should be generated");
        }
예제 #30
0
        public void LogoutCommand_Run_ChecksSignatureAlgorithmStrength()
        {
            var request = new Saml2LogoutRequest()
            {
                DestinationUrl     = new Uri("http://sp.example.com/path/Saml2/logout"),
                Issuer             = new EntityId("https://idp.example.com"),
                SigningCertificate = SignedXmlHelper.TestCert,
                SigningAlgorithm   = SecurityAlgorithms.RsaSha256Signature, // Ignored
                NameId             = new Saml2NameIdentifier("NameId"),
                SessionIndex       = "SessionID"
            };

            var xml = XmlHelpers.XmlDocumentFromString(request.ToXml());

            xml.Sign(SignedXmlHelper.TestCert);

            var requestData = Convert.ToBase64String(Encoding.UTF8.GetBytes(xml.OuterXml));

            var httpRequest = new HttpRequestData(
                "POST",
                new Uri("http://something"),
                "/path",
                new KeyValuePair <string, IEnumerable <string> >[]
            {
                new KeyValuePair <string, IEnumerable <string> >("SAMLRequest", new[] { requestData })
            },
                null,
                null);

            var options = StubFactory.CreateOptions();

            options.SPOptions.MinIncomingSigningAlgorithm = SecurityAlgorithms.RsaSha384Signature;
            options.SPOptions.ServiceCertificates.Add(SignedXmlHelper.TestCert);

            CommandFactory.GetCommand(CommandFactory.LogoutCommandName)
            .Invoking(c => c.Run(httpRequest, options))
            .Should().Throw <InvalidSignatureException>()
            .WithMessage("*weak*");
        }