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); }
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*"); }
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); }
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(); }
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*"); }
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); }
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); }
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"); }
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); }
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*"); }
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(); }
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."); }
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(); }
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(); }
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"); }
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"); }
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"); }
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); }
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*"); }
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(); }
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); }
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); }
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"); }
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(); }
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); }
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(); }
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"); }
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*"); }