michaelvs97 / aspnetcore.recaptcha Goto Github PK
View Code? Open in Web Editor NEWGoogle ReCAPTCHA v2/v3 Library for .NET Core 3.x/5.x
Home Page: https://www.nuget.org/packages/AspNetCore.ReCaptcha/
License: MIT License
Google ReCAPTCHA v2/v3 Library for .NET Core 3.x/5.x
Home Page: https://www.nuget.org/packages/AspNetCore.ReCaptcha/
License: MIT License
Any plans to update to .NET 8.0 and Microsoft.Extensions.Options to 8.0.0?
I am trying to add it to my net6 core razor site and looking to see the response from google or what object it may be in the ModelState.IsValid properties. For some reason it dosent seem to be working.
This is possibly (almost certainly) a result of my stupidity, but I'm unable to validate a V3 token when submitted via AJAX. Excuse terminology - I'm not a programmer...
On my Razor form, I have this:
var token = document.querySelector('input[name="__RequestVerificationToken"]').value;
fetch('/auth/register', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: emailField.value,
password: passwordField.value,
token: token
})
})
This is capturing the token and sending it back, as follows:
However, any call to GetVerifyResponseAsync results in an invalid-input-response error code:
The key and secret are correct - they're working on another page that uses a traditional form post submission.
Any ideas, or am I just terminally dumb?
Describe the bug
If I fill out all the fields of my form, except the captcha, there is no client side validation. The browser goes to the server, where I can use ModelState.IsValid to find the error. But I would like to prevent the browser going to the server.
To Reproduce
Steps to reproduce the behavior:
builder.Services.AddReCaptcha(builder.Configuration.GetSection("ReCaptcha"));
"ReCaptcha": {
"SiteKey": "my site key",
"SecretKey": "my secret key",
"Version": "v2", // The ReCaptcha version to use, can be v2, v2invisible or v3
"UseRecaptchaNet": false, // Value whether to use google recaptcha or recaptcha.net
"ScoreThreshold": 0.5 // Only applicable for recaptcha v3, specifies the score threshold when it is considered successful
}
@using AspNetCore.ReCaptcha
and @Html.ReCaptcha()
(this one inside the form)[ValidateReCaptcha]
just above public class contactModel : PageModel
OnPost()
action, addif (!ModelState.IsValid)
{
TempData["mensajeError"] = "An error ocurred, did you solve the captcha?";
return Page();
}
Expected behavior
It would be nice to have an option to add an asp-validation-for
tag or an asp:RequiredFieldValidator
tag in order to add client-side validation for the captcha.
Or is there a way with javascript to check that the captcha was solved and if it wasn't, show a red message below the captcha without having the browser go back to the server?
Desktop (please complete the following information):
Describe the bug
It looks like using www.recaptcha.net
results in 404 error on the siteverify POST call.
Setting the width would be a great feature for presentations. Or maybe just enter the component on a div
Hi there - apologies for nuking the template. Hopefully this inquiry is OK.
I'd like to contribute two features:
true
for backward compatibility. If false
, the HTML would not be rendered and the action filter would not validate the submission. Note that it looks like this has also been requested here: #53AutoTheme
property with corresponding auto-theme=true
attribute in the tag helper. If true, inject a script that sets the theme to "dark" based on e.g. window.matchMedia('(prefers-color-scheme: dark)').matches
We're handling these in our application but it would be cleaner if implemented in the library.
If you are interested in these features I'd be happy to contribute. Let me know if the above implementations sound good and if I should then just stage two typical PRs into a develop
branch or follow some other workflow.
Would you have an idea how I'd go about using this in Blazor?
Its a nice neat library would be great to get it working.
Is your feature request related to a problem? Please describe.
Hello, this plugin is great, just it lowers my "PageSpeed" score a lot.
I am talking about the Recaptcha v3.
Describe the solution you'd like
If the <script> tag that calls the Recaptha function is "async" (or better: defer) the issue does not occur.
Thanks!
We do want to configure the underlying httpclient to add some Polly backoff strategies and circuit breakers. However, the IHttpClientBuilder
returned by AddHttpClient
is currently not exposed to further configuration.
Please consider an overload in AddReCaptcha(this IServiceCollection services, Action<ReCaptchaSettings> configureOptions)
taking in an Action to further configure the httpclient.
Describe the bug
I'm using .net 6 i used previous version everything was fine today(feb 16) i updated the package and when i'm trying to sumbit
the form second time i'm getting error. and i'm not able to submit the form. this might be issue on my end as well i'm new to coding
so sorry if it is not in your end
To Reproduce
Steps to reproduce the behavior:
Expected behavior
A clear and concise description of what you expected to happen.
Screenshots
If applicable, add screenshots to help explain your problem.
Desktop (please complete the following information):
Smartphone (please complete the following information):
Additional context
Add any other context about the problem here.
Hi guys. I am trying to use your package but I have a question. How do I tell if the validation on the recaptcha was a success or not ?
I added the [ValidateReCaptcha] class over my method but I want to get the response. Also I am trying to implement the recaptcha on two different parts of my website. One post data straight to the controller and another post data to the controller using ajax. How can I handle this?. Please help
I don't think it's really an issue but rather something wrong in my code. Anyway, I've been trying to fix it on my own, with a help on forums, unfortunatelly without any luck. So as a last resort I'm asking here, mayble you'll find few minutes to check what's wrong. I have your package installed in Asp.Net Core 3.1 Razor Pages proejct. For some reason, no "Confirm you're a human" checkbox appears (or anything similiar), the only visual confirmation that your package is working is working is ReCaptcha badge saying that site is protected. I'm pretty sure I've done everything according to your instruction, don't know what to ckeck next. Here's the forum post I created (unsolved yet), here's the page I'm having problem with (reCaptcha should be displayed above "Submit" button), and here's source code.
Describe the bug
Not sure if this is a bug or feature enhancement. Currently when an ajax action is called, the token doesn't get refreshed after a form postback.
From Google's documentation,
"Note: reCAPTCHA tokens expire after two minutes. If you're protecting an action with reCAPTCHA, make sure to call execute when the user takes the action rather than on page load."
To Reproduce
Steps to reproduce the behavior:
Expected behavior
Expected any get/post action on a form will extend the 2min default expiry by calling "execute"
Desktop (please complete the following information):
How to implement the package on Razor Pages using localhost?
Describe the bug
The form is submitted via ajax (post) but it keeps returning "Your request cannot be completed because you failed Recaptcha verification."
To Reproduce
"ReCaptcha": {
"SiteKey": "KEY",
"SecretKey": "Key",
"Version": "v2"
},
<div class="card card-body">
<form class="form-home" id="contact-form">
<div asp-validation-summary="All"></div>
<div class="row">
<div class="col-12 col-sm-5 offset-sm-1">
<input class="form-control" type="text" placeholder="Nombre y Apellido" name="name" required>
</div>
<div class="col-12 col-sm-5">
<input class="form-control" type="email" placeholder="E-mail" name="email" required>
</div>
<div class="col-12 col-sm-5 offset-sm-1">
<input class="form-control" type="tel" placeholder="Teléfono" name="phone">
</div>
<div class="col-12 col-sm-5">
<select class="form-select form-select-lg mb-3" aria-label=".form-select-lg example" name="reason">
<option selected>Motivo</option>
<option value="Sugerencia">Sugerencia</option>
<option value="Reclamo">Reclamo</option>
<option value="Contratar un seguro">Contratar un seguro</option>
</select>
</div>
<div class="col-12 col-sm-10 offset-sm-1">
<textarea class="form-control" id="exampleFormControlTextarea1" rows="5" placeholder="Comentarios" name="message" required></textarea>
</div>
<div class="col-12 col-sm-10 offset-sm-1 mt-3 align-center">
@Html.ReCaptcha()
</div>
<div class="col-12">
<button class="btn-cancelar mt-4" type="button">CANCELAR</button> <button class="btn-enviar mt-4" type="submit">ENVIAR</button>
</div>
</div>
</form>
<br />
<div id="submitted-message">Gracias, su mesaje fue enviada!</div>
<div id="error-message">Favor llenar todos los campos!</div>
</div>
[ValidateReCaptcha]
[HttpPost]
public async Task<IActionResult> Submit([FromBody]ContactFormModel model)
{
if (!ModelState.IsValid)
return BadRequest();
return Ok(model);
}
document.addEventListener('DOMContentLoaded', () => {
let form = document.getElementById('contact-form');
if (form !== null) {
form.addEventListener('submit', f => {
$("#contact-form").validate();
f.preventDefault();
var formData = {
name: $("input[name=name]").val(),
email: $("input[name=email]").val(),
phone: $("input[name=phone]").val(),
reason: $("[name=reason]").val(),
message: $("[name=message]").val(),
};
$.ajax({
type: "POST",
url: "/Umbraco/Api/Contact/Submit",
data: JSON.stringify(formData),
dataType: "json",
contentType: "application/json; charset=utf-8",
encode: true,
}).done(function (data) {
if (data.success) {
$('#error-message').fadeOut();
$('#contact-form').fadeOut();
$('#submitted-message').fadeIn();
}
}).error(() => {
$('#error-message').fadeIn();
});
})
}
})
Expected behavior
recaptcha validation should work
Chrome Browser
Describe the bug
When using [ValidateReCaptcha]
on a Controller Action, when the validation fails, the Action is still executed.
To Reproduce
Steps to reproduce the behavior:
[ValidateReCaptcha]
attribute. Get it to return Ok("Action executed")
g-captcha-response
property.Expected behavior
The action should not complete, as validation has failed.
Screenshots
If applicable, add screenshots to help explain your problem.
Desktop (please complete the following information):
Additional context
I have inspected the source code, and it looks like ValidateRecaptchaFilter.OnActionExecutionAsync()
and ValidateRecaptchaFilter.OnPageHandlerExecutionAsync()
does NOT stop execution, even if ValidateRecaptcha()
has added an error to context.ModelState
.
ValidateRecaptcha()
correctly adds an error to context.ModelState
if ReCaptchaService
returns an error:
However, in both
and , even thoughValidateRecaptcha()
is called (and error is added to ModelState
in case of validation failure), they both still call await next()
, continuing the execution chain despite there being errors.
Before calling await next()
in both of those cases, the code should check if context.ModelState.IsValid
before continuing.
We've made a copy of these classes that added that additional logic, and it works as expected: execution is stopped when validation fails (dependencies are slightly different because of our use case and because I used Rider's decompiler to get the source code, but the gist is there)
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = false)]
[ExcludeFromCodeCoverage]
public class ValidateMultiformReCaptchaAttribute : Attribute, IFilterFactory, IFilterMetadata
{
public IFilterMetadata CreateInstance(IServiceProvider services)
=> (IFilterMetadata) new ValidateMultiformReCaptchaFilter(services.GetService<IReCaptchaService>(), services.GetService<LocalizationService>());
public bool IsReusable => true;
}
public class ValidateMultiformReCaptchaFilter : IAsyncActionFilter, IFilterMetadata, IAsyncPageFilter
{
private readonly IReCaptchaService _recaptcha;
private const string FormField = "g-recaptcha-response";
private readonly string _errorMessage;
public ValidateMultiformReCaptchaFilter(IReCaptchaService recaptcha, LocalizationService localisation)
{
_recaptcha = recaptcha;
_errorMessage = localisation.GetString("/Recaptcha/ValidationFailed");
}
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
await ValidateRecaptcha(context);
// In the original AspNet.ReCaptcha library,
// execution continues even if the model is invalid
// This is added to break execution when that's the case
if (!context.ModelState.IsValid)
{
context.Result = new BadRequestObjectResult(_errorMessage);
return;
}
await next();
}
public Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context) => Task.CompletedTask;
public async Task OnPageHandlerExecutionAsync(
PageHandlerExecutingContext context,
PageHandlerExecutionDelegate next)
{
if (ShouldValidate(context)) await ValidateRecaptcha(context);
// In the original AspNet.ReCaptcha library,
// execution continues even if the model is invalid.
// This is added to break execution when that's the case
if (!context.ModelState.IsValid)
{
context.Result = new BadRequestObjectResult(_errorMessage);
return;
}
await next();
static bool ShouldValidate(ActionContext context) =>
!HttpMethods.IsGet(context.HttpContext.Request.Method) &&
!HttpMethods.IsHead(context.HttpContext.Request.Method) &&
!HttpMethods.IsOptions(context.HttpContext.Request.Method);
}
private async Task ValidateRecaptcha(ActionContext context)
{
if (!context.HttpContext.Request.HasFormContentType)
{
context.ModelState.AddModelError("", _errorMessage);
}
else
{
StringValues reCaptchaResponse;
context.HttpContext.Request.Form.TryGetValue(FormField, out reCaptchaResponse);
if (await _recaptcha.VerifyAsync(reCaptchaResponse)) return;
context.ModelState.AddModelError("Recaptcha", _errorMessage);
}
}
}
Is your feature request related to a problem? Please describe.
We are not able to monitor our users' ReCaptcha level - version v1.7.0
Describe the solution you'd like
It would be great to see ReCaptcha logging response in order to monitor the levels.
Describe alternatives you've considered
NA
Additional context
At the moment I have come across this line in your solution:
_logger?.LogTrace("recaptcha response: {recaptchaResponse}", stringResult);
However, I cannot see scores recieved by Google Recaptcha response.
logging response would help integrate with monitoring platforms
Thank you.
I have two forms on some pages and I found that the g-recaptcha-response was only populated for the first tag on the page.
Is it possible to have the tag on the page twice? If not currently, could ids be put on the tags to match up to the corresponding tags?
Hello Michael,
I would like to ask you about the language support, analyzed the code a bit and found that the language parameter is not using yet.
What are you plans for adding language support?
Thanks
In some cases, you would like to dynamically manage the AspNetCore.ReCaptcha configuration.
For example, SAAS clients want to manage their SecretKey and SiteKey through the administration page.
ReCaptchaTagHelper uses IOptionsSnapshot. This is wonderful.
I would like ReCaptchaService to use this too.
I understand the problem with pre-configuring HttpCLient with BaseUrl. This is only about SecretKey and SiteKey.
Can the callback options for error and expired be included for v2 invisible? They appear to only be included for V2. They appear to be valid for v2 invisible as well as v2 checkbox.
From RecaptchaTagHelper.cs
ReCaptchaVersion.V2Invisible => ReCaptchaGenerator.ReCaptchaV2Invisible(settings.RecaptchaBaseUrl, settings.SiteKey, Text, ClassName, Language, Callback, Badge),
ReCaptchaVersion.V3 => ReCaptchaGenerator.ReCaptchaV3(settings.RecaptchaBaseUrl, settings.SiteKey, Action, Language, Callback, ReCaptchaGenerator.GenerateId(ViewContext), Nonce),
_ => ReCaptchaGenerator.ReCaptchaV2(settings.RecaptchaBaseUrl, settings.SiteKey, Size, Theme, Language, Callback, ErrorCallback, ExpiredCallback, AutoTheme, Nonce),
Is your feature request related to a problem? Please describe.
We're using CSP on our site, which by default blocks the execution of inline scripts. Normally this can be solved by adding sha-256 value to the site's HTTP header (where the sha-256 value is dependent on the script that's expected to run), or by adding a 'nonce' value to both the HTTP header and the script tag directly
Describe the solution you'd like
Ideally we could pass in a nonce to the recaptcha tag helper, so <recaptcha nonce='some_token_here'/>
which then outputs (pseudocode)
<script nonce='some_token_here' src="https://www.google.com/recaptcha/api.js..."></script>
<script nonce='some_token_here'>function updateReCaptcha1() {grecaptcha.execute(...)}</script>
Describe alternatives you've considered
google.com can be added to the CSP allowed sources, so that isn't so much of a problem, however the generated script ignores any additional attributes passed in to the recaptcha tag besides language.
Describe the bug
It is possible to specify the 'action' on the form. i.e. @Html.ReCaptcha(action: "login")
However, I can't see a mechanism to validate the action in the [ValidateReCaptcha]
attribute. e.g. [ValidateReCaptcha(action: "login")]
To Reproduce
Expected behavior
Google's docs say its "important to verify" this action value.
"action": string // the action name for this request (important to verify)
Sorry if I'm missing something!
PS Thanks for such a useful and well written wrapper!
Desktop (please complete the following information):
Describe the bug
as per the title, ReCaptchaResponse.Score is defined as a double whereas ReCaptchaSettings.ScoreThreshold is defined as a float (single), resulting in unpredictable behavior. As an example, I used a value of 0.1 for the threshold parameter, and have received a 0.1 from the recaptcha service:
Both have a logical value of 0.1, however the float value has to be converted to a double for comparison, which yields a possibly unexpected result:
To Reproduce
Steps to reproduce the behavior:
Console.WriteLine((double)(float)0.1);
line in a console project
or
Expected behavior
Both properties should be of the same type as they represent semantically the same value. The correct type would probably be a decimal as the number is a rational number with a fixed number of decimals.
Screenshots
See screenshots in text above
Desktop (please complete the following information):
Doesn't matter
Hi guys!
I am trying to use your nuget but struggling with the intregration.
I have implemented the nuget like told in the readme but once I try to submit my request it will fail based the the Recaptcha Value.
Just double checked if my appsettings is filled with the correct keys and it is. so thats not the case. @Html.Recaptcha() is rendering the badge without any error.
I hope you guys can help me out. (if you need anything else of information let me know)
part of the form where the recaptcha needs to be rendered
@using (Html.BeginForm("SendContactMessage", "Contact", FormMethod.Post, new { @class = "form" }))
{
<div class="form-group">
@Html.LabelFor(m => m.Message)
@Html.TextAreaFor(m => m.Message, new { @class = "form-control message-area" })
@Html.ValidationMessageFor(m => m.Message)
</div>
<div class="form-group">
@Html.ReCaptcha(language: "nl-NL")
<input class="btn btn-lg btn-dustswiffer" type="submit" value="Verstuur" />
</div>
}
Part of method thats being called after submitting the form
[HttpPost]
[ValidateReCaptcha]
public async Task<IActionResult> SendContactMessage(ContactViewModel viewmodel, CancellationToken cancellationToken)
{
if (!ModelState.IsValid)
{
return View("Index", viewmodel);
}
}
update: using v3
Describe the bug
I found that my code did not work, so I pulled the samples, and they dont work either.
Clone samples, run net6.0 sample, notice no recap on the Contact page. V2 sample works.
To Reproduce
Steps to reproduce the behavior:
Expected behavior
You should see a ReCaptcha
Desktop (please complete the following information):
Additional context
V2 Sample configuration works.
How would you localize the error message used by the ValidateReCaptchaAttribute
?
Is your feature request related to a problem? Please describe.
While the library is definitely functional, debugging of failed captcha verifications is nigh impossible (as far as I can tell). The error-codes
field in the response from Google reCAPTCHA is ignored and there is no out-of-the-box logging of responses
Describe the solution you'd like
I've forked the source code and took a stab at implementing something, I've:
ErrorCodes
property for the ReCaptchaResponse
class to receive the error codes returned by the API [JsonPropertyName("error-codes")]
public string[] ErrorCodes { get; set; }
ReCaptchaService.GetVerifyResponseAsync
method to include the following: var stringResult = await result.Content.ReadAsStringAsync();
var obj = JsonSerializer.Deserialize<ReCaptchaResponse>(stringResult);
_logger?.Log(obj.Success ? LogLevel.Information : LogLevel.Warning, stringResult);
return obj;
and injected an optional ILogger<IReCaptchaService> logger
into the ctor.
It seems to work, if the above changes look ok to you, would you accept a PR with this? Alternatively feel free to add yourself if you like it.
Describe alternatives you've considered
One alternative that I've tried is decorating the registered IReCaptchaService
service with a logging wrapper, but that is a bit clunky and does not really give access to the raw response from the reCAPTCHA API that still has the error codes property in it...
Is your feature request related to a problem? Please describe.
I would like to disable ReCaptcha when environment.IsDevelopment() == true
Describe the solution you'd like
I would like a bool in ReCaptchaSettings called Enabled.
Describe alternatives you've considered
Is it possible for me to skip calling services.AddReCaptcha(this.Configuration.GetSection("ReCaptcha")
in development, and that will not break anything? Even though I still have the tag helpers, and the attributes on my Razor Pages?
Additional context
Add any other context or screenshots about the feature request here.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.