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();
        }
示例#4
0
        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.");
        }
示例#12
0
        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>();
        }
示例#14
0
        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");
        }
示例#15
0
        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");
        }
示例#17
0
        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");
        }
示例#18
0
        /// <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);
        }
示例#23
0
        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>();
        }
示例#25
0
        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();
        }
示例#26
0
        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);
        }
示例#29
0
        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);
        }
示例#30
0
        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"
            };
        }
示例#31
0
 /// <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();
 }
示例#32
0
 /// <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);
示例#33
0
 /// <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);
 }
示例#34
0
 /// <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);
 }
示例#35
0
 /// <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();
 }
示例#36
0
        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);
        }
示例#37
0
        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();
        }