예제 #1
0
        /// <summary>
        /// 一句配置Session和登陆Cookie
        /// 需在Configure中加入 app.UseAuthentication() 以使得登陆配置生效
        /// </summary>
        /// <param name="services"></param>
        /// <param name="sessionTimeOutHours">Session过期回收时间(默认2小时)</param>
        /// <param name="loginPath">用户登陆路径</param>
        /// <param name="accessDeniedPath">禁止访问路径,不设置则回到登陆页</param>
        /// <param name="returnUrlParameter">上一页面地址回传参数</param>
        /// <param name="cookieDomain">Cookie作用域</param>
        /// <param name="securePolicy">Cookie安全策略</param>
        /// <returns></returns>
        public static IServiceCollection AddSessionAndCookie(this IServiceCollection services,
                                                             double sessionTimeOutHours      = 2,
                                                             string loginPath                = "/Account/Login",
                                                             string accessDeniedPath         = null,
                                                             string returnUrlParameter       = "ReturnUrl",
                                                             string cookieDomain             = null,
                                                             CookieSecurePolicy securePolicy = CookieSecurePolicy.SameAsRequest)
        {
            services.AddMemoryCache();
            services
            .AddSession(options =>
            {
                var cookie          = options.Cookie;
                cookie.HttpOnly     = true;
                cookie.SecurePolicy = securePolicy;
                options.IdleTimeout = TimeSpan.FromHours(sessionTimeOutHours);
            })
            .AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
            {
                options.LoginPath          = new PathString(loginPath);
                options.ReturnUrlParameter = returnUrlParameter;
                options.AccessDeniedPath   = new PathString(accessDeniedPath ?? loginPath);

                options.Cookie.HttpOnly     = true;
                options.Cookie.SecurePolicy = securePolicy;
                options.Cookie.Domain       = cookieDomain;
            });

            return(services);
        }
예제 #2
0
        public static CookieAuthenticationOptions SetupOtherCookies(
            this IApplicationBuilder app,
            string scheme,
            bool useRelatedSitesMode,
            SiteContext tenant,
            CookieSecurePolicy cookieSecure = CookieSecurePolicy.None
            )
        {
            var options = new CookieAuthenticationOptions();

            if (useRelatedSitesMode)
            {
                options.AuthenticationScheme = scheme;
                options.CookieName           = scheme;
                options.CookiePath           = "/";
            }
            else
            {
                //options.AuthenticationScheme = $"{scheme}-{tenant.SiteFolderName}";
                options.AuthenticationScheme = scheme;
                options.CookieName           = $"{scheme}-{tenant.SiteFolderName}";
                options.CookiePath           = "/" + tenant.SiteFolderName;
            }

            options.AutomaticAuthenticate = false;

            if (cookieSecure != CookieSecurePolicy.None)
            {
                options.CookieSecure = cookieSecure;
            }

            return(options);
        }
예제 #3
0
    public async Task SecureSessionBasedOnHttpsAndSecurePolicy(
        CookieSecurePolicy cookieSecurePolicy,
        string requestUri,
        bool shouldBeSecureOnly)
    {
        using var host = new HostBuilder()
                         .ConfigureWebHost(webHostBuilder =>
        {
            webHostBuilder
            .UseTestServer()
            .Configure(app =>
            {
                app.UseSession(new SessionOptions
                {
                    Cookie =
                    {
                        Name         = "TestCookie",
                        SecurePolicy = cookieSecurePolicy
                    }
                });
                app.Run(context =>
                {
                    Assert.Null(context.Session.GetString("Key"));
                    context.Session.SetString("Key", "Value");
                    Assert.Equal("Value", context.Session.GetString("Key"));
                    return(Task.FromResult(0));
                });
            })
            .ConfigureServices(services =>
            {
                services.AddDistributedMemoryCache();
                services.AddSession();
            });
        }).Build();

        await host.StartAsync();

        using (var server = host.GetTestServer())
        {
            var client   = server.CreateClient();
            var response = await client.GetAsync(requestUri);

            response.EnsureSuccessStatusCode();
            Assert.True(response.Headers.TryGetValues("Set-Cookie", out var values));
            Assert.Single(values);
            if (shouldBeSecureOnly)
            {
                Assert.Contains("; secure", values.First());
            }
            else
            {
                Assert.DoesNotContain("; secure", values.First());
            }
        }
    }
예제 #4
0
        public static IApplicationBuilder UseCloudscribeCoreDefaultAuthentication(
            this IApplicationBuilder builder,
            ILoggerFactory loggerFactory,
            MultiTenantOptions multiTenantOptions,
            SiteContext tenant,
            CookieSecurePolicy applicationCookieSecure = CookieSecurePolicy.SameAsRequest
            )
        {
            var useFolder = !multiTenantOptions.UseRelatedSitesMode &&
                            multiTenantOptions.Mode == cloudscribe.Core.Models.MultiTenantMode.FolderName &&
                            tenant.SiteFolderName.Length > 0;

            var externalCookieOptions = builder.SetupOtherCookies(
                AuthenticationScheme.External,
                multiTenantOptions.UseRelatedSitesMode,
                tenant);

            builder.UseCookieAuthentication(externalCookieOptions);

            var twoFactorRememberMeCookieOptions = builder.SetupOtherCookies(
                AuthenticationScheme.TwoFactorRememberMe,
                multiTenantOptions.UseRelatedSitesMode,
                tenant);

            builder.UseCookieAuthentication(twoFactorRememberMeCookieOptions);

            var twoFactorUserIdCookie = builder.SetupOtherCookies(
                AuthenticationScheme.TwoFactorUserId,
                multiTenantOptions.UseRelatedSitesMode,
                tenant);

            builder.UseCookieAuthentication(twoFactorUserIdCookie);

            //var cookieEvents = new CookieAuthenticationEvents();
            var logger           = loggerFactory.CreateLogger <SiteAuthCookieValidator>();
            var cookieValidator  = new SiteAuthCookieValidator(logger);
            var appCookieOptions = builder.SetupAppCookie(
                cookieValidator,
                AuthenticationScheme.Application,
                multiTenantOptions.UseRelatedSitesMode,
                tenant,
                applicationCookieSecure
                );

            builder.UseCookieAuthentication(appCookieOptions);

            // known issue here is if a site is updated to populate the
            // social auth keys, it currently requires a restart so that the middleware gets registered
            // in order for it to work or for the social auth buttons to appear
            builder.UseSocialAuth(tenant, externalCookieOptions, useFolder);


            return(builder);
        }
예제 #5
0
        /// <summary>
        /// this overload is deprecated, the ILoggerFactory is not used or needed here
        /// </summary>
        /// <param name="app"></param>
        /// <param name="loggerFactory"></param>
        /// <param name="multiTenantOptions"></param>
        /// <param name="sslIsAvailable"></param>
        /// <param name="applicationCookieSecure"></param>
        /// <returns></returns>
        public static IApplicationBuilder UseCloudscribeCore(
            this IApplicationBuilder app,
            ILoggerFactory loggerFactory,
            MultiTenantOptions multiTenantOptions,
            bool sslIsAvailable = false,
            CookieSecurePolicy applicationCookieSecure = CookieSecurePolicy.SameAsRequest
            )
        {
            app.UseCloudscribeCore(multiTenantOptions, sslIsAvailable, applicationCookieSecure);

            return(app);
        }
예제 #6
0
        public static IApplicationBuilder UseCloudscribeCoreDefaultAuthentication(
            this IApplicationBuilder builder,
            ILoggerFactory loggerFactory,
            MultiTenantOptions multiTenantOptions,
            SiteContext tenant,
            bool sslIsAvailable = true,
            CookieSecurePolicy applicationCookieSecure = CookieSecurePolicy.SameAsRequest
            )
        {
            var useFolder = !multiTenantOptions.UseRelatedSitesMode &&
                            multiTenantOptions.Mode == cloudscribe.Core.Models.MultiTenantMode.FolderName &&
                            tenant.SiteFolderName.Length > 0;

            var externalCookieOptions = builder.SetupOtherCookies(
                AuthenticationScheme.External,
                multiTenantOptions.UseRelatedSitesMode,
                tenant);

            builder.UseCookieAuthentication(externalCookieOptions);

            var twoFactorRememberMeCookieOptions = builder.SetupOtherCookies(
                AuthenticationScheme.TwoFactorRememberMe,
                multiTenantOptions.UseRelatedSitesMode,
                tenant);

            builder.UseCookieAuthentication(twoFactorRememberMeCookieOptions);

            var twoFactorUserIdCookie = builder.SetupOtherCookies(
                AuthenticationScheme.TwoFactorUserId,
                multiTenantOptions.UseRelatedSitesMode,
                tenant);

            builder.UseCookieAuthentication(twoFactorUserIdCookie);

            //var cookieEvents = new CookieAuthenticationEvents();
            var logger           = loggerFactory.CreateLogger <SiteAuthCookieValidator>();
            var cookieValidator  = new SiteAuthCookieValidator(logger);
            var appCookieOptions = builder.SetupAppCookie(
                cookieValidator,
                AuthenticationScheme.Application,
                multiTenantOptions.UseRelatedSitesMode,
                tenant,
                applicationCookieSecure
                );

            builder.UseCookieAuthentication(appCookieOptions);


            builder.UseSocialAuth(tenant, externalCookieOptions, useFolder, sslIsAvailable);


            return(builder);
        }
예제 #7
0
    public void ConfiguresSecurePolicy(CookieSecurePolicy policy, bool requestIsHttps, bool secure)
    {
        var builder = new CookieBuilder
        {
            SecurePolicy = policy
        };
        var context = new DefaultHttpContext();

        context.Request.IsHttps = requestIsHttps;
        var options = builder.Build(context);

        Assert.Equal(secure, options.Secure);
    }
예제 #8
0
        public static IApplicationBuilder UseCloudscribeCoreDefaultAuthentication(
           this IApplicationBuilder builder,
           ILoggerFactory loggerFactory,
           MultiTenantOptions multiTenantOptions,
           SiteContext tenant,
           CookieSecurePolicy applicationCookieSecure = CookieSecurePolicy.SameAsRequest
           )
        {

            var useFolder = !multiTenantOptions.UseRelatedSitesMode
                                        && multiTenantOptions.Mode == cloudscribe.Core.Models.MultiTenantMode.FolderName
                                        && tenant.SiteFolderName.Length > 0;

            var externalCookieOptions = builder.SetupOtherCookies(
                    AuthenticationScheme.External,
                    multiTenantOptions.UseRelatedSitesMode,
                    tenant);
            builder.UseCookieAuthentication(externalCookieOptions);

            var twoFactorRememberMeCookieOptions = builder.SetupOtherCookies(
                AuthenticationScheme.TwoFactorRememberMe,
                multiTenantOptions.UseRelatedSitesMode,
                tenant);
            builder.UseCookieAuthentication(twoFactorRememberMeCookieOptions);

            var twoFactorUserIdCookie = builder.SetupOtherCookies(
                AuthenticationScheme.TwoFactorUserId,
                multiTenantOptions.UseRelatedSitesMode,
                tenant);
            builder.UseCookieAuthentication(twoFactorUserIdCookie);

            //var cookieEvents = new CookieAuthenticationEvents();
            var logger = loggerFactory.CreateLogger<SiteAuthCookieValidator>();
            var cookieValidator = new SiteAuthCookieValidator(logger);
            var appCookieOptions = builder.SetupAppCookie(
                cookieValidator,
                AuthenticationScheme.Application,
                multiTenantOptions.UseRelatedSitesMode,
                tenant,
                applicationCookieSecure
                );
            builder.UseCookieAuthentication(appCookieOptions);

            // known issue here is if a site is updated to populate the
            // social auth keys, it currently requires a restart so that the middleware gets registered
            // in order for it to work or for the social auth buttons to appear 
            builder.UseSocialAuth(tenant, externalCookieOptions, useFolder);


            return builder;
        }
예제 #9
0
        public static IApplicationBuilder UseCloudscribeCore(
            this IApplicationBuilder app,
            CookieSecurePolicy applicationCookieSecure = CookieSecurePolicy.SameAsRequest
            )
        {
            var multiTenantOptionsAccessor = app.ApplicationServices.GetRequiredService <IOptions <cloudscribe.Core.Models.MultiTenantOptions> >();
            var config = app.ApplicationServices.GetRequiredService <IConfiguration>();

            var sslIsAvailable     = config.GetValue <bool>("AppSettings:UseSsl");
            var multiTenantOptions = multiTenantOptionsAccessor.Value;

            app.UseCloudscribeCore(multiTenantOptions, sslIsAvailable, applicationCookieSecure);

            return(app);
        }
예제 #10
0
        public static IApplicationBuilder UseCloudscribeCore(
            this IApplicationBuilder app,
            ILoggerFactory loggerFactory,
            MultiTenantOptions multiTenantOptions,
            bool sslIsAvailable = false,
            CookieSecurePolicy applicationCookieSecure = CookieSecurePolicy.SameAsRequest
            )
        {
            app.UseCloudscribeCommonStaticFiles();

            app.UseMultitenancy <cloudscribe.Core.Models.SiteContext>();

            app.UsePerTenant <cloudscribe.Core.Models.SiteContext>((ctx, builder) =>
            {
                if (!string.IsNullOrWhiteSpace(ctx.Tenant.ForcedCulture) && !string.IsNullOrWhiteSpace(ctx.Tenant.ForcedUICulture))
                {
                    var tenantLocalization = new RequestLocalizationOptions();
                    tenantLocalization.DefaultRequestCulture = new RequestCulture(culture: ctx.Tenant.ForcedCulture, uiCulture: ctx.Tenant.ForcedUICulture);
                    tenantLocalization.SupportedCultures     = new[] { new CultureInfo(ctx.Tenant.ForcedCulture) };
                    tenantLocalization.SupportedUICultures   = new[] { new CultureInfo(ctx.Tenant.ForcedUICulture) };

                    builder.UseRequestLocalization(tenantLocalization);
                }

                // custom 404 and error page - this preserves the status code (ie 404)
                if (multiTenantOptions.Mode != cloudscribe.Core.Models.MultiTenantMode.FolderName || string.IsNullOrEmpty(ctx.Tenant.SiteFolderName))
                {
                    builder.UseStatusCodePagesWithReExecute("/oops/error/{0}");
                }
                else
                {
                    builder.UseStatusCodePagesWithReExecute("/" + ctx.Tenant.SiteFolderName + "/oops/error/{0}");
                }

                // resolve static files from wwwroot folders within themes and within sitefiles
                builder.UseSiteAndThemeStaticFiles(loggerFactory, multiTenantOptions, ctx.Tenant);


                //builder.UseAuthentication();
            });

            app.UseCloudscribeEnforceSiteRulesMiddleware();

            app.UseAuthentication();

            return(app);
        }
예제 #11
0
        public async Task SecureSessionBasedOnHttpsAndSecurePolicy(
            CookieSecurePolicy cookieSecurePolicy,
            string requestUri,
            bool shouldBeSecureOnly)
        {
            var builder = new WebHostBuilder()
                          .Configure(app =>
            {
                app.UseSession(new SessionOptions
                {
                    CookieName   = "TestCookie",
                    CookieSecure = cookieSecurePolicy
                });
                app.Run(context =>
                {
                    Assert.Null(context.Session.GetString("Key"));
                    context.Session.SetString("Key", "Value");
                    Assert.Equal("Value", context.Session.GetString("Key"));
                    return(Task.FromResult(0));
                });
            })
                          .ConfigureServices(services =>
            {
                services.AddSingleton <IDistributedCache>(new FauxCouchbaseCache());
                services.AddCouchbaseSession();
            });

            using (var server = new TestServer(builder))
            {
                var client   = server.CreateClient();
                var response = await client.GetAsync(requestUri);

                response.EnsureSuccessStatusCode();
                IEnumerable <string> values;
                Assert.True(response.Headers.TryGetValues("Set-Cookie", out values));
                Assert.Equal(1, values.Count());
                if (shouldBeSecureOnly)
                {
                    Assert.Contains("; secure", values.First());
                }
                else
                {
                    Assert.DoesNotContain("; secure", values.First());
                }
            }
        }
예제 #12
0
        public void SaveTempData_HonorsCookieSecurePolicy_OnOptions(
            bool isRequestSecure,
            CookieSecurePolicy cookieSecurePolicy,
            bool expectedSecureFlag)
        {
            // Arrange
            var values = new Dictionary <string, object>();

            values.Add("int", 10);
            var tempDataProviderStore = new TempDataSerializer();
            var expectedDataToProtect = tempDataProviderStore.Serialize(values);
            var expectedDataInCookie  = WebEncoders.Base64UrlEncode(expectedDataToProtect);
            var dataProtector         = new PassThroughDataProtector();
            var options = new CookieTempDataProviderOptions();

            options.Cookie.SecurePolicy = cookieSecurePolicy;
            var tempDataProvider = GetProvider(dataProtector, options);
            var responseCookies  = new MockResponseCookieCollection();
            var httpContext      = new Mock <HttpContext>();

            httpContext
            .SetupGet(hc => hc.Request.PathBase)
            .Returns("/");
            httpContext
            .SetupGet(hc => hc.Request.IsHttps)
            .Returns(isRequestSecure);
            httpContext
            .Setup(hc => hc.Response.Cookies)
            .Returns(responseCookies);

            // Act
            tempDataProvider.SaveTempData(httpContext.Object, values);

            // Assert
            Assert.Equal(1, responseCookies.Count);
            var cookieInfo = responseCookies[CookieTempDataProvider.CookieName];

            Assert.NotNull(cookieInfo);
            Assert.Equal(expectedDataInCookie, cookieInfo.Value);
            Assert.Equal(expectedDataToProtect, dataProtector.PlainTextToProtect);
            Assert.Equal("/", cookieInfo.Options.Path);
            Assert.Equal(expectedSecureFlag, cookieInfo.Options.Secure);
            Assert.True(cookieInfo.Options.HttpOnly);
            Assert.Null(cookieInfo.Options.Expires);
            Assert.Null(cookieInfo.Options.Domain);
        }
예제 #13
0
        public void SaveCookieToken_HonorsCookieSecurePolicy_OnOptions(
            bool isRequestSecure,
            CookieSecurePolicy policy,
            bool?expectedCookieSecureFlag)
        {
            // Arrange
            var  token = "serialized-value";
            bool defaultCookieSecureValue = expectedCookieSecureFlag ?? false; // pulled from config; set by ctor
            var  cookies = new MockResponseCookieCollection();

            var httpContext = new Mock <HttpContext>();

            httpContext
            .Setup(hc => hc.Request.IsHttps)
            .Returns(isRequestSecure);
            httpContext
            .Setup(o => o.Response.Cookies)
            .Returns(cookies);
            httpContext
            .SetupGet(hc => hc.Request.PathBase)
            .Returns("/");

            var options = new AntiforgeryOptions()
            {
                Cookie =
                {
                    Name         = _cookieName,
                    SecurePolicy = policy
                },
            };

            var tokenStore = new DefaultAntiforgeryTokenStore(new TestOptionsManager(options));

            // Act
            tokenStore.SaveCookieToken(httpContext.Object, token);

            // Assert
            Assert.Equal(1, cookies.Count);
            Assert.NotNull(cookies);
            Assert.Equal(_cookieName, cookies.Key);
            Assert.Equal("serialized-value", cookies.Value);
            Assert.True(cookies.Options !.HttpOnly);
            Assert.Equal(defaultCookieSecureValue, cookies.Options.Secure);
        }
예제 #14
0
        public static CookieAuthenticationOptions SetupAppCookie(
            this IApplicationBuilder app,
            SiteAuthCookieValidator siteValidator,
            string scheme,
            bool useRelatedSitesMode,
            SiteContext tenant,
            CookieSecurePolicy cookieSecure = CookieSecurePolicy.SameAsRequest
            )
        {
            var cookieEvents = new CookieAuthenticationEvents();
            var options      = new CookieAuthenticationOptions();

            if (useRelatedSitesMode)
            {
                options.AuthenticationScheme = scheme;
                options.CookieName           = scheme;
                options.CookiePath           = "/";
            }
            else
            {
                //options.AuthenticationScheme = $"{scheme}-{tenant.SiteFolderName}";
                options.AuthenticationScheme     = scheme;
                options.CookieName               = $"{scheme}-{tenant.SiteFolderName}";
                options.CookiePath               = "/" + tenant.SiteFolderName;
                cookieEvents.OnValidatePrincipal = siteValidator.ValidatePrincipal;
            }

            var tenantPathBase = string.IsNullOrEmpty(tenant.SiteFolderName)
                ? PathString.Empty
                : new PathString("/" + tenant.SiteFolderName);

            options.LoginPath        = tenantPathBase + "/account/login";
            options.LogoutPath       = tenantPathBase + "/account/logoff";
            options.AccessDeniedPath = tenantPathBase + "/account/accessdenied";

            options.Events = cookieEvents;

            options.AutomaticAuthenticate = true;
            options.AutomaticChallenge    = false;

            options.CookieSecure = cookieSecure;

            return(options);
        }
예제 #15
0
        /// <summary>
        /// Add SAML 2.0 configuration.
        /// </summary>
        /// <param name="loginPath">Redirection target used by the handler.</param>
        /// <param name="slidingExpiration">If set to true the handler re-issue a new cookie with a new expiration time any time it processes a request which is more than halfway through the expiration window.</param>
        /// <param name="accessDeniedPath">If configured, access denied redirection target used by the handler.</param>
        /// <param name="sessionStore">Allow configuration of a custom ITicketStore.</param>
        /// <param name="cookieSameSite">The SameSite attribute of the cookie. The default value is Microsoft.AspNetCore.Http.SameSiteMode.Lax</param>
        /// <param name="cookieDomain">If configured, the domain to associate the cookie with.</param>
        /// <param name="cookieSecurePolicy">The cookie policy. The default value is Microsoft.AspNetCore.Http.CookieSecurePolicy.SameAsRequest.</param>
        public static IServiceCollection AddSaml2(this IServiceCollection services, string loginPath = "/Auth/Login", bool slidingExpiration = false, string accessDeniedPath = null, ITicketStore sessionStore = null, SameSiteMode cookieSameSite = SameSiteMode.Lax, string cookieDomain = null, CookieSecurePolicy cookieSecurePolicy = CookieSecurePolicy.SameAsRequest)
        {
            services.AddAuthentication(Saml2Constants.AuthenticationScheme)
            .AddCookie(Saml2Constants.AuthenticationScheme, o =>
            {
                o.LoginPath         = new PathString(loginPath);
                o.SlidingExpiration = slidingExpiration;
                if (!string.IsNullOrEmpty(accessDeniedPath))
                {
                    o.AccessDeniedPath = new PathString(accessDeniedPath);
                }
                if (sessionStore != null)
                {
                    o.SessionStore = sessionStore;
                }
                o.Cookie.SameSite     = cookieSameSite;
                o.Cookie.SecurePolicy = cookieSecurePolicy;
                if (!string.IsNullOrEmpty(cookieDomain))
                {
                    o.Cookie.Domain = cookieDomain;
                }
            });

            return(services);
        }
예제 #16
0
        public async Task SecureSignInCausesSecureOnlyCookieByDefault(
            CookieSecurePolicy cookieSecurePolicy,
            string requestUri,
            bool shouldBeSecureOnly)
        {
            var server = CreateServer(new CookieAuthenticationOptions
            {
                LoginPath = new PathString("/login"),
                CookieName = "TestCookie",
                CookieSecure = cookieSecurePolicy
            }, SignInAsAlice);

            var transaction = await SendAsync(server, requestUri);
            var setCookie = transaction.SetCookie;

            if (shouldBeSecureOnly)
            {
                Assert.Contains("; secure", setCookie);
            }
            else
            {
                Assert.DoesNotContain("; secure", setCookie);
            }
        }
예제 #17
0
        public static CookieAuthenticationOptions SetupAppCookie(
            this IApplicationBuilder app,
           SiteAuthCookieValidator siteValidator,
           string scheme,
           bool useRelatedSitesMode,
           SiteContext tenant,
           CookieSecurePolicy cookieSecure = CookieSecurePolicy.SameAsRequest
           )
        {
            var cookieEvents = new CookieAuthenticationEvents();
            var options = new CookieAuthenticationOptions();
            if (useRelatedSitesMode)
            {
                options.AuthenticationScheme = scheme;
                options.CookieName = scheme;
                options.CookiePath = "/";
            }
            else
            {
                //options.AuthenticationScheme = $"{scheme}-{tenant.SiteFolderName}";
                options.AuthenticationScheme = scheme;
                options.CookieName = $"{scheme}-{tenant.SiteFolderName}";
                options.CookiePath = "/" + tenant.SiteFolderName;
                cookieEvents.OnValidatePrincipal = siteValidator.ValidatePrincipal;
            }

            var tenantPathBase = string.IsNullOrEmpty(tenant.SiteFolderName)
                ? PathString.Empty
                : new PathString("/" + tenant.SiteFolderName);

            options.LoginPath = tenantPathBase + "/account/login";
            options.LogoutPath = tenantPathBase + "/account/logoff";
            options.AccessDeniedPath = tenantPathBase + "/account/accessdenied";

            options.Events = cookieEvents;

            options.AutomaticAuthenticate = true;
            options.AutomaticChallenge = false;

            options.CookieSecure = cookieSecure;

            return options;
        }
 public AnonymousIdCookieOptionsBuilder SetCustomCookieSecurePolicy(CookieSecurePolicy cookieSecurePolicy)
 {
     this.cookieSecurePolicy = cookieSecurePolicy;
     return(this);
 }
예제 #19
0
        public static CookieAuthenticationOptions SetupOtherCookies(
            this IApplicationBuilder app,
            string scheme,
            bool useRelatedSitesMode,
            SiteContext tenant,
            CookieSecurePolicy cookieSecure = CookieSecurePolicy.None
            )
        {
            var options = new CookieAuthenticationOptions();
            if (useRelatedSitesMode)
            {
                options.AuthenticationScheme = scheme;
                options.CookieName = scheme;
                options.CookiePath = "/";
            }
            else
            {
                //options.AuthenticationScheme = $"{scheme}-{tenant.SiteFolderName}";
                options.AuthenticationScheme = scheme;
                options.CookieName = $"{scheme}-{tenant.SiteFolderName}";
                options.CookiePath = "/" + tenant.SiteFolderName;
            }

            options.AutomaticAuthenticate = false;

            if (cookieSecure != CookieSecurePolicy.None)
            {
                options.CookieSecure = cookieSecure;
            }

            return options;

        }
예제 #20
0
        public static IApplicationBuilder UseCloudscribeCore(
            this IApplicationBuilder app,
            ILoggerFactory loggerFactory,
            MultiTenantOptions multiTenantOptions,
            bool sslIsAvailable = false,
            Func <IApplicationBuilder, ISiteContext, bool> identityServerInvoker = null,
            CookieSecurePolicy applicationCookieSecure = CookieSecurePolicy.SameAsRequest
            )
        {
            app.UseCloudscribeCommonStaticFiles();

            app.UseMultitenancy <cloudscribe.Core.Models.SiteContext>();



            app.UsePerTenant <cloudscribe.Core.Models.SiteContext>((ctx, builder) =>
            {
                //var locOptions = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>();


                if (!string.IsNullOrWhiteSpace(ctx.Tenant.ForcedCulture) && !string.IsNullOrWhiteSpace(ctx.Tenant.ForcedUICulture))
                {
                    var tenantLocalization = new RequestLocalizationOptions();
                    tenantLocalization.DefaultRequestCulture = new RequestCulture(culture: ctx.Tenant.ForcedCulture, uiCulture: ctx.Tenant.ForcedUICulture);
                    tenantLocalization.SupportedCultures     = new[] { new CultureInfo(ctx.Tenant.ForcedCulture) };
                    tenantLocalization.SupportedUICultures   = new[] { new CultureInfo(ctx.Tenant.ForcedUICulture) };

                    builder.UseRequestLocalization(tenantLocalization);
                }



                // custom 404 and error page - this preserves the status code (ie 404)
                if (multiTenantOptions.Mode != cloudscribe.Core.Models.MultiTenantMode.FolderName || string.IsNullOrEmpty(ctx.Tenant.SiteFolderName))
                {
                    builder.UseStatusCodePagesWithReExecute("/oops/error/{0}");
                }
                else
                {
                    builder.UseStatusCodePagesWithReExecute("/" + ctx.Tenant.SiteFolderName + "/oops/error/{0}");
                }

                // resolve static files from wwwroot folders within themes and within sitefiles
                builder.UseSiteAndThemeStaticFiles(loggerFactory, multiTenantOptions, ctx.Tenant);

                builder.UseCloudscribeCoreDefaultAuthentication(
                    loggerFactory,
                    multiTenantOptions,
                    ctx.Tenant,
                    sslIsAvailable);

                // to make this multi tenant for folders we are
                // using a fork of IdentityServer4 and hoping to get changes so we don't need a fork
                // https://github.com/IdentityServer/IdentityServer4/issues/19

                if (identityServerInvoker != null)
                {
                    var addedIdentityServer = identityServerInvoker(builder, ctx.Tenant);
                }
                //builder.UseIdentityServer();

                //// this sets up the authentication for apis within this application endpoint
                //// ie apis that are hosted in the same web app endpoint with the authority server
                //// this is not needed here if you are only using separate api endpoints
                //// it is needed in the startup of those separate endpoints
                //// note that with both cookie auth and jwt auth middleware the principal is merged from both the cookie and the jwt token if it is passed
                //builder.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
                //{
                //    Authority = "https://localhost:44399",
                //    // using the site aliasid as the scope so each tenant has a different scope
                //    // you can view the aliasid from site settings
                //    // clients must be configured with the scope to have access to the apis for the tenant
                //    ApiName = ctx.Tenant.AliasId,
                //    //RoleClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role",
                //    //AuthenticationScheme = AuthenticationScheme.Application,

                //    RequireHttpsMetadata = true
                //});
            });

            app.UseCloudscribeEnforceSiteRulesMiddleware();

            return(app);
        }
예제 #21
0
        public static AuthenticationBuilder AddCookieAuthentication(this IServiceCollection services, CookieSecurePolicy cookieSecurePolicy)
        => services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
        .AddCookie(cfg =>
        {
            cfg.Cookie.SecurePolicy = cookieSecurePolicy;

            cfg.Events = new CookieAuthenticationEvents
            {
                OnValidatePrincipal = async context =>
                {
                    var userSession = context.HttpContext.RequestServices.GetRequiredService <IUserRepository>();
                    try
                    {
                        var userId     = context.Principal.GetId();
                        var user       = await userSession.GetByIdAsync(userId);
                        var claimRoles = context.Principal.Claims.Where(c => c.Type == ClaimTypes.Role)
                                         .Select(c => c.Value);
                        if (!(claimRoles.Except(user.Roles).Count() == 0 && user.Roles.Except(claimRoles).Count() == 0))
                        {
                            await context.HttpContext.SignOutAsync();
                            context.RejectPrincipal();
                        }
                    }
                    catch (Exception e) when(e is FormatException || e is EntityNotFoundException)
                    {
                        context.RejectPrincipal();
                    }
                },
                OnRedirectToAccessDenied = context =>
                {
                    context.HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
                    return(Task.CompletedTask);
                },
                OnRedirectToLogin = context =>
                {
                    context.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                    return(Task.CompletedTask);
                },
            };
        });