google / recaptcha

PHP client library for reCAPTCHA, a free service to protect your website from spam and abuse.
http://www.google.com/recaptcha/
BSD 3-Clause "New" or "Revised" License
3.47k stars 768 forks source link

Recaptcha V2 just spins #539

Open autohpn opened 9 months ago

autohpn commented 9 months ago

Issue description I have a problem with recaptcha v2. It has stopped working without having changed anything. When checking, it only rotates and does not verify.

Environment

Reproducing the issue

stdex commented 9 months ago

This should be conflict with mootools: https://stackoverflow.com/questions/77473778/google-recaptcha-keeps-on-loading
https://stackoverflow.com/questions/77462429/joomla-recaptcha-v2-0-spinning
https://stackoverflow.com/questions/77454968/joomla-recaptcha-issues

Compatability bind, that could have worked earlier (https://gist.github.com/sleemanj/f076ed2c0b887ab08074b55dad2fd636 https://github.com/google/recaptcha/issues/374#issuecomment-729881795) also stop working.

autohpn commented 9 months ago

Thanks for your answer!

how can i solve this????? I don't found the solution :-(

dimov-cz commented 9 months ago

What version of Mootools do you use? 1.6.0 resolves some Array.from related issues.

stdex commented 9 months ago

I can confirm problem on mootools 1.4.2

autohpn commented 9 months ago

the problem happens with both 1.4.2 and 1.6.

I have managed to solve the problem by not loading mootools in the urls where the captcha loads. It is the only radical way by which I have been able to do it.

dimov-cz commented 9 months ago

1.6.0 without comp. layer is working for me

dimov-cz commented 9 months ago

The problematic code in compatibility mode is: /<1.5compat>/ Array.from = Array.convert; /</1.5compat>/

and in 1.5.1 and earlier version Array.from implementation which doesn't handle objects like MapIterate and Set.

SaintAnd commented 9 months ago

For me it's worked in template index.php after : <?php unset($this->_scripts[$this->baseurl.'/media/system/js/mootools-core.js']); ?>

am-unklown commented 9 months ago

For me it's worked in template index.php after : <?php unset($this->_scripts[$this->baseurl.'/media/system/js/mootools-core.js']); ?>

it removes core of mootools which can be used somewhere in your site. for example in my case it is used in virtuemart users/orders pages. removing it may lead to other issues.

am-unklown commented 9 months ago

1.6.0 without comp. layer is working for me

for me it resolves problem with recaptcha but brings problems in admin part of site (e.g. on pages with availability to sort entities: articles, orders, etc). enabling compat layer even with fix form #374 brokes recaptcha.

SaintAnd commented 9 months ago

For me it's worked in template index.php after : <?php unset($this->_scripts[$this->baseurl.'/media/system/js/mootools-core.js']); ?>

it removes core of mootools which can be used somewhere in your site. for example in my case it is used in virtuemart users/orders pages. removing it may lead to other issues.

I agree with you. This leads to other problems on the site. Spoilers and sliders break

SaintAnd commented 9 months ago

Unfortunately, this is the only option currently used. <?php if ($_SERVER["REQUEST_URI"] == "/internet-priemnaya/") { unset($this->_scripts[$this->baseurl.'/media/system/js/mootools-core.js']);} ?>

jacksleight commented 9 months ago

Using @sleemanj's original bind compatibility approach and the Array.from hint from @dimov-cz I've come up with the following which seems to be working for me (mootools 1.4.5):

// Add this BEFORE mootools is loaded

Function.prototype._nativeBind = Function.prototype.bind;
Array._nativeFrom = Array.from;
// Add this AFTER mootools is loaded

var isRecaptcha = function() {
    var stack = new Error().stack;
    if (!stack) {
        try {
            throw new Error();
        } catch (e) {
            stack = e.stack;
        }
    }
    return stack.match(/recaptcha/);
}

Function.prototype._mootoolsBind = Function.prototype.bind;
Array._mootoolsFrom = Array.from;

Function.prototype.bind = function (...args) {
    return isRecaptcha() ? this._nativeBind(...args) : this._mootoolsBind(...args);
};
Array.from = function (...args) {
    return isRecaptcha() ? this._nativeFrom(...args) : this._mootoolsFrom(...args);
};

I've not tested this thoroughly yet and there could be issues with it! Improvements welcome.

pinta83 commented 9 months ago

Okay, I have a much elegant solution for this.... Change this part of code

Array.from = function(item){
    if (item == null) return [];
    return (Type.isEnumerable(item) && typeof item != 'string') ? (typeOf(item) == 'array') ? item : slice.call(item) : [item];
};

with this

Array.from = function(item){
    if(new Error().stack.indexOf('recaptcha') >= 0) return [].slice.call(item); // Single line added for reCaptcha fix
    if (item == null) return [];
    return (Type.isEnumerable(item) && typeof item != 'string') ? (typeOf(item) == 'array') ? item : slice.call(item) : [item];
};

Patched files are below if anyone needs.... Unzip into JPATH_ROOT/media/system/js/ mootools.zip

AlexSmetaninGB commented 9 months ago

post the file if it works please

pinta83 commented 9 months ago

post the file if it works please

Edited and uploaded in thread above ;)

AlexSmetaninGB commented 9 months ago

Cool, it seems to work... Could you write what the error was and what caused it? Thanks man!!!

AlexSmetaninGB commented 9 months ago

thx all ;_) pinta83-WO (dev) dimov-cz (dev) SaintAnd- ru (sql) Andrew Gospodin jacksleight-United Kingdom (j.s) Jack Sleight AlexSmetaninGB-ru (bug report) AlexSmetanin

AlexSmetaninGB commented 9 months ago

thx all ;_) pinta83-us (dev) dimov-cz (dev) SaintAnd-us (sql) jacksleight-us (j.s) AlexSmetaninGB-ru (dev, bug report)

pinta83-WO (dev) dimov-cz (dev) SaintAnd- ru (sql) Andrew Gospodin jacksleight-United Kingdom (j.s) Jack Sleight AlexSmetaninGB-ru (bug report) AlexSmetanin

trinkel commented 9 months ago

Note that you may need to clear the browser cache for this to work.

sempostma commented 8 months ago

This works without having to run a script before mootools is loaded:

// Add this AFTER mootools is loaded
(function fixMooToolsAndRecaptchaMapsIssueIffy() {
// restore native Array.from by getting the native implemenation from a new frame
var frame = document.createElement('iframe');
frame.sandbox = 'allow-same-origin';
document.body.appendChild(frame);
Array._nativeFrom = frame.contentWindow.Array.from
Function.prototype._nativeBind= frame.contentWindow.Function.prototype.bind
frame.remove();
var isRecaptchaOrMaps = function() {
    var stack = new Error().stack;
    if (!stack) {
        try {
            throw new Error();
        } catch (e) {
            stack = e.stack;
        }
    }
    return stack.match(/recaptcha/) || stack.match(/maps\.google\.com/);
}

Function.prototype._mootoolsBind = Function.prototype.bind;
Array._mootoolsFrom = Array.from;

Function.prototype.bind = function (...args) {
    return isRecaptchaOrMaps () ? this._nativeBind(...args) : this._mootoolsBind(...args);
};
Array.from = function (...args) {
    return isRecaptchaOrMaps () ? this._nativeFrom(...args) : this._mootoolsFrom(...args);
};
})();