public async Task OnActionExecutionAsync_WhenActionDoesNotMatch_BlocksAndReturns_RecaptchaValidationFailedResult() { // Arrange var action = "submit"; var httpContext = new DefaultHttpContext(); httpContext.Request.Headers.Add(RecaptchaServiceConstants.TokenKeyName, TokenValue); _actionExecutingContext.HttpContext = httpContext; _recaptchaServiceMock = new Mock <IRecaptchaService>(); _recaptchaServiceMock.Setup(service => service.ValidateRecaptchaResponse(It.Is <string>(s => s == TokenValue), null)) .ReturnsAsync(new ValidationResponse { Success = true }) .Verifiable(); _filter = new ValidateRecaptchaFilter(_recaptchaServiceMock.Object, _optionsMock.Object, _logger); _filter.Action = action; // Act await _filter.OnActionExecutionAsync(_actionExecutingContext, _actionExecutionDelegate); // Assert _recaptchaServiceMock.Verify(); Assert.IsInstanceOf <IRecaptchaValidationFailedResult>(_actionExecutingContext.Result); }
public async Task TestPostWrongContentType(string httpMethod) { var recaptchaService = new Mock <IRecaptchaValidationService>(MockBehavior.Strict); recaptchaService .Setup(a => a.ValidateResponseAsync(It.IsAny <string>(), It.IsAny <string>())) .Verifiable(); var sink = new TestSink(); var loggerFactory = new TestLoggerFactory(sink, enabled: true); var filter = new ValidateRecaptchaFilter(recaptchaService.Object, loggerFactory); var httpContext = new DefaultHttpContext(); httpContext.Request.Method = httpMethod; httpContext.Request.ContentType = "Wrong content type"; var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor()); var context = new AuthorizationFilterContext(actionContext, new[] { filter }); recaptchaService.Verify(a => a.ValidateResponseAsync(It.IsAny <string>(), It.IsAny <string>()), Times.Never()); await filter.OnAuthorizationAsync(context); Assert.Empty(sink.Scopes); Assert.Single(sink.Writes); Assert.Equal($"Recaptcha validation failed. The content type is 'Wrong content type', it should be form content.", sink.Writes[0].State?.ToString()); var httpBadRequest = Assert.IsType <BadRequestResult>(context.Result); Assert.Equal(StatusCodes.Status400BadRequest, httpBadRequest.StatusCode); Assert.True(context.ModelState.IsValid); Assert.Empty(context.ModelState); }
public async Task VerifyAsyncReturnsBoolean(bool success) { var reCaptchaServiceMock = new Mock <IReCaptchaService>(); reCaptchaServiceMock.Setup(x => x.VerifyAsync(It.IsAny <string>())).Returns(Task.FromResult(success)); var filter = new ValidateRecaptchaFilter(reCaptchaServiceMock.Object, "", ""); var expected = new StringValues("123"); var httpContextMock = new Mock <HttpContext>(); var pageContext = CreatePageContext(new ActionContext(httpContextMock.Object, new RouteData(), new ActionDescriptor())); var model = new Mock <PageModel>(); var pageHandlerExecutedContext = new PageHandlerExecutedContext( pageContext, Array.Empty <IFilterMetadata>(), new HandlerMethodDescriptor(), model.Object); var actionExecutingContext = CreatePageHandlerExecutingContext(httpContextMock, pageContext, expected, model); PageHandlerExecutionDelegate next = () => Task.FromResult(pageHandlerExecutedContext); await filter.OnPageHandlerExecutionAsync(actionExecutingContext, next); reCaptchaServiceMock.Verify(x => x.VerifyAsync(It.IsAny <string>()), Times.Once); }
public async Task OnActionExecutionAsync_WhenValidationSuccess_ReturnsOkResult_WithoutAddingResponseToArguments() { // Arrange var httpContext = new DefaultHttpContext(); httpContext.Request.Headers.Add(RecaptchaServiceConstants.TokenKeyName, TokenValue); _actionExecutingContext.HttpContext = httpContext; _recaptchaServiceMock = new Mock <IRecaptchaService>(); _recaptchaServiceMock.Setup(service => service.ValidateRecaptchaResponse(It.Is <string>(s => s == TokenValue), null)) .ReturnsAsync(new ValidationResponse { Success = true }) .Verifiable(); _filter = new ValidateRecaptchaFilter(_recaptchaServiceMock.Object, _optionsMock.Object, _logger); // Act await _filter.OnActionExecutionAsync(_actionExecutingContext, _actionExecutionDelegate); // Assert _recaptchaServiceMock.Verify(); Assert.IsInstanceOf <OkResult>(_actionExecutingContext.Result); Assert.AreEqual(0, _actionExecutingContext.ActionArguments.Count); }
public async Task OnActionExecutionAsync_ShouldAddRemoteIp() { // Arrange var ip = "144.22.5.213"; var httpContext = new DefaultHttpContext(); httpContext.Request.Headers.Add(RecaptchaServiceConstants.TokenKeyName, TokenValue); httpContext.Connection.RemoteIpAddress = IPAddress.Parse(ip); _actionExecutingContext.HttpContext = httpContext; _optionsMock.SetupGet(options => options.CurrentValue) .Returns(new RecaptchaOptions { UseRemoteIp = true }); _recaptchaServiceMock = new Mock <IRecaptchaService>(); _recaptchaServiceMock.Setup(service => service.ValidateRecaptchaResponse(It.Is <string>(s => s == TokenValue), It.Is <string>(s => s == ip))) .ReturnsAsync(new ValidationResponse { Success = true }) .Verifiable(); _filter = new ValidateRecaptchaFilter(_recaptchaServiceMock.Object, _optionsMock.Object, _logger); // Act await _filter.OnActionExecutionAsync(_actionExecutingContext, _actionExecutionDelegate); // Assert _recaptchaServiceMock.Verify(); Assert.IsInstanceOf <OkResult>(_actionExecutingContext.Result); Assert.AreEqual(0, _actionExecutingContext.ActionArguments.Count); }
public void InitializeTest() { _logger = new LoggerFactory().CreateLogger <ValidateRecaptchaFilter>(); _optionsMock = new Mock <IOptionsMonitor <RecaptchaOptions> >(); _optionsMock.SetupGet(options => options.CurrentValue) .Returns(new RecaptchaOptions()); _recaptchaServiceMock = new Mock <IRecaptchaService>(); _recaptchaServiceMock.Setup(service => service.ValidateRecaptchaResponse(It.Is <string>(s => s == TokenValue), null)) .ReturnsAsync(new ValidationResponse { Success = true }) .Verifiable(); _actionContext = new ActionContext( new DefaultHttpContext(), Mock.Of <RouteData>(), Mock.Of <ActionDescriptor>(), new ModelStateDictionary()); _actionExecutingContext = new ActionExecutingContext(_actionContext, new List <IFilterMetadata>(), new Dictionary <string, object>(), Mock.Of <Controller>()) { Result = new OkResult() // It will return ok unless during code execution you change this when by condition }; #pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously _actionExecutionDelegate = async() => { return(new ActionExecutedContext(_actionContext, new List <IFilterMetadata>(), Mock.Of <Controller>())); }; #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously _filter = new ValidateRecaptchaFilter(_recaptchaServiceMock.Object, _optionsMock.Object, _logger); }
public async Task TestPostSucessNoIp(string httpMethod) { var recaptchaResponse = Guid.NewGuid().ToString(); var recaptchaService = new Mock <IRecaptchaValidationService>(MockBehavior.Strict); recaptchaService .Setup(a => a.ValidateResponseAsync(recaptchaResponse, null)) .Returns(Task.FromResult(0)) .Verifiable(); var filter = new ValidateRecaptchaFilter(recaptchaService.Object, NullLoggerFactory.Instance); var httpContext = new DefaultHttpContext(); httpContext.Request.Method = httpMethod; httpContext.Request.HttpContext.Connection.RemoteIpAddress = null; httpContext.Request.ContentType = "application/x-www-form-urlencoded"; httpContext.Request.Form = new FormCollection(new Dictionary <string, StringValues> { { "g-recaptcha-response", recaptchaResponse } }); var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor()); var context = new AuthorizationFilterContext(actionContext, new[] { filter }); await filter.OnAuthorizationAsync(context); recaptchaService.Verify(); Assert.Null(context.Result); Assert.True(context.ModelState.IsValid); Assert.Empty(context.ModelState); }
public async Task TestPostFailInvalidResponse(string httpMethod) { var recaptchaResponse = Guid.NewGuid().ToString(); var ipAddress = new IPAddress(new byte[] { 127, 0, 0, 1 }); var errorMessage = Guid.NewGuid().ToString(); var validationMessage = Guid.NewGuid().ToString(); var recaptchaService = new Mock <IRecaptchaValidationService>(MockBehavior.Strict); recaptchaService .Setup(a => a.ValidateResponseAsync(recaptchaResponse, ipAddress.ToString())) .Throws(new RecaptchaValidationException(errorMessage, true)) .Verifiable(); recaptchaService .Setup(a => a.ValidationMessage) .Returns(validationMessage) .Verifiable(); var configurationService = new Mock <IRecaptchaConfigurationService>(MockBehavior.Strict); configurationService .Setup(a => a.Enabled) .Returns(true) .Verifiable(); var sink = new TestSink(); var loggerFactory = new TestLoggerFactory(sink, enabled: true); var filter = new ValidateRecaptchaFilter(recaptchaService.Object, configurationService.Object, loggerFactory); var httpContext = new DefaultHttpContext(); httpContext.Request.Method = httpMethod; httpContext.Request.HttpContext.Connection.RemoteIpAddress = ipAddress; httpContext.Request.ContentType = "application/x-www-form-urlencoded"; httpContext.Request.Form = new FormCollection(new Dictionary <string, StringValues> { { "g-recaptcha-response", recaptchaResponse } }); var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor()); var context = new AuthorizationFilterContext(actionContext, new[] { filter }); await filter.OnAuthorizationAsync(context); recaptchaService.Verify(); Assert.Empty(sink.Scopes); Assert.Single(sink.Writes); Assert.Equal($"Recaptcha validation failed. {errorMessage}", sink.Writes[0].State?.ToString()); Assert.Null(context.Result); Assert.False(context.ModelState.IsValid); Assert.NotEmpty(context.ModelState); Assert.NotNull(context.ModelState["g-recaptcha-response"]); Assert.Equal(1, context.ModelState["g-recaptcha-response"].Errors.Count); Assert.Equal(validationMessage, context.ModelState["g-recaptcha-response"].Errors.First().ErrorMessage); }
public async Task VerifyAsyncReturnsBoolean(bool success) { var reCaptchaServiceMock = new Mock <IReCaptchaService>(); reCaptchaServiceMock.Setup(x => x.VerifyAsync(It.IsAny <string>())).Returns(Task.FromResult(success)); var filter = new ValidateRecaptchaFilter(reCaptchaServiceMock.Object, "", ""); var expected = new StringValues("123"); var httpContextMock = new Mock <HttpContext>(); var modelState = new ModelStateDictionary(); var actionContext = CreateActionContext(httpContextMock, modelState); var actionExecutingContext = CreateActionExecutingContext(httpContextMock, actionContext, expected); Task <ActionExecutedContext> Next() { var ctx = new ActionExecutedContext(actionContext, new List <IFilterMetadata>(), Mock.Of <Controller>()); return(Task.FromResult(ctx)); } await filter.OnActionExecutionAsync(actionExecutingContext, Next); reCaptchaServiceMock.Verify(x => x.VerifyAsync(It.IsAny <string>()), Times.Once); if (!success) { Assert.Equal(1, modelState.ErrorCount); } }
public async Task TestPostSkipping(string httpMethod) { var recaptchaService = new Mock <IRecaptchaValidationService>(MockBehavior.Strict); recaptchaService .Setup(a => a.ValidateResponseAsync(It.IsAny <string>(), It.IsAny <string>())) .Returns(Task.FromResult(0)) .Verifiable(); var configurationService = new Mock <IRecaptchaConfigurationService>(MockBehavior.Strict); configurationService .Setup(a => a.Enabled) .Returns(true) .Verifiable(); var filter = new ValidateRecaptchaFilter(recaptchaService.Object, configurationService.Object, NullLoggerFactory.Instance); var actionContext = new ActionContext(new DefaultHttpContext(), new RouteData(), new ActionDescriptor()); actionContext.HttpContext.Request.Method = httpMethod; var context = new AuthorizationFilterContext(actionContext, new[] { filter }); await filter.OnAuthorizationAsync(context); recaptchaService.Verify(a => a.ValidateResponseAsync(It.IsAny <string>(), It.IsAny <string>()), Times.Never()); Assert.Null(context.Result); Assert.True(context.ModelState.IsValid); Assert.Empty(context.ModelState); }
public async Task TestPostFailMissingResponse(string httpMethod) { var recaptchaResponse = string.Empty; var ipAddress = new IPAddress(new byte[] { 127, 0, 0, 1 }); var errorMessage = Guid.NewGuid().ToString(); var validationMessage = Guid.NewGuid().ToString(); var recaptchaService = new Mock <IRecaptchaValidationService>(MockBehavior.Strict); recaptchaService .Setup(a => a.ValidateResponseAsync(It.IsAny <string>(), It.IsAny <string>())) .Returns(Task.FromResult(0)) .Verifiable(); recaptchaService .Setup(a => a.ValidationMessage) .Returns(validationMessage) .Verifiable(); var configurationService = new Mock <IRecaptchaConfigurationService>(MockBehavior.Strict); configurationService .Setup(a => a.Enabled) .Returns(true) .Verifiable(); var loggerFactory = GetLoggerFactory <ValidateRecaptchaFilter>(); var filter = new ValidateRecaptchaFilter(recaptchaService.Object, configurationService.Object, loggerFactory.Object); var httpContext = new DefaultHttpContext(); httpContext.Request.Method = httpMethod; httpContext.Request.HttpContext.Connection.RemoteIpAddress = ipAddress; httpContext.Request.ContentType = "application/x-www-form-urlencoded"; httpContext.Request.Form = new FormCollection(new Dictionary <string, StringValues> { { "g-recaptcha-response", recaptchaResponse } }); var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor()); var context = new AuthorizationFilterContext(actionContext, new[] { filter }); await filter.OnAuthorizationAsync(context); recaptchaService.Verify(a => a.ValidateResponseAsync(It.IsAny <string>(), It.IsAny <string>()), Times.Never()); Assert.Null(context.Result); Assert.False(context.ModelState.IsValid); Assert.NotEmpty(context.ModelState); Assert.NotNull(context.ModelState["g-recaptcha-response"]); Assert.Equal(1, context.ModelState["g-recaptcha-response"].Errors.Count); Assert.Equal(validationMessage, context.ModelState["g-recaptcha-response"].Errors.First().ErrorMessage); }
public void Construction_IsSuccessful() { // Arrange // Act var instance = new ValidateRecaptchaFilter(_recaptchaServiceMock.Object, _optionsMock.Object, _logger); // Assert Assert.NotNull(instance); }
public ValidateRecaptchaFilterTests() { _stubVerifySite = new Mock <ISiteVerifier>(); var options = new ValidateRecaptchaFilterOptions { ErrorMessage = ErrorMessage, HostName = HostName }; _filter = new ValidateRecaptchaFilter(_stubVerifySite.Object, options); _context = CreateContext(); }
public async Task TestPostFail(string httpMethod) { var recaptchaResponse = Guid.NewGuid().ToString(); var ipAddress = new IPAddress(new byte[] { 127, 0, 0, 1 }); var errorMessage = Guid.NewGuid().ToString(); var recaptchaService = new Mock <IRecaptchaValidationService>(MockBehavior.Strict); recaptchaService .Setup(a => a.ValidateResponseAsync(recaptchaResponse, ipAddress.ToString())) .Throws(new RecaptchaValidationException(errorMessage, false)) .Verifiable(); var configurationService = new Mock <IRecaptchaConfigurationService>(MockBehavior.Strict); configurationService .Setup(a => a.Enabled) .Returns(true) .Verifiable(); var logger = new TestLogger(); var loggerFactory = new TestLoggerFactory <ValidateRecaptchaFilter>(logger); var filter = new ValidateRecaptchaFilter(recaptchaService.Object, configurationService.Object, loggerFactory); var httpContext = new DefaultHttpContext(); httpContext.Request.Method = httpMethod; httpContext.Request.HttpContext.Connection.RemoteIpAddress = ipAddress; httpContext.Request.ContentType = "application/x-www-form-urlencoded"; httpContext.Request.Form = new FormCollection(new Dictionary <string, StringValues> { { "g-recaptcha-response", recaptchaResponse } }); var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor()); var context = new AuthorizationFilterContext(actionContext, new[] { filter }); await filter.OnAuthorizationAsync(context); recaptchaService.Verify(); Assert.Equal(0, logger.ScopeCount); Assert.Single(logger.Log); Assert.Equal($"Recaptcha validation failed. {errorMessage}", logger.Log[0]); var httpBadRequest = Assert.IsType <BadRequestResult>(context.Result); Assert.Equal(StatusCodes.Status400BadRequest, httpBadRequest.StatusCode); Assert.True(context.ModelState.IsValid); Assert.Empty(context.ModelState); }
public async Task OnActionExecutionAsync_WhenActionDoesNotMatch_ContinuesAndAddsResponseToArguments() { // Arrange var action = "submit"; var httpContext = new DefaultHttpContext(); httpContext.Request.Headers.Add(RecaptchaServiceConstants.TokenKeyName, TokenValue); _actionExecutingContext.HttpContext = httpContext; _recaptchaServiceMock = new Mock <IRecaptchaService>(); _recaptchaServiceMock.Setup(service => service.ValidateRecaptchaResponse(It.Is <string>(s => s == TokenValue), null)) .ReturnsAsync(new ValidationResponse { Success = true, ErrorMessages = new List <string> { "invalid-input-response" } }) .Verifiable(); _filter = new ValidateRecaptchaFilter(_recaptchaServiceMock.Object, _optionsMock.Object, _logger) { OnValidationFailedAction = ValidationFailedAction.ContinueRequest, Action = action }; _actionExecutingContext.ActionArguments.Add("argumentName", new ValidationResponse { Success = true }); // Act await _filter.OnActionExecutionAsync(_actionExecutingContext, _actionExecutionDelegate); // Assert _recaptchaServiceMock.Verify(); Assert.IsInstanceOf <OkResult>(_actionExecutingContext.Result); Assert.IsTrue((_actionExecutingContext.ActionArguments["argumentName"] as ValidationResponse).Success); Assert.GreaterOrEqual((_actionExecutingContext.ActionArguments["argumentName"] as ValidationResponse).Errors.Count(), 1); Assert.AreEqual(ValidationError.InvalidInputResponse, (_actionExecutingContext.ActionArguments["argumentName"] as ValidationResponse).Errors.First()); }
public async Task OnActionExecutionAsync_WhenValidationSuccess_ContinuesAndAddsResponseToArguments() { // Arrange var action = "submit"; var httpContext = new DefaultHttpContext(); httpContext.Request.Headers.Add(RecaptchaServiceConstants.TokenKeyName, TokenValue); _actionExecutingContext.HttpContext = httpContext; _recaptchaServiceMock = new Mock <IRecaptchaService>(); _recaptchaServiceMock.Setup(service => service.ValidateRecaptchaResponse(It.Is <string>(s => s == TokenValue), null)) .ReturnsAsync(new ValidationResponse { Success = true, Action = action }) .Verifiable(); _filter = new ValidateRecaptchaFilter(_recaptchaServiceMock.Object, _optionsMock.Object, _logger) { Action = action }; _actionExecutingContext.ActionArguments.Add("argumentName", new ValidationResponse { Success = false, Action = string.Empty }); // Act await _filter.OnActionExecutionAsync(_actionExecutingContext, _actionExecutionDelegate); // Assert _recaptchaServiceMock.Verify(); Assert.IsInstanceOf <OkResult>(_actionExecutingContext.Result); Assert.IsTrue((_actionExecutingContext.ActionArguments["argumentName"] as ValidationResponse).Success); Assert.AreEqual(action, (_actionExecutingContext.ActionArguments["argumentName"] as ValidationResponse).Action); Assert.AreEqual((_actionExecutingContext.ActionArguments["argumentName"] as ValidationResponse).Errors.Count(), 0); }
public async Task TestPostWrongContentType(string httpMethod) { var recaptchaService = new Mock <IRecaptchaValidationService>(MockBehavior.Strict); recaptchaService .Setup(a => a.ValidateResponseAsync(It.IsAny <string>(), It.IsAny <string>())) .Verifiable(); var configurationService = new Mock <IRecaptchaConfigurationService>(MockBehavior.Strict); configurationService .Setup(a => a.Enabled) .Returns(true) .Verifiable(); var loggerFactory = GetLoggerFactory <ValidateRecaptchaFilter>(); var filter = new ValidateRecaptchaFilter(recaptchaService.Object, configurationService.Object, loggerFactory.Object); var httpContext = new DefaultHttpContext(); httpContext.Request.Method = httpMethod; httpContext.Request.ContentType = "Wrong content type"; var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor()); var context = new AuthorizationFilterContext(actionContext, new[] { filter }); recaptchaService.Verify(a => a.ValidateResponseAsync(It.IsAny <string>(), It.IsAny <string>()), Times.Never()); await filter.OnAuthorizationAsync(context); var httpBadRequest = Assert.IsType <BadRequestResult>(context.Result); Assert.Equal(StatusCodes.Status400BadRequest, httpBadRequest.StatusCode); Assert.True(context.ModelState.IsValid); Assert.Empty(context.ModelState); }
public async Task DoNotValidateIfDisabled() { var recaptchaResponse = string.Empty; var ipAddress = new IPAddress(new byte[] { 127, 0, 0, 1 }); var recaptchaService = new Mock <IRecaptchaValidationService>(MockBehavior.Strict); var configurationService = new Mock <IRecaptchaConfigurationService>(MockBehavior.Strict); configurationService .Setup(a => a.Enabled) .Returns(false) .Verifiable(); var loggerFactory = GetLoggerFactory <ValidateRecaptchaFilter>(); var filter = new ValidateRecaptchaFilter(recaptchaService.Object, configurationService.Object, loggerFactory.Object); var httpContext = new DefaultHttpContext(); httpContext.Request.Method = "POST"; httpContext.Request.HttpContext.Connection.RemoteIpAddress = ipAddress; httpContext.Request.ContentType = "application/x-www-form-urlencoded"; httpContext.Request.Form = new FormCollection(new Dictionary <string, StringValues> { { "g-recaptcha-response", recaptchaResponse } }); var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor()); var context = new AuthorizationFilterContext(actionContext, new[] { filter }); await filter.OnAuthorizationAsync(context); Assert.Null(context.Result); configurationService.Verify(); recaptchaService.Verify(); }