/// <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);
            }
        }
Beispiel #2
0
        public async Task <ActionResult <UserDetail> > PostLogin(LoginModel loginModel)
        {
            // Sign the user in with username/password, this also gives a chance for developers to
            // custom verify the credentials and auto-link user accounts with a custom IBackOfficePasswordChecker
            SignInResult result = await _signInManager.PasswordSignInAsync(
                loginModel.Username, loginModel.Password, isPersistent : true, lockoutOnFailure : true);

            if (result.Succeeded)
            {
                // return the user detail
                return(GetUserDetail(_userService.GetByUsername(loginModel.Username)));
            }

            if (result.RequiresTwoFactor)
            {
                var twofactorView = _backOfficeTwoFactorOptions.GetTwoFactorView(loginModel.Username);
                if (twofactorView.IsNullOrWhiteSpace())
                {
                    return(new ValidationErrorResult($"The registered {typeof(IBackOfficeTwoFactorOptions)} of type {_backOfficeTwoFactorOptions.GetType()} did not return a view for two factor auth "));
                }

                IUser attemptedUser = _userService.GetByUsername(loginModel.Username);

                // create a with information to display a custom two factor send code view
                var verifyResponse = new ObjectResult(new
                {
                    twoFactorView = twofactorView,
                    userId        = attemptedUser.Id
                })
                {
                    StatusCode = StatusCodes.Status402PaymentRequired
                };

                return(verifyResponse);
            }

            // TODO: We can check for these and respond differently if we think it's important
            //  result.IsLockedOut
            //  result.IsNotAllowed

            // return BadRequest (400), we don't want to return a 401 because that get's intercepted
            // by our angular helper because it thinks that we need to re-perform the request once we are
            // authorized and we don't want to return a 403 because angular will show a warning message indicating
            // that the user doesn't have access to perform this function, we just want to return a normal invalid message.
            return(BadRequest());
        }