public void KentorAuthServicesAuthenticationOptions_Ctor_IgnoresConfiguration()
        {
            var subject = new KentorAuthServicesAuthenticationOptions(false);

            subject.SPOptions.Should().BeNull();
            subject.IdentityProviders.IsEmpty.Should().BeTrue();
        }
        public void KentorAuthServicesAuthenticationOptions_Ctor_SetsDefault()
        {
            var subject = new KentorAuthServicesAuthenticationOptions(true);

            subject.Description.Caption.Should().Be(Constants.DefaultCaption);
            subject.AuthenticationMode.Should().Be(AuthenticationMode.Passive);
        }
Beispiel #3
0
        public void ConfigureAuth(IAppBuilder app)
        {
            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
            app.UseCookieAuthentication(new CookieAuthenticationOptions());
            var authServicesOptions = new KentorAuthServicesAuthenticationOptions(false)
            {
                SPOptions = CreateSPOptions()
                //SPOptions = new SPOptions
                //{
                //    EntityId = new EntityId(localMetaUri),
                //    ReturnUrl = returnUrl,
                //    WantAssertionsSigned = true
                //},
                //AuthenticationType = adfsType,
                //Caption = adfsType,
            };
            Uri metadataURI = new Uri(metaUri);
            var idp = new IdentityProvider(new EntityId(entityId), authServicesOptions.SPOptions)
            {
                AllowUnsolicitedAuthnResponse = true,
                Binding = Saml2BindingType.HttpRedirect,
                MetadataLocation = metadataURI.ToString(),
                LoadMetadata = true
            };
            //idp.SigningKeys.AddConfiguredKey(
            //    new X509Certificate2(
            //        HostingEnvironment.MapPath(
            //            "~/App_Data/AzureApp_signing.cer")));

            authServicesOptions.IdentityProviders.Add(idp);
            app.UseKentorAuthServicesAuthentication(authServicesOptions);
        }
        private static KentorAuthServicesAuthenticationOptions CreateAuthServicesOptions()
        {
            var spOptions = CreateSPOptions();
            var authServicesOptions = new KentorAuthServicesAuthenticationOptions(false)
            {
                SPOptions = spOptions
            };

            var idp = new IdentityProvider(new EntityId("http://stubidp.kentor.se/Metadata"), spOptions)
                {
                    AllowUnsolicitedAuthnResponse = true,
                    Binding = Saml2BindingType.HttpRedirect,
                    SingleSignOnServiceUrl = new Uri("http://stubidp.kentor.se")
                };

            idp.SigningKeys.AddConfiguredItem(
                new X509Certificate2(HostingEnvironment.MapPath("~/App_Data/Kentor.AuthServices.StubIdp.pfx")).PublicKey
                                                                                                              .Key);

            authServicesOptions.IdentityProviders.Add(idp);

            // It's enough to just create the federation and associate it
            // with the options. The federation will load the metadata and
            // update the options with any identity providers found.
            new Federation(new Uri("http://localhost:52071/Federation"), true, authServicesOptions);

            return authServicesOptions;
        }
        public void KentorAuthServicesAuthenticationOptions_SetsDefault()
        {
            var subject = new KentorAuthServicesAuthenticationOptions();

            subject.Description.Caption.Should().Be(Constants.DefaultCaption);
            subject.AuthenticationMode.Should().Be(AuthenticationMode.Passive);
            subject.MetadataPath.ToString().Should().Be("/AuthServices");
        }
        public void KentorAuthServicesAuthenticationExtensions_UseKentorAuthServicesAuthentication()
        {
            var app = Substitute.For<IAppBuilder>();

            var options = new KentorAuthServicesAuthenticationOptions();

            app.UseKentorAuthServicesAuthentication(options);

            app.Received().Use(typeof(KentorAuthServicesAuthenticationMiddleware), app, options);
        }
        public void KentorAuthServicesAuthenticationOptions_Caption()
        {
            var subject = new KentorAuthServicesAuthenticationOptions(false)
            {
                Caption = "MyCaption"
            };

            subject.Caption.Should().Be("MyCaption");
            subject.Description.Caption.Should().Be("MyCaption");
        }
        public void KentorAuthServicesAuthenticationOptions_Ctor_LoadsConfiguration()
        {
            var subject = new KentorAuthServicesAuthenticationOptions(true);

            subject.SPOptions.EntityId.Id.Should().Be("https://github.com/KentorIT/authservices");

            subject.IdentityProviders.IsEmpty.Should().BeFalse();
            subject.IdentityProviders[new EntityId("https://idp.example.com")]
                .SingleSignOnServiceUrl.Should().Be("https://idp.example.com/idp");
        }
        public void KentorAuthServicesAuthenticationOptions_Ctor_LoadsFederationFromConfigurationAndRegistersIdp()
        {
            var subject = new KentorAuthServicesAuthenticationOptions(true);

            Action a = () =>
            {
                var i = subject.IdentityProviders[new EntityId("http://idp.federation.example.com/metadata")];
            };

            a.ShouldNotThrow();
        }
        public void KentorAuthServicesAuthenticationMiddleware_CtorSetsDefaultAuthOption()
        {
            var options = new KentorAuthServicesAuthenticationOptions(true);

            options.SignInAsAuthenticationType.Should().BeNull();

            var middleware = new KentorAuthServicesAuthenticationMiddleware(new StubOwinMiddleware(0, null),
                CreateAppBuilder(), options);

            options.SignInAsAuthenticationType.Should().Be(DefaultSignInAsAuthenticationType);
        }
        /// <summary>
        /// Add Kentor AuthServices SAML2 authentication to the Owin pipeline.
        /// </summary>
        /// <param name="app">Owin pipeline builder.</param>
        /// <param name="options">Options for the middleware.</param>
        /// <returns></returns>
        public static IAppBuilder UseKentorAuthServicesAuthentication(this IAppBuilder app,
                                                                      KentorAuthServicesAuthenticationOptions options)
        {
            if (app == null)
            {
                throw new ArgumentNullException("app");
            }

            app.Use(typeof(KentorAuthServicesAuthenticationMiddleware), app, options);

            return(app);
        }
        /// <summary>
        /// Add Kentor AuthServices SAML2 authentication to the Owin pipeline.
        /// </summary>
        /// <param name="app">Owin pipeline builder.</param>
        /// <param name="options">Options for the middleware.</param>
        /// <returns></returns>
        public static IAppBuilder UseKentorAuthServicesAuthentication(this IAppBuilder app, 
            KentorAuthServicesAuthenticationOptions options)
        {
            if (app == null)
            {
                throw new ArgumentNullException("app");
            }

            app.Use(typeof(KentorAuthServicesAuthenticationMiddleware), app, options);

            return app;
        }
Beispiel #13
0
        private static KentorAuthServicesAuthenticationOptions CreateAuthServicesOptions()
        {
            var authServicesOptions = new KentorAuthServicesAuthenticationOptions(false)
            {
                SPOptions = new SPOptions { EntityId = new EntityId("urn:" + ConfigurationManager.AppSettings["auth0:ApplicationName"]), ReturnUrl = new Uri(ConfigurationManager.AppSettings["auth0:ReturnUrl"]) }
            };

            authServicesOptions.IdentityProviders.Add(new IdentityProvider(new EntityId("urn:" + ConfigurationManager.AppSettings["auth0:Domain"]), authServicesOptions.SPOptions)
                {
                    AllowUnsolicitedAuthnResponse = true,
                    MetadataUrl = new Uri(String.Format("https://{0}/samlp/metadata/{1}", ConfigurationManager.AppSettings["auth0:Domain"], ConfigurationManager.AppSettings["auth0:ClientId"])),
                    Binding = Saml2BindingType.HttpPost
                });
            return authServicesOptions;
        }
        public void Configuration(IAppBuilder app)
        {
            var authServicesOptions = new KentorAuthServicesAuthenticationOptions(false)
            {
                SPOptions = new SPOptions
                {
                    EntityId = new EntityId("http://sp.example.com")
                },

                SignInAsAuthenticationType = "External",
                AuthenticationType = "saml2p",
                Caption = "SAML2p"
            };
            authServicesOptions.IdentityProviders.Add(new IdentityProvider(new EntityId("http://stubidp.kentor.se/Metadata"), authServicesOptions.SPOptions)
            {
                LoadMetadata = true
            });

            var cors = new InMemoryCorsPolicyService(Clients.Get());
            var factory = new IdentityServerServiceFactory()
                            .UseInMemoryClients(Clients.Get())
                            .UseInMemoryScopes(Scopes.Get())
                            .UseInMemoryUsers(Users.Get());

            factory.CorsPolicyService = new Registration<ICorsPolicyService>(cors);

            var options = new IdentityServerOptions
            {
                Factory = factory,
                AuthenticationOptions = new AuthenticationOptions()
                {
                    IdentityProviders = (appBuilder, signInAsType) =>
                    {
                        Kentor.AuthServices.Configuration.Options.GlobalEnableSha256XmlSignatures();
                        app.UseKentorAuthServicesAuthentication(authServicesOptions);
                    }
                },
                LoggingOptions = new LoggingOptions()
                {
                    EnableHttpLogging = true,
                    EnableKatanaLogging = true,
                    EnableWebApiDiagnostics = true
                }
            };

            app.UseIdentityServer(options);
        }
        public void KentorAuthServicesAuthenticationMiddleware_Ctor_NullCheckOptionsSpOptionsEntityId()
        {
            var options = new KentorAuthServicesAuthenticationOptions(false)
            {
                SPOptions = new SPOptions()
            };

            Action a = () => new KentorAuthServicesAuthenticationMiddleware(
                new StubOwinMiddleware(404),
                CreateAppBuilder(),
                options);

            a.ShouldThrow<ConfigurationErrorsException>()
                .WithMessage("The SPOptions.EntityId property cannot be null. It must be set to the EntityId used to represent this system.");

        }
        public void KentorAuthServicesAuthenticationMiddleware_Ctor_NullCheckOptionsSpOptions()
        {
            var options = new KentorAuthServicesAuthenticationOptions(false);

            Action a = () => new KentorAuthServicesAuthenticationMiddleware(
                new StubOwinMiddleware(404),
                CreateAppBuilder(),
                options);

            a.ShouldThrow<ConfigurationErrorsException>()
                .WithMessage("The options.SPOptions property cannot be null. There is an implementation class Kentor.AuthServices.Configuration.SPOptions that you can instantiate. The EntityId property of that class is mandatory. It must be set to the EntityId used to represent this system.");
        }
        public async Task KentorAuthServicesAuthenticationMiddleware_DoesntAugmentsGeneratedClaimsWhenNameIdIsMissing()
        {
            var context = OwinTestHelpers.CreateOwinContext();

            string[] specifiedAuthTypes = null;

            context.Set<AuthenticateDelegate>("security.Authenticate",
                (authTypes, callback, state) =>
                {
                    specifiedAuthTypes = authTypes;
                    callback(new ClaimsIdentity(new Claim[]
                        {
                            new Claim(AuthServicesClaimTypes.SessionIndex, "SessionId", null, "http://idp.example.com"),
                            new Claim(ClaimTypes.Role, "SomeRole", null, "http://idp.example.com")
                        }, "Federation"),
                        new Dictionary<string, string>(),
                        new Dictionary<string, object>(),
                        state);
                    return Task.FromResult(0);
                });

            var options = new KentorAuthServicesAuthenticationOptions(true);

            var subject = new KentorAuthServicesAuthenticationMiddleware(
                new StubOwinMiddleware(303, grant: new AuthenticationResponseGrant(
                    new ClaimsIdentity(new Claim[]
                    {
                        new Claim(ClaimTypes.NameIdentifier, "ApplicationNameId")
                    }, "ApplicationIdentity"), new AuthenticationProperties())),
                CreateAppBuilder(),
                options);

            await subject.Invoke(context);

            specifiedAuthTypes.Should().HaveCount(1)
                .And.Subject.Single().Should().Be(DefaultSignInAsAuthenticationType);

            var expected = new ClaimsIdentity(new Claim[]
            {
                new Claim(ClaimTypes.NameIdentifier, "ApplicationNameId"),
            }, "ApplicationIdentity");

            context.Authentication.AuthenticationResponseGrant.Identity
                .ShouldBeEquivalentTo(expected, opt => opt.IgnoringCyclicReferences());
        }
        public async Task KentorAuthServicesAuthenticationMiddleware_LogoutsOnLogoutRequest()
        {
            var options = new KentorAuthServicesAuthenticationOptions(true);
            var subject = new KentorAuthServicesAuthenticationMiddleware(null, CreateAppBuilder(), options);

            var context = OwinTestHelpers.CreateOwinContext();

            var request = new Saml2LogoutRequest()
            {
                SessionIndex = "SessionId",
                DestinationUrl = new Uri("http://sp.example.com/AuthServices/Logout"),
                NameId = new Saml2NameIdentifier("NameId"),
                Issuer = new EntityId("https://idp.example.com"),
                SigningCertificate = SignedXmlHelper.TestCert
            };

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

            context.Request.Path = new PathString(url.AbsolutePath);
            context.Request.QueryString = new QueryString(url.Query.TrimStart('?'));

            await subject.Invoke(context);

            context.Response.StatusCode.Should().Be(303);
            context.Response.Headers["Location"].Should().StartWith("https://idp.example.com/logout?SAMLResponse");

            context.Authentication.AuthenticationResponseRevoke.Should().NotBeNull();
            context.Authentication.AuthenticationResponseRevoke.AuthenticationTypes
                .Should().BeEmpty();
        }
        public async Task KentorAuthServicesAuthenticationMiddleware_HandlesLogoutResponse()
        {
            var app = CreateAppBuilder();
            var options = new KentorAuthServicesAuthenticationOptions(true);
            var subject = new KentorAuthServicesAuthenticationMiddleware(
                null,
                app,
                options);

            var context = OwinTestHelpers.CreateOwinContext();

            var relayState = "MyRelayState";
            var response = new Saml2LogoutResponse(Saml2StatusCode.Success)
            {
                DestinationUrl = new Uri("https://sp.example.com/AuthServices/Logout"),
                RelayState = relayState,
                SigningCertificate = SignedXmlHelper.TestCert,
                Issuer = new EntityId("https://idp.example.com")
            };
            var requestUri = Saml2Binding.Get(Saml2BindingType.HttpRedirect).Bind(response).Location;

            var cookieData = HttpRequestData.EscapeBase64CookieValue(
                Convert.ToBase64String(
                    options.DataProtector.Protect(
                        Encoding.UTF8.GetBytes("http://loggedout.example.com/"))));
            context.Request.Headers["Cookie"] = $"Kentor.{relayState}={cookieData}";
            context.Request.Path = new PathString(requestUri.AbsolutePath);
            context.Request.QueryString = new QueryString(requestUri.Query.TrimStart('?'));
            
            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"));

            await subject.Invoke(context);

            context.Response.StatusCode.Should().Be(303);
            context.Response.Headers["Location"].Should().Be("http://loggedout.example.com/");
        }
        private async Task KentorAuthServicesAuthenticationMiddleware_CreatesRedirectOnAuthRevoke_PreservesRedirect(
            string location, string expectedUrl, string path = "/Account/LogOut")
        {
            var revoke = new AuthenticationResponseRevoke(new string[0]);

            var options = new KentorAuthServicesAuthenticationOptions(true);
            ((SPOptions)options.SPOptions).PublicOrigin = new Uri("https://sp.example.com/ExternalPath/");

            var subject = new KentorAuthServicesAuthenticationMiddleware(
                new StubOwinMiddleware(303, revoke: revoke),
                CreateAppBuilder(),
                options);

            var context = OwinTestHelpers.CreateOwinContext();
            context.Request.Scheme = "http";
            context.Request.Host = new HostString("sp-internal.example.com");
            context.Request.PathBase = new PathString("/AppPath");
            context.Request.Path = new PathString(path);
            context.Response.Headers["Location"] = location;

            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"));

            await subject.Invoke(context);

            var cookieValue = context.Response.Headers["Set-Cookie"].Split(';', '=')[1]
                .Replace('_', '/').Replace('-', '+').Replace('.', '=');

            var returnUrl = Encoding.UTF8.GetString(options.DataProtector.Unprotect(
                Convert.FromBase64String(cookieValue)));

            returnUrl.Should().Be(expectedUrl);
        }
        public async Task KentorAuthServicesAuthenticationMiddleware_DoesntRedirectOnUnspecifiedAuthRevoke_WhenPassiveAndStrictCompatibility()
        {
            var options = new KentorAuthServicesAuthenticationOptions(true)
            {
                AuthenticationMode = AuthenticationMode.Passive,
            };
            options.SPOptions.Compatibility.StrictOwinAuthenticationMode = true;

            var subject = new KentorAuthServicesAuthenticationMiddleware(
                new StubOwinMiddleware(200, revoke: new AuthenticationResponseRevoke(new string[0])),
                CreateAppBuilder(),
                options);

            var context = OwinTestHelpers.CreateOwinContext();

            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"));

            await subject.Invoke(context);

            context.Response.StatusCode.Should().Be(200);
        }
        private void ConfigureIdentityProviders(IAppBuilder app, string signInAsType)
        {
            var authServicesOptions = new KentorAuthServicesAuthenticationOptions(false)
            {
                SPOptions = new SPOptions
                {
                    EntityId = new EntityId("https://localhost:44300/identity/AuthServices")
                },
                SignInAsAuthenticationType = signInAsType,
                AuthenticationType = "okta",
                Caption = "Okta"
            };

            authServicesOptions.IdentityProviders.Add(new IdentityProvider(
                new EntityId("http://www.okta.com/exk5dcmpavv9xKCZC0h7"), authServicesOptions.SPOptions)
            {
                LoadMetadata = true,
                MetadataUrl = new Uri("https://dev-169318.oktapreview.com/app/exk5dcmpavv9xKCZC0h7/sso/saml/metadata"),
                AllowUnsolicitedAuthnResponse = true
            });

            app.UseKentorAuthServicesAuthentication(authServicesOptions);

            app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions
            {
                AuthenticationType = "Google",
                Caption = "Sign-in with Google",
                SignInAsAuthenticationType = signInAsType,

                ClientId = "297503349559-dmgmcoqfpkr7kr93e3kh0kj4gfrigbgf.apps.googleusercontent.com",
                ClientSecret = "hllqf-f_5xvozZnG9YRvOfo1"
            });
        }
Beispiel #23
0
        private void ConfigureSaml2(IAppBuilder app, string signInAsType)
        {
            var options = new KentorAuthServicesAuthenticationOptions(false)
            {
                SPOptions = new SPOptions
                {
                    EntityId = new EntityId("http://localhost:4589/IdSrv3/AuthServices"),
                },
                SignInAsAuthenticationType = signInAsType,
                Caption = "SAML2p"
            };

            UseIdSrv3LogoutOnFederatedLogout(app, options);

            options.SPOptions.SystemIdentityModelIdentityConfiguration.AudienceRestriction.AudienceMode
                = AudienceUriMode.Never;

            options.SPOptions.ServiceCertificates.Add(new X509Certificate2(
                AppDomain.CurrentDomain.SetupInformation.ApplicationBase + "/App_Data/Kentor.AuthServices.Tests.pfx"));

            options.IdentityProviders.Add(new IdentityProvider(
                new EntityId("http://localhost:52071/Metadata"),
                options.SPOptions)
            {
                LoadMetadata = true
            });

            app.UseKentorAuthServicesAuthentication(options);
        }
        public void KentorAuthServicesAuthenticationOptions_Ctor_LoadsIdpFromConfiguration()
        {
            var subject = new KentorAuthServicesAuthenticationOptions(true);

            subject.IdentityProviders.Default.EntityId.Id.Should().Be("https://idp.example.com");
        }
        public async Task KentorAuthServicesAuthenticationMiddleware_CreatesRedirectOnAuthRevoke()
        {
            var revoke = new AuthenticationResponseRevoke(new string[0]);

            var options = new KentorAuthServicesAuthenticationOptions(true);
            ((SPOptions)options.SPOptions).PublicOrigin = new Uri("https://sp.example.com/ExternalPath/");

            var subject = new KentorAuthServicesAuthenticationMiddleware(
                new StubOwinMiddleware(200, revoke: revoke),
                CreateAppBuilder(),
                options);

            var context = OwinTestHelpers.CreateOwinContext();
            context.Request.Scheme = "http";
            context.Request.Host = new HostString("sp-internal.example.com");
            context.Request.PathBase = new PathString("/InternalPath");
            context.Request.Path = new PathString("/LoggedOut");

            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"));

            await subject.Invoke(context);

            context.Response.StatusCode.Should().Be(303);
            context.Response.Headers["Location"].Should().StartWith("https://idp.example.com/logout?SAMLRequest");
            var returnUrl = ExtractRequestState(options.DataProtector, context).ReturnUrl;

            returnUrl.Should().Be("https://sp.example.com/ExternalPath/LoggedOut");
        }
        public async Task KentorAuthServicesAuthenticationMiddleware_StoresAuthenticationProperties()
        {
            var returnUrl = "http://sp.example.com/returnurl";

            var prop = new AuthenticationProperties()
            {
                RedirectUri = returnUrl
            };
            prop.Dictionary["test"] = "SomeValue";

            var options = new KentorAuthServicesAuthenticationOptions(true);
            var middleware = new KentorAuthServicesAuthenticationMiddleware(
                new StubOwinMiddleware(401,
                    new AuthenticationResponseChallenge(
                        new string[] { "KentorAuthServices" }, prop)),
                CreateAppBuilder(),
                options);

            var context = OwinTestHelpers.CreateOwinContext();

            await middleware.Invoke(context);

            var storedAuthnData = ExtractRequestState(options.DataProtector, context);

            new AuthenticationProperties(storedAuthnData.RelayData).Dictionary["test"].Should().Be("SomeValue");
        }
        public async Task KentorAuthServicesAuthenticationMiddleware_SignInUrlRedirectsToIdp()
        {
            var context = OwinTestHelpers.CreateOwinContext();
            context.Request.Host = new HostString("localhost");
            var signinPath = "/AuthServices/SignIn";
            context.Request.Path = new PathString(signinPath);
            context.Request.QueryString = new QueryString("ReturnUrl=%2FHome&idp=https%3A%2F%2Fidp2.example.com");

            var options = new KentorAuthServicesAuthenticationOptions(true);
            var middleware = new KentorAuthServicesAuthenticationMiddleware(
                null, CreateAppBuilder(), options);

            await middleware.Invoke(context);

            context.Response.StatusCode.Should().Be(303);
            context.Response.Headers["Location"].Should().StartWith("https://idp2.example.com/idp?SAMLRequest");

            var relayState = ExtractRelayState(context);

            var storedAuthnData = ExtractRequestState(options.DataProtector, context);

            storedAuthnData.ReturnUrl.Should().Be("http://localhost/Home");
        }
Beispiel #28
0
        private void UseIdSrv3LogoutOnFederatedLogout(IAppBuilder app, KentorAuthServicesAuthenticationOptions options)
        {
            app.Map("/signoutcleanup", cleanup =>
            {
                cleanup.Run(async ctx =>
                {
                    await ctx.Environment.ProcessFederatedSignoutAsync();
                });
            });

            app.Use(async (context, next) =>
            {
                await next.Invoke();

                if (context.Authentication.AuthenticationResponseRevoke != null
                    && context.Response.StatusCode % 100 == 3
                    && !HttpContext.Current.Response.HeadersWritten)
                {
                    var finalLocation = context.Response.Headers["Location"];

                    context.Response.StatusCode = 200;

                    await context.Response.WriteAsync($@"
            <html>
            <body>
            <h1>Signing Out...<span id=""dots""></span></h1>
            <iframe style=""display:none;"" src=""../signoutcleanup""></iframe>
            <script>
            setInterval(function() {{ var dots = document.getElementById(""dots""); dots.innerText = dots.innerText + "".""; }}, 250);
            setTimeout(function() {{ window.location = ""{finalLocation}""; }}, 5000);
            </script>
            </body>
            </html>");
                }
            });
        }
        public async Task KentorAuthServicesAuthenticationMiddleware_CreatesRedirectOnAuthRevoke_UsesAuthPropsReturnUrl()
        {
            var authPropsReturnUrl = "http://sp.exmample.com/AuthPropsLogout";

            var revoke = new AuthenticationResponseRevoke(
                new string[0],
                new AuthenticationProperties { RedirectUri = authPropsReturnUrl });

            var options = new KentorAuthServicesAuthenticationOptions(true);
            options.SPOptions.PublicOrigin = new Uri("https://sp.example.com/ExternalPath/");

            var subject = new KentorAuthServicesAuthenticationMiddleware(
                new StubOwinMiddleware(303, revoke: revoke),
                CreateAppBuilder(),
                options);

            var context = OwinTestHelpers.CreateOwinContext();
            context.Response.Headers["Location"] = "http://sp.example.com/locationHeader";
            context.Request.User = new ClaimsPrincipal(
                new ClaimsIdentity(new Claim[]
                {
                    new Claim(AuthServicesClaimTypes.LogoutNameIdentifier, ",,,,NameId", null, "https://idp.example.com"),
                    new Claim(AuthServicesClaimTypes.SessionIndex, "SessionId", null, "https://idp.example.com")
                }, "Federation"));

            await subject.Invoke(context);

            var cookieValue = context.Response.Headers["Set-Cookie"].Split(';', '=')[1];

            var returnUrl = new StoredRequestState(options.DataProtector.Unprotect(
                HttpRequestData.GetBinaryData(cookieValue))).ReturnUrl;

            returnUrl.Should().Be(authPropsReturnUrl);
        }
        public async Task KentorAuthServicesAuthenticationMiddleware_RedirectRemembersReturnPath()
        {
            var returnUrl = "http://sp.example.com/returnurl";

            var options = new KentorAuthServicesAuthenticationOptions(true);
            var subject = new KentorAuthServicesAuthenticationMiddleware(
                new StubOwinMiddleware(401, new AuthenticationResponseChallenge(
                    new string[] { "KentorAuthServices" }, new AuthenticationProperties()
                    {
                        RedirectUri = returnUrl
                    })),
                    CreateAppBuilder(), options);

            var context = OwinTestHelpers.CreateOwinContext();

            await subject.Invoke(context);

            var storedState = ExtractRequestState(options.DataProtector, context);

            storedState.ReturnUrl.Should().Be(returnUrl);
        }
        public async Task KentorAuthServicesAuthenticationMiddleware_LogoutRequest_HonorsCommandResultHandled()
        {
            var options = new KentorAuthServicesAuthenticationOptions(true)
            {
                Notifications = new KentorAuthServicesNotifications
                {
                    LogoutCommandResultCreated = cr =>
                    {
                        cr.HandledResult = true;
                    }
                }
            };

            var subject = new KentorAuthServicesAuthenticationMiddleware(null, CreateAppBuilder(), options);

            var context = OwinTestHelpers.CreateOwinContext();

            var request = new Saml2LogoutRequest()
            {
                SessionIndex = "SessionId",
                DestinationUrl = new Uri("http://sp.example.com/AuthServices/Logout"),
                NameId = new Saml2NameIdentifier("NameId"),
                Issuer = new EntityId("https://idp.example.com"),
                SigningCertificate = SignedXmlHelper.TestCert
            };

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

            context.Request.Path = new PathString(url.AbsolutePath);
            context.Request.QueryString = new QueryString(url.Query.TrimStart('?'));

            await subject.Invoke(context);

            context.Response.StatusCode.Should().Be(200);
        }