Open olegabr opened 5 years ago
Thanks for reporting @olegabr . We're looking into this
Is this site built using web3js? If so, what version are you using.
Yes, it uses web3js. Good old 0.20.7
is used.
still the same problem
@olegabr it seems like the withCredentials attribute is being set on your request when it shouldn’t be. Can you confirm in your code?
withCredentials
no such attribute in my code. Anyway, I've switched to the new stable 1.2 web3.js version and problem disappears. Thank you.
https://elevato.uk/payments/zamowienie/order-received/506/?key=wc_order_YZH3EpPwfdmKd
it is enough to call this code in a console:
epg.web3.eth.gasPrice
to have this error:
inpage.js:formatted:9351 Access to XMLHttpRequest at 'https://mainnet.infura.io/v3/03a06ac61e0740ed8934ca4bc13c8cf1' from origin 'https://elevato.uk' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
o.send @ inpage.js:formatted:9351
a.send @ inpage.js:formatted:10477
(anonymous) @ inpage.js:formatted:10427
(anonymous) @ VM1730:1
inpage.js:formatted:9351 POST https://mainnet.infura.io/v3/03a06ac61e0740ed8934ca4bc13c8cf1 net::ERR_FAILED
o.send @ inpage.js:formatted:9351
a.send @ inpage.js:formatted:10477
(anonymous) @ inpage.js:formatted:10427
(anonymous) @ VM1730:1
inpage.js:formatted:9353 Uncaught Error: CONNECTION ERROR: Couldn't connect to node https://mainnet.infura.io/v3/03a06ac61e0740ed8934ca4bc13c8cf1.
at Object.InvalidConnection (inpage.js:formatted:8718)
at o.send (inpage.js:formatted:9353)
at a.send (inpage.js:formatted:10477)
at w.gasPrice (inpage.js:formatted:10427)
at <anonymous>:1:14
The current active plugin version uses web3.js 0.20.6: https://wordpress.org/plugins/ether-and-erc20-tokens-woocommerce-payment-gateway/ But according the call stack the version from MetaMask is actually used, and it looks like it is 0.20.6 also.
You asked about the withCredentials
. I've seen it is set in the web3.js code.
Problem persists regardless if I'm logged into my MetaMask account or not.
Thanks for the report @olegabr, we have a fix to return a non-wildcard CORS header in testing now. However, since there's a small chance that some customer is expecting *
we don't want to release this fix going into the weekend, so will plan on releasing it early next week.
@ryanschneider, thank you for the release plans! Will wait it impatiently :-)
Look at this also please: https://github.com/trustwallet/trust-web3-provider/issues/76#issuecomment-536158648
@olegabr the fix for this issue has been deployed, let me know if you are still seeing issues.
Thanks, Ryan
Also sorry didn't mean to close the issue before it was deployed, I referenced it in my PR for the backend code change and forgot that if you say "fixes #foo" then the issue is closed when the PR is merged. I'll close this after I get confirmation from you that the issue is resolved.
Yes, issue still persists:
To reproduce, just open the https://elevato.uk/payments/zamowienie/order-received/506/?key=wc_order_YZH3EpPwfdmKd page and type
epg.web3.eth.gasPrice
in a browser console.
Hmm, ok, that's actually a different issue, now that the Access-Control-Allow-Origin
header is for your site, it's the fact that the fetch request is being sent withCredentials
that's causing the issue, I think this is a bug in web3.js.
I don't want to include return the -Allow-Credentials
header unless strictly necessary, because we do not want to encourage Infura users to include their secret for auth from a client-side dapp, so we might need to get creative in how we work around this issue.
Also which browser are you seeing the issue in? I'm using Safari 13.1 and am not getting any issues on your site when running epg.web3.eth.gasPrice
in the console:
Edit: you originally mentioned Chrome, so I'm guessing the issue above was in Chrome as well, I'll see if I can reproduce.
Confirmed I see the same issue in Chrome (Version 77.0.3865.90).
What's interesting is that if I copy the request from Chrome as a CURL, and run it I don't even see any CORS headers on the request:
$ curl 'https://mainnet.infura.io/v3/03a06ac61e0740ed8934ca4bc13c8cf1' -H 'Sec-Fetch-Mode: cors' -H 'Referer: https://elevato.uk/payments/zamowienie/order-received/506/?key=wc_order_YZH3EpPwfdmKd' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36' -H 'Content-Type: application/json' --data-binary '{"jsonrpc":"2.0","id":6,"method":"eth_gasPrice","params":[]}' --compressed
{"jsonrpc":"2.0","id":6,"result":"0xee6b2800"}
I'll do some digging on the Sec-Fetch-Mode: cors
header and see if that's something we can respond to.
What I determine is how to get Chrome to copy the actual CORS preflight request as a CURL command, that would be the easiest thing to debug, I'll keep digging though.
Ok, this makes even less sense. If I copy the request as a fetch, I get back:
fetch("https://mainnet.infura.io/v3/03a06ac61e0740ed8934ca4bc13c8cf1", {"credentials":"omit","headers":{"content-type":"application/json","sec-fetch-mode":"cors"},"referrer":"https://elevato.uk/payments/zamowienie/order-received/506/?key=wc_order_YZH3EpPwfdmKd","referrerPolicy":"no-referrer-when-downgrade","body":"{\"jsonrpc\":\"2.0\",\"id\":6,\"method\":\"eth_gasPrice\",\"params\":[]}","method":"POST","mode":"cors"});
Notice that the fetch says "credentials":"omit"
. This might actually be a Chrome bug.
edit: According to https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials
When a request's credentials mode (Request.credentials) is "include", browsers will only expose the response to frontend JavaScript code if the Access-Control-Allow-Credentials value is true.
So this really does feel like a Chrome bug, since the fetch is set to omit
. I'll see if I can find any open Chrome issues, maybe they will lead us to a work-around.
Also, FWIW, confirmed I get the same issue on Brave (Version 0.67.123 Chromium: 76.0.3809.87 (Official Build)) (which is based on Chromium in recent releases), but not in Firefox 65.0b11 (which behaves like Safari).
Nice research. My two cents:
epg.web3.version
{api: "0.20.7", getNode: ƒ, getNetwork: ƒ, …}
epg.web3metamask.version
{api: "0.20.7", getNode: ƒ, getNetwork: ƒ, …}
The 0.20.7 version of web3js is used. It cames from MetaMask. I see it as an inpage.js
in debugger.
This is the place where withCredentials
is set to true
:
https://github.com/ethereum/web3.js/blame/0.20.7/lib/web3/httpprovider.js#L66
HttpProvider.prototype.prepareRequest = function (async) {
var request;
if (async) {
request = new XHR2();
request.timeout = this.timeout;
} else {
request = new XMLHttpRequest();
}
request.withCredentials = true;
request.open('POST', this.host, async);
if (this.user && this.password) {
var auth = 'Basic ' + new Buffer(this.user + ':' + this.password).toString('base64');
request.setRequestHeader('Authorization', auth);
} request.setRequestHeader('Content-Type', 'application/json');
if(this.headers) {
this.headers.forEach(function(header) {
request.setRequestHeader(header.name, header.value);
});
}
return request;
};
This flag was added to fix this issue: https://github.com/ethereum/web3.js/issues/1665
I do not use filters in my code, so, I can try to exploit the HttpProvider.prototype.prepareRequest
method to workaround this issue. However, I want to hear your ideas here.
With this patch I've worked around the original error:
function epg_web3_prepareRequest_shim(async) {
var request;
// if (async) {
// request = new XHR2();
// request.timeout = this.timeout;
// } else {
request = new XMLHttpRequest();
// }
// request.withCredentials = true;
request.open('POST', this.host, async);
if (this.user && this.password) {
var auth = 'Basic ' + new Buffer(this.user + ':' + this.password).toString('base64');
request.setRequestHeader('Authorization', auth);
} request.setRequestHeader('Content-Type', 'application/json');
if(this.headers) {
this.headers.forEach(function(header) {
request.setRequestHeader(header.name, header.value);
});
}
return request;
};
window.epg.web3.currentProvider.prepareRequest = epg_web3_prepareRequest_shim;
But regardless if I apply this patch or not, if I try to send tx via MetaMask, I get this error now:
inpage.js:1 MetaMask - RPC Error: Internal JSON-RPC error. {code: -32603, message: "Internal JSON-RPC error.", data: {…}, stack: "Error: Error: [ethjs-query] while formatting outpu…eaoehlefnkodbefgpgknn/background.js:1:1230603"}}'"}
ether-and-erc20-tokens-woocommerce-payment-gateway.js?ver=2.6.6:774 {code: -32603, message: "Internal JSON-RPC error.", data: {…}, stack: "Error: Error: [ethjs-query] while formatting outpu…eaoehlefnkodbefgpgknn/background.js:1:1230603"}}'"}
ether-and-erc20-tokens-woocommerce-payment-gateway.js?ver=2.6.6:805 {code: -32603, message: "Internal JSON-RPC error.", data: {…}, stack: "Error: Error: [ethjs-query] while formatting outpu…eaoehlefnkodbefgpgknn/background.js:1:1230603"}}'"}
Full error message:
"Error: Error: [ethjs-query] while formatting outputs from RPC '{"value":{"code":-32603,"message":"Internal JSON-RPC error.","data":{"originalError":{}},"stack":"Error: BlockReEmitMiddleware - retries exhausted\n at chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:1:1230698\n at async chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:1:1230603"}}'"
Any update?
Any idea where this.user
and this.password
are being set? I think that's the issue: you should not be using Basic auth at all when accessing Infura from a client-side app, auth should only be use when you want to lock a projectID to require it's project secret, which can't be done securely client-side, so should only be used in server-side applications.
My guess is that the user/pass being set are not valid for Infura, and we're returning a 400 error, and MM is retrying, leading to MM emitting the JSONRPC error you included, that error looks to be generated inside MM.
Error in Chrome console:
Chrome request headers: