Google Recaptcha V3 double submit issue (timeout-or-duplicate error) - javascript

I have an issue somewhat similar to this scenario :
I got "timeout-or-duplicate" error using ReCaptcha v3
In may scenario i have a form and a button that perfrom submit of the form. Inside the form a setInterval keep the recaptcha fresh :
<script src="https://www.google.com/recaptcha/api.js?render=<%=ServiceLocator.AppConfigProvider.Instance.RecaptchaPublicKey%>"></script>
<script>
onSetupDone(function () {
getReCaptcha();
setInterval(function () { getReCaptcha(); }, 90000);
function getReCaptcha() {
grecaptcha.ready(function () {
grecaptcha.execute('<%=ServiceLocator.AppConfigProvider.Instance.RecaptchaPublicKey%>', { action: globals.currentPage }).then(function (token) {
document.getElementById("reCAPTCHAResponse").value = token;
});
});
};
/**
* Get a previously stored RecaptchaToken
* */
window.getReCaptchaValue = function () {
var result = document.getElementById("reCAPTCHAResponse").value;
getReCaptcha();//refresh the value
return result;
};
});
</script>
the OnSetupDone() is a function equivalent to document ready (it's called once per page, when document is ready and all setup phase is done).
My problem is that when user click twice the button that cause form submit, multiple form are submitted (and then cancelled when a next click occured)
But if the cancellation occurred only after the server use of recaptcha token, i end up using a token twice. And so request is declined (timeout-or-duplicate error).
What is not clear to me is which is the whay to handle situation like that (avoid use a recaptcha token twice in a from submit).
Should i add an handler in the form submit event and take another captcha? (this does not guarantee me that the next submit will be processed after the form sumbit event enqueued by javascript.. so i guess answer is still no)
PS : as shown in the picture, the page (an asp.net page) does not reload while the submit is processed. This also contribute to the fact that the old token is retained by the alredy submitted form.

Related

POST works with alert message but doesn't without it

I am making a post request to google app script with the code below
var url ="MY WEBAPP EXEC"
function submitForm() {
var postRequest = {}
postRequest.name = $("#inputName").val();
postRequest.email = $("#inputEmail1").val();
postRequest.message = $("#inputMessage").val();
alert(JSON.stringify(postRequest)); // this alert
$.post(url, postRequest, function(data,status){
alert('success')
});
}
I am very confused why the post is working with the alert but doesn't work without it. Thank you.
===
OK I guess my question was not clear enough sorry.
I have a form accessing GAS remotely. I assumed the url implied that I was accessing GAS remotely. At the moment I am working on my localhost and on my JS above it works if the alert statement is present and does not do anything if alert is not there.
I was watching the execution list on GSuite Developer Hub to see if the request failed or completed. I observed if the alert statement is in the script the execution status is completed but if the alert statement is not there nothing happens. I assume that my post script is not working if alert is not there. Any idea why?
You haven't shown exactly how that function is called, but it's likely to be because, if this is truly a "form submit" action, the result of submitting a form is to "load a new page" (which can be the same page you're on, and is so by default with no action attribute in the form tag
Since you want to perform AJAX on form submit, you need to "prevent" the "default" form submit action - this can be achieved as shown in the second and third lines below
var url ="MY WEBAPP EXEC"
function submitForm(e) { // if this function is called using an event handler, it gets an event as the first and only argument
e.preventDefault(); // prevent the "default" form submit action
var postRequest = {}
postRequest.name = $("#inputName").val();
postRequest.email = $("#inputEmail1").val();
postRequest.message = $("#inputMessage").val();
alert(JSON.stringify(postRequest)); // this alert
$.post(url, postRequest, function(data,status){
alert('success')
});
}

how do i add validation to this method in angular controller?

Hi I have a controller where the post method still takes place even when an error comes up to say the fields weren't completed. You refresh the page and entry goes from the view.
$scope.create = function () {
var account = Account.save($scope.account);
modalService.success('Success! Your Account has been created!');
$uibModalInstance.close(account);
};
I have tried a few things, but they haven't worked. I need the method to return false if the form hasn't been filled in or fields are missing. Basically a 422 error; as the post goes to an api endpoint.
The example above is my code and need to add some validation into it, but just don't know where to start.
Really tired and need some help quickly.
Thank you in advance.
You could wait till that save method actually complete an ajax and then respond to you
var account = Account.save($scope.account).$promise.then(function(){
//success function
modalService.success('Success! Your Account has been created!');
$uibModalInstance.close(account);
}, function(error){ //error function
//here is the place you can do error handling part.
console.log('Error occured, do handle it here.')
});
Update
If you wanted to make sure before submitting form user should be enter a all form fields and all. Then you could take use of angular form validation feature. Where you can disabled form submit button till all form required fields are filled up & have required attribute over the fields which are required.

Page redirect in jQuery fails randomly. Race condition?

Elaborating on an example from the very good post by Felix Kling I wrote some jQuery code to authenticate a user. If the authentication is successful the window.location object should be assigned/replaced to a new URL.
The redirection occasionally fails, even though the user is authenticated correctly: based on the values of sessionStorage('Auth') the looks of the menus for an authenticated user are modified by some other JS code, so I know when the credentials were entered correctly.
Here is my code.
$(document).ready(function() {
$('#submit').click(function() {
var webServiceHref = window.location.href;
var webServicePath = webServiceHref.slice(0,webServiceHref.lastIndexOf("/"));
var serviceUrl = webServicePath + "/login.php";
$.post(serviceUrl,
{
Email: $("#Email").val(),
Password: $("#Password").val()
}).done(function(data, status) {
var json = JSON.parse(data);
if (json.valid == true){
sessionStorage.setItem('Auth', true);
sessionStorage.setItem('FirstName', json.FirstName);
sessionStorage.setItem('Email', json.Email);
$("#messageLine").val("Authentication succeded");
$(location).attr('href', webServicePath + "/welcome.html");
// window.location.href = webServicePath + "/welcome.html";
} else {
sessionStorage.clear();
$("#messageLine").val("Incorrect Username or Password");
}
});
}); // click
}); // ready
This behavior does not depend from the way the redirection is called:
I left in my code, commented out, some of the JS and jQuery
combinations of methods (window.location.assign, window.location.replace etc.) suggested in numerous posts on SO.
I have even tried .reload() without success.
In Chrome inspector I can even see the callback statements being executed, the assignment of the new URL being made, but when the function returns the window object sometimes does not change, and sometimes ... it does.
Perhaps the assignment of the URL is queued after other event which causes the original login.html page to be reloaded?
What am I missing? Am I using the deferred object incorrectly?
Thank you in advance for your help.
If your "#submit" element is actually submitting a form (e.g. it is an input of type "submit" within a form), that could cancel the page redirection. E.g. when no action is specified on the form, it just reloads the same page, preventing your modification of window.location.href from having any effect.
See also that post: javascript redirect not working anyway
You have 3 easy possible solutions:
Turn your element/button into a normal one (not a submit).
Prevent the element/button from submitting the form (function (event) { event.preventDefault(); /* rest of your code */}).
Attach your main callback on the form submit event. The user is then able to trigger the action by hitting "Enter", not just by clicking on the submit button.

Google reCAPTCHA fail for second time submit

I implement the reCAPTCHA in this tutorial,
https://codeforgeek.com/2014/12/google-recaptcha-tutorial/
which work well for the first time submit. The problems I have are:
I send the captcha with other form data e.g. username , email etc.... so if captcha is correct but other not , the user will send it again, but the second time it return "{ "success": false }"
if I idle it for ~2 min , it will session expire and if I select the box it pop up alert and warning something like " can not refresh : invalid parameter", and I can not select the box again
How to fix those problem? Thanks a lot.
Google reCAPTCHA gives these two functions: I always use this in all my AJAX powered forms.
grecaptcha.getResponse()
grecaptcha.reset();
For both of your problems, use the second function whenever you need in your JavaScript code.
Remember this works if you have only one CAPTCHA in your page. If you have more than two CAPTCHAs use their IDs as explained in Google Docs
https://developers.google.com/recaptcha/docs/display#js_api
Those who have the same problem and meet this topic during research;
If you experience problem when you render the captcha automatically, try to render it explicitly. In order to do this, add following code inside body tag.
<script src="https://www.google.com/recaptcha/api.js?onload=recaptchaCallback&render=explicit&hl=tr" async defer></script>
var recaptchaCallback = function () {
// alert("grecaptcha is ready!");
grecaptcha.render("YOUR HTML DIV ID", {
'sitekey': 'YOUR SITE KEY',
});
};
I'm using AJAX to check registration form and get response. So I have added reset function to my AJAX response.
$('#frmRegistration').submit(function () {
$.ajax({
url: "_ajax/_ajaxRegistration.php",
type: "POST",
data: $('#frmRegistration').serialize(),
success: function (reply) {
$('#resultRegistration').html(reply);
grecaptcha.reset();
}
});
});
Reference Google reCaptcha explicit render.

Checking for duplicate username

I am doing a registration page, for my mobile app, and want to check for duplicate usernames entered by the user/client
I have a button on the page that when clicked, checks availability of the username. However I would like to also incorporate that automatically, if not already done so, when the client clicks submit/go to step 3,
I want to perform the check for duplicate usernames using Ajax and if there exists a duplicate, then refresh the SAME page with the error message for duplication, else proceed to step 3.
In my HTML file I have some js that does the following:
$("#check-username").click(function() {
(...this works as I am able to click the CHECK button
and see if the username exists)
I have another js file, that is sourced in my HTML that does the following:
submitHandler : function() {
$("#reg1").hide();
$("span#step").html("2");
$("#check-username").click;
$("#reg3").show();
scrollTop();
}
When I click on Go to next step which is reg3, It does not do the validation for check-username. Is my method/syntax for calling check-username correct?
$("#check-username").click;
^^----- Missing Braces
supposed to be
$("#check-username").click();
The problem is you need to go to step 3 only after the validation ajax request returns from the server. You also are going to need to look at the response from the server to see if it's a duplicate. For example:
$("#check-username").click(function() {
validateUser();
});
function validateUser(){
return $.ajax({
url: '/path/to/validate'
});
}
And your submit handler stuff:
submitHandler : function() {
$("#reg1").hide();
$("span#step").html("2");
validateUser()
.done(function(r){
//for example...
if(r.isValidUser){
$("#reg3").show();
scrollTop();
}
});
}

Categories