public void HttpRequestData_Ctor_Deserialize_StoredRequestState() { var url = new Uri("http://example.com:42/ApplicationPath/Path?RelayState=Foo"); string appPath = "/ApplicationPath"; var storedRequestData = new StoredRequestState( new EntityId("http://idp.example.com"), new Uri("http://sp.example.com/loggedout"), new Saml2Id("id123"), null); var cookies = new KeyValuePair<string, string>[] { new KeyValuePair<string, string>( "Kentor.Foo", HttpRequestData.ConvertBinaryData( StubDataProtector.Protect(storedRequestData.Serialize()))) }; var subject = new HttpRequestData( "GET", url, appPath, Enumerable.Empty<KeyValuePair<string, string[]>>(), cookies, StubDataProtector.Unprotect); subject.StoredRequestState.ShouldBeEquivalentTo(storedRequestData); }
public override UnbindResult Unbind(HttpRequestData request, IOptions options) { if (request == null) { throw new ArgumentNullException(nameof(request)); } var xmlDoc = new XmlDocument() { PreserveWhitespace = true }; string encodedMessage; if (!request.Form.TryGetValue("SAMLResponse", out encodedMessage)) { encodedMessage = request.Form["SAMLRequest"]; } xmlDoc.LoadXml(Encoding.UTF8.GetString(Convert.FromBase64String(encodedMessage))); string relayState = null; request.Form.TryGetValue("RelayState", out relayState); return new UnbindResult(xmlDoc.DocumentElement, relayState, TrustLevel.None); }
public void Saml2ArtifactBinding_Unbind_FromGet() { var issuer = new EntityId("https://idp.example.com"); var artifact = Uri.EscapeDataString( Convert.ToBase64String( Saml2ArtifactBinding.CreateArtifact(issuer, 0x1234))); var relayState = MethodBase.GetCurrentMethod().Name; PrepareArtifactState(relayState, issuer); var r = new HttpRequestData( "GET", new Uri($"http://example.com/path/acs?SAMLart={artifact}&RelayState={relayState}")); StubServer.LastArtifactResolutionSoapActionHeader = null; var result = Saml2Binding.Get(Saml2BindingType.Artifact).Unbind(r, StubFactory.CreateOptions()); var xmlDocument = new XmlDocument() { PreserveWhitespace = true }; xmlDocument.LoadXml("<message> <child-node /> </message>"); var expected = new UnbindResult(xmlDocument.DocumentElement, relayState, TrustLevel.None); result.ShouldBeEquivalentTo(expected); StubServer.LastArtifactResolutionSoapActionHeader.Should().Be( "http://www.oasis-open.org/committees/security"); StubServer.LastArtifactResolutionWasSigned.Should().BeFalse(); }
public static CommandResult Run( HttpRequestData request, string returnPath, IOptions options) { if (request == null) { throw new ArgumentNullException(nameof(request)); } if (options == null) { throw new ArgumentNullException(nameof(options)); } var binding = Saml2Binding.Get(request); if (binding != null) { var unbindResult = binding.Unbind(request, options); VerifyMessageIsSigned(unbindResult, options); switch (unbindResult.Data.LocalName) { case "LogoutRequest": return HandleRequest(unbindResult, options); case "LogoutResponse": return HandleResponse(unbindResult, request); default: throw new NotImplementedException(); } } return InitiateLogout(request, returnPath, options); }
public override UnbindResult Unbind(HttpRequestData request, IOptions options) { if (request == null) { throw new ArgumentNullException(nameof(request)); } var payload = Convert.FromBase64String(request.QueryString["SAMLRequest"].First()); using (var compressed = new MemoryStream(payload)) { using (var decompressedStream = new DeflateStream(compressed, CompressionMode.Decompress, true)) { using (var deCompressed = new MemoryStream()) { decompressedStream.CopyTo(deCompressed); var xml = new XmlDocument() { PreserveWhitespace = true }; xml.LoadXml(Encoding.UTF8.GetString(deCompressed.GetBuffer())); return new UnbindResult( xml.DocumentElement, request.QueryString["RelayState"].SingleOrDefault()); } } } }
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); ((SPOptions)(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. SetCookieData = "https://sp.example.com/" }; actual.ShouldBeEquivalentTo(expected, opt => opt .Excluding(cr => cr.Location) .Excluding(cr => cr.SetCookieName)); 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 HttpRequestBaseExtensions_ToHttpRequestData() { var url = new Uri("http://example.com:42/ApplicationPath/Path?RelayState=SomeState"); string appPath = "/ApplicationPath"; var request = Substitute.For<HttpRequestBase>(); request.HttpMethod.Returns("GET"); request.Url.Returns(url); request.Form.Returns(new NameValueCollection { { "Key", "Value" } }); request.ApplicationPath.Returns(appPath); var cookieValue = HttpRequestData.ConvertBinaryData( MachineKey.Protect( new StoredRequestState(null, new Uri("urn:someUri"), null, null).Serialize(), HttpRequestBaseExtensions.ProtectionPurpose)); request.Cookies.Returns(new HttpCookieCollection()); request.Cookies.Add(new HttpCookie("Kentor.SomeState", cookieValue)); var actual = request.ToHttpRequestData(); var expected = new HttpRequestData( "GET", url, appPath, new KeyValuePair<string, string[]>[] { new KeyValuePair<string, string[]>("Key", new string[] { "Value" }) }, Enumerable.Empty<KeyValuePair<string, string>>(), null); actual.ShouldBeEquivalentTo(expected, opt => opt.Excluding(s => s.StoredRequestState)); actual.StoredRequestState.ReturnUrl.AbsoluteUri.Should().Be("urn:someUri"); }
public void HttpRequestBaseExtensions_ToHttpRequestData() { var url = new Uri("http://example.com:42/ApplicationPath/Path?RelayState=SomeState"); string appPath = "/ApplicationPath"; var request = Substitute.For<HttpRequestBase>(); request.HttpMethod.Returns("GET"); request.Url.Returns(url); request.Form.Returns(new NameValueCollection { { "Key", "Value" } }); request.ApplicationPath.Returns(appPath); var cookieValue = HttpRequestData.EscapeBase64CookieValue(Convert.ToBase64String( MachineKey.Protect(Encoding.UTF8.GetBytes("CookieValue"), "Kentor.AuthServices"))); request.Cookies.Returns(new HttpCookieCollection()); request.Cookies.Add(new HttpCookie("Kentor.SomeState", cookieValue)); var subject = request.ToHttpRequestData(); var expected = new HttpRequestData( "GET", url, appPath, new KeyValuePair<string, string[]>[] { new KeyValuePair<string, string[]>("Key", new string[] { "Value" }) }, Enumerable.Empty<KeyValuePair<string, string>>(), null); subject.ShouldBeEquivalentTo(expected, opt => opt.Excluding(s => s.CookieData)); subject.CookieData.Should().Be("CookieValue"); }
public void MetadataCommand_Run_CallsNotifications() { var request = new HttpRequestData("GET", new Uri("http://localhost/AuthServices")); var options = StubFactory.CreateOptions(); options.Notifications.MetadataCreated = (md, urls) => { md.CacheDuration = new TimeSpan(0, 0, 17); urls.ApplicationUrl.Host.Should().Be("localhost"); }; CommandResult notifiedCommandResult = null; options.Notifications.MetadataCommandResultCreated = cr => { notifiedCommandResult = cr; }; var subject = new MetadataCommand(); var actualCommandResult = subject.Run(request, options); actualCommandResult.Should().BeSameAs(notifiedCommandResult); var parsedResult = XElement.Parse(actualCommandResult.Content); parsedResult.Attribute("cacheDuration").Value .Should().Be("PT17S"); }
public CommandResult Run(HttpRequestData request, IOptions options) { return new CommandResult() { HttpStatusCode = HttpStatusCode.NotFound }; }
public void AcsCommand_Run_CallsNotifications() { var messageId = MethodBase.GetCurrentMethod().Name; 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 = """ + messageId + @""" Version=""2.0"" IssueInstant=""2013-01-01T00:00:00Z""> <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=""" + messageId + @"_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 requestData = new HttpRequestData( "POST", new Uri("http://localhost"), "/ModulePath", new KeyValuePair<string, string[]>[] { new KeyValuePair<string, string[]>("SAMLResponse", new string[] { formValue }) }, null); var options = StubFactory.CreateOptions(); var responseUnboundCalled = false; options.Notifications.MessageUnbound = ur => { ur.Should().NotBeNull(); responseUnboundCalled = true; }; CommandResult notifiedCommandResult = null; options.Notifications.AcsCommandResultCreated = (cr, r) => { notifiedCommandResult = cr; r.Id.Value.Should().Be(messageId); }; new AcsCommand().Run(requestData, options) .Should().BeSameAs(notifiedCommandResult); responseUnboundCalled.Should().BeTrue("the ResponseUnbound notification should have been called."); }
public CommandResult Run(HttpRequestData request, IOptions options) { if(request == null) { throw new ArgumentNullException(nameof(request)); } if(options == null) { throw new ArgumentNullException(nameof(options)); } var binding = Saml2Binding.Get(request); if (binding != null) { UnbindResult unbindResult = null; try { unbindResult = binding.Unbind(request, options); var samlResponse = new Saml2Response(unbindResult.Data, request.StoredRequestState?.MessageId); var result = ProcessResponse(options, samlResponse, request.StoredRequestState); if(unbindResult.RelayState != null) { result.ClearCookieName = "Kentor." + unbindResult.RelayState; } return result; } catch (FormatException ex) { throw new BadFormatSamlResponseException( "The SAML Response did not contain valid BASE64 encoded data.", ex); } catch (XmlException ex) { var newEx = new BadFormatSamlResponseException( "The SAML response contains incorrect XML", ex); // Add the payload to the exception if (unbindResult != null) { newEx.Data["Saml2Response"] = unbindResult.Data.OuterXml; } throw newEx; } catch (Exception ex) { if (unbindResult != null) { // Add the payload to the existing exception ex.Data["Saml2Response"] = unbindResult.Data.OuterXml; } throw; } } throw new NoSamlResponseFoundException(); }
public void Saml2Binding_Get_ReturnsSaml2Artifact_ForArtifactInUrl() { var r = new HttpRequestData( "GET", new Uri("http://example.com/ModulePath/Acs?SAMLart=ABCD")); Saml2Binding.Get(r).Should().BeOfType<Saml2ArtifactBinding>(); }
public void SignInCommand_Run_With_InvalidIdp_ThrowsException() { var request = new HttpRequestData("GET", new Uri("http://localhost/signin?idp=no-such-idp-in-config")); Action a = () => new SignInCommand().Run(request, Options.FromConfiguration); a.ShouldThrow<InvalidOperationException>().WithMessage("Unknown idp"); }
public CommandResult Run(HttpRequestData request, IOptions options) { if(request == null) { throw new ArgumentNullException("request"); } if(options == null) { throw new ArgumentNullException("options"); } var binding = Saml2Binding.Get(request); if (binding != null) { string unpackedPayload = null; try { unpackedPayload = binding.Unbind(request); var samlResponse = Saml2Response.Read(unpackedPayload); var relayStates = request.Form.First(x => string.Compare(x.Key, "RelayState", StringComparison.OrdinalIgnoreCase) == 0); string returnURL = string.Empty; returnURL = relayStates.Value; /* foreach(var state in relayStates) { returnURL = state; break; } */ return ProcessResponse(options, samlResponse, returnURL); } catch (FormatException ex) { throw new BadFormatSamlResponseException( "The SAML Response did not contain valid BASE64 encoded data.", ex); } catch (XmlException ex) { var newEx = new BadFormatSamlResponseException( "The SAML response contains incorrect XML", ex); // Add the payload to the exception newEx.Data["Saml2Response"] = unpackedPayload; throw newEx; } catch (Exception ex) { // Add the payload to the existing exception ex.Data["Saml2Response"] = unpackedPayload; throw; } } throw new NoSamlResponseFoundException(); }
protected internal override bool CanUnbind(HttpRequestData request) { if (request == null) { throw new ArgumentNullException(nameof(request)); } return request.HttpMethod == "POST" && request.Form.Keys.Contains("SAMLResponse"); }
public void SignInCommand_Run_MapsReturnUrl() { var defaultDestination = Options.FromConfiguration.IdentityProviders.Default.SingleSignOnServiceUrl; var httpRequest = new HttpRequestData("GET", new Uri("http://localhost/signin?ReturnUrl=%2FReturn.aspx")); var actual = new SignInCommand().Run(httpRequest, Options.FromConfiguration); actual.RequestState.ReturnUrl.Should().Be("http://localhost/Return.aspx"); }
/// <summary> /// Run the command, initiating or handling the logout sequence. /// </summary> /// <param name="request">Request data.</param> /// <param name="options">Options</param> /// <returns>CommandResult</returns> public CommandResult Run(HttpRequestData request, IOptions options) { if(request == null) { throw new ArgumentNullException(nameof(request)); } var returnUrl = request.QueryString["ReturnUrl"].SingleOrDefault(); return Run(request, returnUrl, options); }
public void Saml2RedirectBinding_Unbind_WithoutRelayStateAndSignature() { var request = new HttpRequestData("GET", new Uri("http://localhost?SAMLRequest=" + ExampleSerializedData)); var result = Saml2Binding.Get(Saml2BindingType.HttpRedirect).Unbind(request, null); var expectedXml = XmlHelpers.FromString(ExampleXmlData).DocumentElement; result.RelayState.Should().Be(null); result.Data.Should().BeEquivalentTo(expectedXml); result.TrustLevel.Should().Be(TrustLevel.None); }
public void SignInCommand_Run_PublicOrigin() { var options = StubFactory.CreateOptionsPublicOrigin(new Uri("https://my.public.origin:8443")); var idp = options.IdentityProviders.Default; var request = new HttpRequestData("GET", new Uri("http://sp.example.com?idp=" + Uri.EscapeDataString(idp.EntityId.Id))); var subject = new SignInCommand().Run(request, Options.FromConfiguration); subject.Location.Host.Should().Be(new Uri("https://idp.example.com").Host); }
public override string Unbind(HttpRequestData request) { if (request == null) { throw new ArgumentNullException(nameof(request)); } var xml = Encoding.UTF8.GetString( Convert.FromBase64String(request.Form["SAMLResponse"])); return xml; }
public void SignInCommand_Run_With_Idp2_ReturnsAuthnRequestForSecondIdp() { var secondIdp = Options.FromConfiguration.IdentityProviders[1]; var secondDestination = secondIdp.SingleSignOnServiceUrl; var secondEntityId = secondIdp.EntityId; var request = new HttpRequestData("GET", new Uri("http://sp.example.com?idp=" + Uri.EscapeDataString(secondEntityId.Id))); var subject = new SignInCommand().Run(request, Options.FromConfiguration); subject.Location.Host.Should().Be(secondDestination.Host); }
public void Saml2Binding_Get_ReturnsSamlArtifact_ForArtifactInPost() { var r = new HttpRequestData( "POST", new Uri("http://example.com/ModulePath"), "/ModulePath", new KeyValuePair<string, string[]>[] { new KeyValuePair<string, string[]>("SAMLart", new string[] { "Some Data" }) }); Saml2Binding.Get(r).Should().BeOfType<Saml2ArtifactBinding>(); }
public void Saml2Binding_Get_ReturnsSaml2Postbinding() { var r = new HttpRequestData( "POST", new Uri("http://example.com"), "/ModulePath", new KeyValuePair<string, string[]>[] { new KeyValuePair<string, string[]>("SAMLResponse", new string[] { "Some Data" }) }); Saml2Binding.Get(r).Should().BeOfType<Saml2PostBinding>(); }
public void Saml2Binding_Get_NullOnGetWithSamlResponseBody() { var r = new HttpRequestData( "GET", new Uri("http://example.com"), "/ModulePath", new KeyValuePair<string, string[]>[] { new KeyValuePair<string, string[]>("SAMLResponse", new string[] { "Some Data" }) }); Saml2Binding.Get(r).Should().BeNull(); }
public AuthServicesUrls(HttpRequestData request, ISPOptions spOptions) { if (request == null) { throw new ArgumentNullException(nameof(request)); } if (spOptions == null) { throw new ArgumentNullException(nameof(spOptions)); } Init(request.ApplicationUrl, spOptions); }
public void Saml2RedirectBinding_Unbind_WithoutRelayState() { var request = new HttpRequestData("GET", new Uri("http://localhost?SAMLRequest=" + ExampleSerializedData)); var result = Saml2Binding.Get(Saml2BindingType.HttpRedirect).Unbind(request); var expected = new { Data = ExampleXmlData, RelayState = (string)null }; result.ShouldBeEquivalentTo(expected); }
public override UnbindResult Unbind(HttpRequestData request) { if (request == null) { throw new ArgumentNullException(nameof(request)); } var data = Encoding.UTF8.GetString(Convert.FromBase64String(request.Form["SAMLResponse"])); string relayState = null; request.Form.TryGetValue("RelayState", out relayState); return new UnbindResult(data, relayState); }
public AuthServicesUrls(HttpRequestData request, ISPOptions spOptions) { if (request == null) { throw new ArgumentNullException("request"); } if (spOptions == null) { throw new ArgumentNullException("spOptions"); } Init(request.ApplicationUrl, spOptions.ModulePath); }
public CommandResult Run(HttpRequestData request, IOptions options) { if(options == null) { throw new ArgumentNullException(nameof(options)); } var urls = new AuthServicesUrls(request, options.SPOptions); return new CommandResult() { Content = options.SPOptions.CreateMetadata(urls).ToXmlString(), ContentType = "application/samlmetadata+xml" }; }
/// <summary> /// Extracts a message out of the current HttpRequest. /// </summary> /// <param name="request">Current HttpRequest.</param> /// <param name="options">Options, used to look up certificate information /// in bindings that validate signatures. If set to null, the returned /// result will have TrustLevel.None.</param> /// <returns>Extracted message.</returns> public virtual UnbindResult Unbind(HttpRequestData request, IOptions options) { throw new NotImplementedException(); }
/// <summary> /// Checks if the binding can extract a message out of the current /// http request. /// </summary> /// <param name="request">HttpRequest to check for message.</param> /// <returns>True if the binding supports the current request.</returns> protected internal abstract bool CanUnbind(HttpRequestData request);
/// <summary> /// Checks if the binding can extract a message out of the current /// http request. /// </summary> /// <param name="request">HttpRequest to check for message.</param> /// <returns>True if the binding supports the current request.</returns> protected internal virtual bool CanUnbind(HttpRequestData request) { return(false); }
/// <summary> /// Get a cached binding instance that can handle the current request. /// </summary> /// <param name="request">Current HttpRequest</param> /// <returns>A derived class instance that supports the requested binding, /// or null if no binding supports the current request.</returns> public static Saml2Binding Get(HttpRequestData request) { return(bindings.FirstOrDefault(b => b.Value.CanUnbind(request)).Value); }
/// <summary> /// Extracts a message out of the current HttpRequest. /// </summary> /// <param name="request">Current HttpRequest.</param> /// <returns>Extracted message.</returns> public virtual string Unbind(HttpRequestData request) { throw new NotImplementedException(); }
private static CommandResult InitiateLogout(HttpRequestData request, Uri returnUrl, IOptions options) { string idpEntityId = null; Claim sessionIndexClaim = null; if (request.User != null) { idpEntityId = request.User.FindFirst(AuthServicesClaimTypes.LogoutNameIdentifier)?.Issuer; sessionIndexClaim = request.User.FindFirst(AuthServicesClaimTypes.SessionIndex); } IdentityProvider idp; var knownIdp = options.IdentityProviders.TryGetValue(new EntityId(idpEntityId), out idp); options.SPOptions.Logger.WriteVerbose("Initiating logout, checking requirements for federated logout" + "\n Issuer of LogoutNameIdentifier claim (should be Idp entity id): " + idpEntityId + "\n Issuer is a known Idp: " + knownIdp + "\n Session index claim (should have a value): " + sessionIndexClaim + "\n Idp has SingleLogoutServiceUrl: " + idp?.SingleLogoutServiceUrl?.OriginalString + "\n There is a signingCertificate in SPOptions: " + (options.SPOptions.SigningServiceCertificate != null) + "\n Idp configured to DisableOutboundLogoutRequests (should be false): " + idp?.DisableOutboundLogoutRequests); CommandResult commandResult; if (idpEntityId != null && knownIdp && sessionIndexClaim != null && idp.SingleLogoutServiceUrl != null && options.SPOptions.SigningServiceCertificate != null && !idp.DisableOutboundLogoutRequests) { var logoutRequest = idp.CreateLogoutRequest(request.User); commandResult = Saml2Binding.Get(idp.SingleLogoutServiceBinding) .Bind(logoutRequest); commandResult.RelayState = logoutRequest.RelayState; commandResult.RequestState = new StoredRequestState( idp.EntityId, returnUrl, logoutRequest.Id, null); if (!options.SPOptions.Compatibility.DisableLogoutStateCookie) { commandResult.SetCookieName = "Kentor." + logoutRequest.RelayState; } options.SPOptions.Logger.WriteInformation("Sending logout request to " + idp.EntityId.Id); } else { commandResult = new CommandResult { HttpStatusCode = HttpStatusCode.SeeOther, Location = returnUrl }; options.SPOptions.Logger.WriteInformation("Doing a local only logout."); } commandResult.TerminateLocalSession = true; return(commandResult); }
public CommandResult Run(HttpRequestData request, IOptions options) { if (request == null) { throw new ArgumentNullException("request"); } if (options == null) { throw new ArgumentNullException("options"); } var binding = options.Notifications.GetBinding(request); if (binding != null) { UnbindResult unbindResult = null; try { unbindResult = binding.Unbind(request, options); options.Notifications.MessageUnbound(unbindResult); var samlResponse = new Saml2Response(unbindResult.Data, request.StoredRequestState == null?null:request.StoredRequestState.MessageId); var result = ProcessResponse(options, samlResponse, request.StoredRequestState); if (unbindResult.RelayState != null) { result.ClearCookieName = "Kentor." + unbindResult.RelayState; } options.Notifications.AcsCommandResultCreated(result, samlResponse); return(result); } catch (FormatException ex) { throw new BadFormatSamlResponseException( "The SAML Response did not contain valid BASE64 encoded data.", ex); } catch (XmlException ex) { var newEx = new BadFormatSamlResponseException( "The SAML response contains incorrect XML", ex); // Add the payload to the exception if (unbindResult != null) { newEx.Data["Saml2Response"] = unbindResult.Data.OuterXml; } throw newEx; } catch (Exception ex) { if (unbindResult != null) { // Add the payload to the existing exception ex.Data["Saml2Response"] = unbindResult.Data.OuterXml; } throw; } } throw new NoSamlResponseFoundException(); }