/// <inheritdoc />
        public async Task InvokeAsync(HttpContext context, RequestDelegate next)
        {
            if (_runtimeState.Level < RuntimeLevel.Run || context.Request.IsBackOfficeRequest() || !_basicAuthService.IsBasicAuthEnabled())
            {
                await next(context);

                return;
            }

            IPAddress clientIPAddress = context.Connection.RemoteIpAddress;

            if (_basicAuthService.IsIpAllowListed(clientIPAddress))
            {
                await next(context);

                return;
            }

            AuthenticateResult authenticateResult = await context.AuthenticateBackOfficeAsync();

            if (authenticateResult.Succeeded)
            {
                await next(context);

                return;
            }

            if (context.TryGetBasicAuthCredentials(out var username, out var password))
            {
                IBackOfficeSignInManager backOfficeSignInManager =
                    context.RequestServices.GetService <IBackOfficeSignInManager>();

                if (backOfficeSignInManager is not null)
                {
                    SignInResult signInResult =
                        await backOfficeSignInManager.PasswordSignInAsync(username, password, false, true);

                    if (signInResult.Succeeded)
                    {
                        await next.Invoke(context);
                    }
                    else
                    {
                        SetUnauthorizedHeader(context);
                    }
                }
                else
                {
                    SetUnauthorizedHeader(context);
                }
            }
            else
            {
                // no authorization header
                SetUnauthorizedHeader(context);
            }
        }
    public TestAuthHandler(
        IOptionsMonitor <AuthenticationSchemeOptions> options,
        ILoggerFactory logger,
        UrlEncoder encoder,
        ISystemClock clock,
        IBackOfficeSignInManager backOfficeSignInManager,
        IUserService userService,
        IUmbracoMapper umbracoMapper)
        : base(options, logger, encoder, clock)
    {
        _backOfficeSignInManager = backOfficeSignInManager;

        var user = userService.GetUserById(Constants.Security.SuperUserId);

        _fakeUser = umbracoMapper.Map <IUser, BackOfficeIdentityUser>(user);
        _fakeUser.SecurityStamp = "Needed";
    }
Exemple #3
0
 public AuthenticationController(
     IBackOfficeSecurityAccessor backofficeSecurityAccessor,
     IBackOfficeUserManager backOfficeUserManager,
     IBackOfficeSignInManager signInManager,
     IUserService userService,
     ILocalizedTextService textService,
     IUmbracoMapper umbracoMapper,
     IOptionsSnapshot <GlobalSettings> globalSettings,
     IOptionsSnapshot <SecuritySettings> securitySettings,
     ILogger <AuthenticationController> logger,
     IIpResolver ipResolver,
     IOptionsSnapshot <UserPasswordConfigurationSettings> passwordConfiguration,
     IEmailSender emailSender,
     ISmsSender smsSender,
     IHostingEnvironment hostingEnvironment,
     LinkGenerator linkGenerator,
     IBackOfficeExternalLoginProviders externalAuthenticationOptions,
     IBackOfficeTwoFactorOptions backOfficeTwoFactorOptions,
     IHttpContextAccessor httpContextAccessor,
     IOptions <WebRoutingSettings> webRoutingSettings,
     ITwoFactorLoginService twoFactorLoginService)
 {
     _backofficeSecurityAccessor = backofficeSecurityAccessor;
     _userManager                   = backOfficeUserManager;
     _signInManager                 = signInManager;
     _userService                   = userService;
     _textService                   = textService;
     _umbracoMapper                 = umbracoMapper;
     _globalSettings                = globalSettings.Value;
     _securitySettings              = securitySettings.Value;
     _logger                        = logger;
     _ipResolver                    = ipResolver;
     _passwordConfiguration         = passwordConfiguration.Value;
     _emailSender                   = emailSender;
     _smsSender                     = smsSender;
     _hostingEnvironment            = hostingEnvironment;
     _linkGenerator                 = linkGenerator;
     _externalAuthenticationOptions = externalAuthenticationOptions;
     _backOfficeTwoFactorOptions    = backOfficeTwoFactorOptions;
     _httpContextAccessor           = httpContextAccessor;
     _webRoutingSettings            = webRoutingSettings.Value;
     _twoFactorLoginService         = twoFactorLoginService;
 }
 public AuthenticationController(
     IBackOfficeSecurityAccessor backofficeSecurityAccessor,
     IBackOfficeUserManager backOfficeUserManager,
     IBackOfficeSignInManager signInManager,
     IUserService userService,
     ILocalizedTextService textService,
     IUmbracoMapper umbracoMapper,
     IOptions <GlobalSettings> globalSettings,
     IOptions <SecuritySettings> securitySettings,
     ILogger <AuthenticationController> logger,
     IIpResolver ipResolver,
     IOptions <UserPasswordConfigurationSettings> passwordConfiguration,
     IEmailSender emailSender,
     ISmsSender smsSender,
     IHostingEnvironment hostingEnvironment,
     LinkGenerator linkGenerator,
     IBackOfficeExternalLoginProviders externalAuthenticationOptions,
     IBackOfficeTwoFactorOptions backOfficeTwoFactorOptions,
     IHttpContextAccessor httpContextAccessor,
     IOptions <WebRoutingSettings> webRoutingSettings)
     : this(
         backofficeSecurityAccessor,
         backOfficeUserManager,
         signInManager,
         userService,
         textService,
         umbracoMapper,
         globalSettings,
         securitySettings,
         logger,
         ipResolver,
         passwordConfiguration,
         emailSender,
         smsSender,
         hostingEnvironment,
         linkGenerator,
         externalAuthenticationOptions,
         backOfficeTwoFactorOptions,
         StaticServiceProvider.Instance.GetRequiredService <IHttpContextAccessor>(),
         StaticServiceProvider.Instance.GetRequiredService <IOptions <WebRoutingSettings> >(),
         StaticServiceProvider.Instance.GetRequiredService <ITwoFactorLoginService>())
 {
 }
Exemple #5
0
        public TwoFactorLoginController(
            IBackOfficeSecurityAccessor backOfficeSecurityAccessor,
            ILogger <TwoFactorLoginController> logger,
            ITwoFactorLoginService twoFactorLoginService,
            IBackOfficeSignInManager backOfficeSignInManager,
            IBackOfficeUserManager backOfficeUserManager,
            IOptionsSnapshot <TwoFactorLoginViewOptions> twoFactorLoginViewOptions)
        {
            _backOfficeSecurityAccessor = backOfficeSecurityAccessor;
            _logger = logger;

            if (twoFactorLoginService is not ITwoFactorLoginService2 twoFactorLoginService2)
            {
                throw new ArgumentException("twoFactorLoginService needs to implement ITwoFactorLoginService2 until the interfaces are merged", nameof(twoFactorLoginService));
            }
            _twoFactorLoginService     = twoFactorLoginService2;
            _backOfficeSignInManager   = backOfficeSignInManager;
            _backOfficeUserManager     = backOfficeUserManager;
            _twoFactorLoginViewOptions = twoFactorLoginViewOptions;
        }
Exemple #6
0
 public BackOfficeController(
     IBackOfficeUserManager userManager,
     IRuntimeState runtimeState,
     IRuntimeMinifier runtimeMinifier,
     IOptionsSnapshot <GlobalSettings> globalSettings,
     IHostingEnvironment hostingEnvironment,
     ILocalizedTextService textService,
     IGridConfig gridConfig,
     BackOfficeServerVariables backOfficeServerVariables,
     AppCaches appCaches,
     IBackOfficeSignInManager signInManager,
     IBackOfficeSecurityAccessor backofficeSecurityAccessor,
     ILogger <BackOfficeController> logger,
     IJsonSerializer jsonSerializer,
     IBackOfficeExternalLoginProviders externalLogins,
     IHttpContextAccessor httpContextAccessor,
     IBackOfficeTwoFactorOptions backOfficeTwoFactorOptions,
     IManifestParser manifestParser,
     ServerVariablesParser serverVariables,
     IOptions <SecuritySettings> securitySettings)
 {
     _userManager               = userManager;
     _runtimeState              = runtimeState;
     _runtimeMinifier           = runtimeMinifier;
     _globalSettings            = globalSettings.Value;
     _hostingEnvironment        = hostingEnvironment;
     _textService               = textService;
     _gridConfig                = gridConfig ?? throw new ArgumentNullException(nameof(gridConfig));
     _backOfficeServerVariables = backOfficeServerVariables;
     _appCaches     = appCaches;
     _signInManager = signInManager;
     _backofficeSecurityAccessor = backofficeSecurityAccessor;
     _logger                     = logger;
     _jsonSerializer             = jsonSerializer;
     _externalLogins             = externalLogins;
     _httpContextAccessor        = httpContextAccessor;
     _backOfficeTwoFactorOptions = backOfficeTwoFactorOptions;
     _manifestParser             = manifestParser;
     _serverVariables            = serverVariables;
     _securitySettings           = securitySettings;
 }
 public BackOfficeController(
     IBackOfficeUserManager userManager,
     IRuntimeState runtimeState,
     IRuntimeMinifier runtimeMinifier,
     IOptions <GlobalSettings> globalSettings,
     IHostingEnvironment hostingEnvironment,
     ILocalizedTextService textService,
     IGridConfig gridConfig,
     BackOfficeServerVariables backOfficeServerVariables,
     AppCaches appCaches,
     IBackOfficeSignInManager signInManager,
     IBackOfficeSecurityAccessor backofficeSecurityAccessor,
     ILogger <BackOfficeController> logger,
     IJsonSerializer jsonSerializer,
     IBackOfficeExternalLoginProviders externalLogins,
     IHttpContextAccessor httpContextAccessor,
     IBackOfficeTwoFactorOptions backOfficeTwoFactorOptions,
     IManifestParser manifestParser,
     ServerVariablesParser serverVariables)
     : this(userManager,
            runtimeState,
            runtimeMinifier,
            globalSettings,
            hostingEnvironment,
            textService,
            gridConfig,
            backOfficeServerVariables,
            appCaches,
            signInManager,
            backofficeSecurityAccessor,
            logger,
            jsonSerializer,
            externalLogins,
            httpContextAccessor,
            backOfficeTwoFactorOptions,
            manifestParser,
            serverVariables,
            StaticServiceProvider.Instance.GetRequiredService <IOptions <SecuritySettings> >()
            )
 {
 }
Exemple #8
0
 public InstallApiController(
     DatabaseBuilder databaseBuilder,
     IProfilingLogger proflog,
     ILogger <InstallApiController> logger,
     InstallHelper installHelper,
     InstallStepCollection installSteps,
     InstallStatusTracker installStatusTracker,
     IRuntime runtime,
     IBackOfficeUserManager backOfficeUserManager,
     IBackOfficeSignInManager backOfficeSignInManager)
 {
     _databaseBuilder         = databaseBuilder ?? throw new ArgumentNullException(nameof(databaseBuilder));
     _proflog                 = proflog ?? throw new ArgumentNullException(nameof(proflog));
     _installSteps            = installSteps;
     _installStatusTracker    = installStatusTracker;
     _runtime                 = runtime;
     _backOfficeUserManager   = backOfficeUserManager;
     _backOfficeSignInManager = backOfficeSignInManager;
     InstallHelper            = installHelper;
     _logger = logger;
 }
 public CheckIfUserTicketDataIsStaleFilter(
     IRequestCache requestCache,
     IUmbracoMapper umbracoMapper,
     IUserService userService,
     IEntityService entityService,
     ILocalizedTextService localizedTextService,
     IOptions <GlobalSettings> globalSettings,
     IBackOfficeSignInManager backOfficeSignInManager,
     IBackOfficeAntiforgery backOfficeAntiforgery,
     IScopeProvider scopeProvider,
     AppCaches appCaches)
 {
     _requestCache            = requestCache;
     _umbracoMapper           = umbracoMapper;
     _userService             = userService;
     _entityService           = entityService;
     _localizedTextService    = localizedTextService;
     _globalSettings          = globalSettings;
     _backOfficeSignInManager = backOfficeSignInManager;
     _backOfficeAntiforgery   = backOfficeAntiforgery;
     _scopeProvider           = scopeProvider;
     _appCaches = appCaches;
 }
    /// <inheritdoc />
    public void Configure(CookieAuthenticationOptions options)
    {
        options.SlidingExpiration   = false;
        options.ExpireTimeSpan      = _globalSettings.TimeOut;
        options.Cookie.Domain       = _securitySettings.AuthCookieDomain;
        options.Cookie.Name         = _securitySettings.AuthCookieName;
        options.Cookie.HttpOnly     = true;
        options.Cookie.SecurePolicy =
            _globalSettings.UseHttps ? CookieSecurePolicy.Always : CookieSecurePolicy.SameAsRequest;
        options.Cookie.Path = "/";

        // For any redirections that may occur for the back office, they all go to the same path
        var backOfficePath = _globalSettings.GetBackOfficePath(_hostingEnvironment);

        options.AccessDeniedPath = backOfficePath;
        options.LoginPath        = backOfficePath;
        options.LogoutPath       = backOfficePath;

        options.DataProtectionProvider = _dataProtection;

        // NOTE: This is borrowed directly from aspnetcore source
        // Note: the purpose for the data protector must remain fixed for interop to work.
        IDataProtector dataProtector = options.DataProtectionProvider.CreateProtector(
            "Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware",
            Constants.Security.BackOfficeAuthenticationType,
            "v2");
        var ticketDataFormat = new TicketDataFormat(dataProtector);

        options.TicketDataFormat = new BackOfficeSecureDataFormat(_globalSettings.TimeOut, ticketDataFormat);

        // Custom cookie manager so we can filter requests
        options.CookieManager = new BackOfficeCookieManager(
            _umbracoContextAccessor,
            _runtimeState,
            _umbracoRequestPaths,
            _basicAuthService);

        options.Events = new CookieAuthenticationEvents
        {
            // IMPORTANT! If you set any of OnRedirectToLogin, OnRedirectToAccessDenied, OnRedirectToLogout, OnRedirectToReturnUrl
            // you need to be aware that this will bypass the default behavior of returning the correct status codes for ajax requests and
            // not redirecting for non-ajax requests. This is because the default behavior is baked into this class here:
            // https://github.com/dotnet/aspnetcore/blob/master/src/Security/Authentication/Cookies/src/CookieAuthenticationEvents.cs#L58
            // It would be possible to re-use the default behavior if any of these need to be set but that must be taken into account else
            // our back office requests will not function correctly. For now we don't need to set/configure any of these callbacks because
            // the defaults work fine with our setup.
            OnValidatePrincipal = async ctx =>
            {
                // We need to resolve the BackOfficeSecurityStampValidator per request as a requirement (even in aspnetcore they do this)
                BackOfficeSecurityStampValidator securityStampValidator =
                    ctx.HttpContext.RequestServices.GetRequiredService <BackOfficeSecurityStampValidator>();

                // Same goes for the signinmanager
                IBackOfficeSignInManager signInManager =
                    ctx.HttpContext.RequestServices.GetRequiredService <IBackOfficeSignInManager>();

                ClaimsIdentity?backOfficeIdentity = ctx.Principal?.GetUmbracoIdentity();
                if (backOfficeIdentity == null)
                {
                    ctx.RejectPrincipal();
                    await signInManager.SignOutAsync();
                }

                // ensure the thread culture is set
                backOfficeIdentity?.EnsureCulture();

                EnsureTicketRenewalIfKeepUserLoggedIn(ctx);

                // add or update a claim to track when the cookie expires, we use this to track time remaining
                backOfficeIdentity?.AddOrUpdateClaim(new Claim(
                                                         Constants.Security.TicketExpiresClaimType,
                                                         ctx.Properties.ExpiresUtc !.Value.ToString("o"),
                                                         ClaimValueTypes.DateTime,
                                                         Constants.Security.BackOfficeAuthenticationType,
                                                         Constants.Security.BackOfficeAuthenticationType,
                                                         backOfficeIdentity));

                await securityStampValidator.ValidateAsync(ctx);

                // This might have been called from GetRemainingTimeoutSeconds, in this case we don't want to ensure valid session
                // since that in it self will keep the session valid since we renew the lastVerified date.
                // Similarly don't renew the token
                if (IsRemainingSecondsRequest(ctx))
                {
                    return;
                }

                // This relies on IssuedUtc, so call it before updating it.
                await EnsureValidSessionId(ctx);

                // We have to manually specify Issued and Expires,
                // because the SecurityStampValidator refreshes the principal every 30 minutes,
                // When the principal is refreshed the Issued is update to time of refresh, however, the Expires remains unchanged
                // When we then try and renew, the difference of issued and expires effectively becomes the new ExpireTimeSpan
                // meaning we effectively lose 30 minutes of our ExpireTimeSpan for EVERY principal refresh if we don't
                // https://github.com/dotnet/aspnetcore/blob/main/src/Security/Authentication/Cookies/src/CookieAuthenticationHandler.cs#L115
                ctx.Properties.IssuedUtc  = _systemClock.UtcNow;
                ctx.Properties.ExpiresUtc = _systemClock.UtcNow.Add(_globalSettings.TimeOut);
                ctx.ShouldRenew           = true;
            },
            OnSigningIn = ctx =>
            {
                // occurs when sign in is successful but before the ticket is written to the outbound cookie
                ClaimsIdentity?backOfficeIdentity = ctx.Principal?.GetUmbracoIdentity();
                if (backOfficeIdentity != null)
                {
                    // generate a session id and assign it
                    // create a session token - if we are configured and not in an upgrade state then use the db, otherwise just generate one
                    Guid session = _runtimeState.Level == RuntimeLevel.Run
                        ? _userService.CreateLoginSession(
                        backOfficeIdentity.GetId() !.Value,
                        _ipResolver.GetCurrentRequestIpAddress())
                        : Guid.NewGuid();

                    // add our session claim
                    backOfficeIdentity.AddClaim(new Claim(
                                                    Constants.Security.SessionIdClaimType,
                                                    session.ToString(),
                                                    ClaimValueTypes.String,
                                                    Constants.Security.BackOfficeAuthenticationType,
                                                    Constants.Security.BackOfficeAuthenticationType,
                                                    backOfficeIdentity));

                    // since it is a cookie-based authentication add that claim
                    backOfficeIdentity.AddClaim(new Claim(
                                                    ClaimTypes.CookiePath,
                                                    "/",
                                                    ClaimValueTypes.String,
                                                    Constants.Security.BackOfficeAuthenticationType,
                                                    Constants.Security.BackOfficeAuthenticationType,
                                                    backOfficeIdentity));
                }

                return(Task.CompletedTask);
            },
            OnSignedIn = ctx =>
            {
                // occurs when sign in is successful and after the ticket is written to the outbound cookie

                // When we are signed in with the cookie, assign the principal to the current HttpContext
                ctx.HttpContext.SetPrincipalForRequest(ctx.Principal);

                return(Task.CompletedTask);
            },
            OnSigningOut = ctx =>
            {
                // Clear the user's session on sign out
                if (ctx.HttpContext?.User?.Identity != null)
                {
                    var claimsIdentity = ctx.HttpContext.User.Identity as ClaimsIdentity;
                    var sessionId      = claimsIdentity?.FindFirstValue(Constants.Security.SessionIdClaimType);
                    if (sessionId.IsNullOrWhiteSpace() == false && Guid.TryParse(sessionId, out Guid guidSession))
                    {
                        _userService.ClearLoginSession(guidSession);
                    }
                }

                // Remove all of our cookies
                var cookies = new[]
                {
                    BackOfficeSessionIdValidator.CookieName, _securitySettings.AuthCookieName,
                    Constants.Web.PreviewCookieName, Constants.Security.BackOfficeExternalCookieName,
                    Constants.Web.AngularCookieName, Constants.Web.CsrfValidationCookieName
                };
                foreach (var cookie in cookies)
                {
                    ctx.Options.CookieManager.DeleteCookie(ctx.HttpContext !, cookie, new CookieOptions {
                        Path = "/"
                    });
                }

                return(Task.CompletedTask);
            }
        };
    }