/// <summary>
        /// Adds user impersonation components, including <see cref="IUserInfo"/> implementation for impersonated users and a dashboard snippet.
        /// </summary>
        public static RhetosServiceCollectionBuilder AddImpersonation(this RhetosServiceCollectionBuilder builder, Action <ImpersonationOptions> configureOptions = null)
        {
            builder.Services.AddHttpContextAccessor();

            builder.Services.AddOptions();
            if (configureOptions != null)
            {
                builder.Services.Configure(configureOptions);
            }

            builder.AddRestApiFilters();

            builder.ConfigureRhetosHost((serviceProvider, rhetosHostBuilder) =>
                                        rhetosHostBuilder.ConfigureContainer(containerBuilder =>
            {
                containerBuilder.Register(_ => serviceProvider.GetRequiredService <IHttpContextAccessor>()).SingleInstance().ExternallyOwned();
                containerBuilder.Register(_ => serviceProvider.GetRequiredService <IDataProtectionProvider>()).SingleInstance().ExternallyOwned();
                containerBuilder.Register(_ => serviceProvider.GetRequiredService <IOptions <ImpersonationOptions> >().Value).SingleInstance().ExternallyOwned();

                containerBuilder.RegisterType <RhetosAspNetCoreIdentityUser>().InstancePerMatchingLifetimeScope(UnitOfWorkScope.ScopeName);
                containerBuilder.Register <BaseAuthentication>(context => new BaseAuthentication(context.Resolve <RhetosAspNetCoreIdentityUser>())).InstancePerMatchingLifetimeScope(UnitOfWorkScope.ScopeName);
                containerBuilder.RegisterType <ImpersonationService>().InstancePerMatchingLifetimeScope(UnitOfWorkScope.ScopeName);
                containerBuilder.Register <IUserInfo>(context => context.Resolve <ImpersonationService>().GetUserInfo()).InstancePerMatchingLifetimeScope(UnitOfWorkScope.ScopeName);
            }));

            builder.Services.AddDataProtection();
            builder.Services.AddMvcCore()
            .AddApplicationPart(typeof(ImpersonationController).Assembly);

            builder.AddDashboardSnippet <ImpersonationDashboardSnippet>();

            return(builder);
        }
        /// <summary>
        /// Configures authentication for current application, using HTTP cookies.
        /// Registers required components for the <see cref="AuthenticationController"/> and <see cref="AuthenticationService"/>.
        /// </summary>
        public static RhetosServiceCollectionBuilder AddAspNetFormsAuth(this RhetosServiceCollectionBuilder builder, Action <AspNetFormsAuthOptions> configureOptions = null)
        {
            builder.Services.AddOptions();
            if (configureOptions != null)
            {
                builder.Services.Configure(configureOptions);
            }

            builder.Services.AddIdentityCore <IdentityUser <Guid> >(options =>
            {
                options.Password.RequireDigit           = false;
                options.Password.RequireLowercase       = false;
                options.Password.RequireNonAlphanumeric = false;
                options.Password.RequireUppercase       = false;
                options.Password.RequiredLength         = 1;
                options.User.AllowedUserNameCharacters  = "";
            })
            .AddUserStore <RhetosUserStore>()
            .AddDefaultTokenProviders()
            .AddSignInManager <SignInManager <IdentityUser <Guid> > >();

            builder.Services.TryAddScoped <ISecurityStampValidator, SecurityStampValidator <IdentityUser <Guid> > >();
            builder.Services.TryAddScoped <AuthenticationService>();

            builder.AddRestApiFilters();

            builder.Services.AddAuthentication(IdentityConstants.ApplicationScheme)
            .AddCookie(IdentityConstants.ApplicationScheme, o => o.Events.OnRedirectToLogin = context =>
            {
                context.Response.StatusCode = StatusCodes.Status401Unauthorized;
                return(Task.CompletedTask);
            });

            return(builder);
        }