Exemple #1
0
        protected async override Task <bool> ValidateContextAsync(CustomTokenRequestValidationContext context,
                                                                  CustomValidatorRequestContext validatorContext)
        {
            var email = context.Result.ValidatedRequest.Subject?.GetDisplayName()
                        ?? context.Result.ValidatedRequest.ClientClaims?.FirstOrDefault(claim => claim.Type == JwtClaimTypes.Email)?.Value;

            if (!string.IsNullOrWhiteSpace(email))
            {
                validatorContext.User = await _userManager.FindByEmailAsync(email);
            }
            return(validatorContext.User != null);
        }
        public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
        {
            if (!AuthEmailHeaderIsValid(context))
            {
                context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant,
                                                           "Auth-Email header invalid.");
                return;
            }

            var user = await _userManager.FindByEmailAsync(context.UserName.ToLowerInvariant());

            var validatorContext = new CustomValidatorRequestContext
            {
                User        = user,
                KnownDevice = await KnownDeviceAsync(user, context.Request)
            };
            string bypassToken = null;

            if (!validatorContext.KnownDevice &&
                _captchaValidationService.RequireCaptchaValidation(_currentContext, user))
            {
                var captchaResponse = context.Request.Raw["captchaResponse"]?.ToString();

                if (string.IsNullOrWhiteSpace(captchaResponse))
                {
                    context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "Captcha required.",
                                                               new Dictionary <string, object>
                    {
                        { _captchaValidationService.SiteKeyResponseKeyName, _captchaValidationService.SiteKey },
                    });
                    return;
                }

                validatorContext.CaptchaResponse = await _captchaValidationService.ValidateCaptchaResponseAsync(
                    captchaResponse, _currentContext.IpAddress, null);

                if (!validatorContext.CaptchaResponse.Success)
                {
                    await BuildErrorResultAsync("Captcha is invalid. Please refresh and try again", false, context, null);

                    return;
                }
                bypassToken = _captchaValidationService.GenerateCaptchaBypassToken(user);
            }

            await ValidateAsync(context, context.Request, validatorContext);

            if (context.Result.CustomResponse != null && bypassToken != null)
            {
                context.Result.CustomResponse["CaptchaBypassToken"] = bypassToken;
            }
        }
        protected async override Task <bool> ValidateContextAsync(ResourceOwnerPasswordValidationContext context,
                                                                  CustomValidatorRequestContext validatorContext)
        {
            if (string.IsNullOrWhiteSpace(context.UserName) || validatorContext.User == null)
            {
                return(false);
            }

            if (!await _userService.CheckPasswordAsync(validatorContext.User, context.Password))
            {
                return(false);
            }

            return(true);
        }
        protected async Task ValidateAsync(T context, ValidatedTokenRequest request,
                                           CustomValidatorRequestContext validatorContext)
        {
            var isBot = (validatorContext.CaptchaResponse?.IsBot ?? false);

            if (isBot)
            {
                _logger.LogInformation(Constants.BypassFiltersEventId,
                                       "Login attempt for {0} detected as a captcha bot with score {1}.",
                                       request.UserName, validatorContext.CaptchaResponse.Score);
            }

            var twoFactorToken    = request.Raw["TwoFactorToken"]?.ToString();
            var twoFactorProvider = request.Raw["TwoFactorProvider"]?.ToString();
            var twoFactorRemember = request.Raw["TwoFactorRemember"]?.ToString() == "1";
            var twoFactorRequest  = !string.IsNullOrWhiteSpace(twoFactorToken) &&
                                    !string.IsNullOrWhiteSpace(twoFactorProvider);

            var valid = await ValidateContextAsync(context, validatorContext);

            var user = validatorContext.User;

            if (!valid)
            {
                await UpdateFailedAuthDetailsAsync(user, false, !validatorContext.KnownDevice);
            }
            if (!valid || isBot)
            {
                await BuildErrorResultAsync("Username or password is incorrect. Try again.", false, context, user);

                return;
            }

            var(isTwoFactorRequired, requires2FABecauseNewDevice, twoFactorOrganization) = await RequiresTwoFactorAsync(user, request);

            if (isTwoFactorRequired)
            {
                // Just defaulting it
                var twoFactorProviderType = TwoFactorProviderType.Authenticator;
                if (!twoFactorRequest || !Enum.TryParse(twoFactorProvider, out twoFactorProviderType))
                {
                    await BuildTwoFactorResultAsync(user, twoFactorOrganization, context, requires2FABecauseNewDevice);

                    return;
                }

                BeforeVerifyTwoFactor(user, twoFactorProviderType, requires2FABecauseNewDevice);

                var verified = await VerifyTwoFactor(user, twoFactorOrganization,
                                                     twoFactorProviderType, twoFactorToken);

                AfterVerifyTwoFactor(user, twoFactorProviderType, requires2FABecauseNewDevice);

                if ((!verified || isBot) && twoFactorProviderType != TwoFactorProviderType.Remember)
                {
                    await UpdateFailedAuthDetailsAsync(user, true, !validatorContext.KnownDevice);
                    await BuildErrorResultAsync("Two-step token is invalid. Try again.", true, context, user);

                    return;
                }
                else if ((!verified || isBot) && twoFactorProviderType == TwoFactorProviderType.Remember)
                {
                    // Delay for brute force.
                    await Task.Delay(2000);
                    await BuildTwoFactorResultAsync(user, twoFactorOrganization, context, requires2FABecauseNewDevice);

                    return;
                }
            }
            else
            {
                twoFactorRequest  = false;
                twoFactorRemember = false;
                twoFactorToken    = null;
            }

            // Returns true if can finish validation process
            if (await IsValidAuthTypeAsync(user, request.GrantType))
            {
                var device = await SaveDeviceAsync(user, request);

                if (device == null)
                {
                    await BuildErrorResultAsync("No device information provided.", false, context, user);

                    return;
                }
                await BuildSuccessResultAsync(user, context, device, twoFactorRequest&& twoFactorRemember);
            }
            else
            {
                SetSsoResult(context, new Dictionary <string, object>
                {
                    {
                        "ErrorModel", new ErrorResponseModel("SSO authentication is required.")
                    }
                });
            }
        }
 protected abstract Task <bool> ValidateContextAsync(T context, CustomValidatorRequestContext validatorContext);