BitMEX / api-connectors

Libraries for connecting to the BitMEX API.
https://www.bitmex.com/app/restAPI
910 stars 795 forks source link

403 error with trade operations using API (javascript) #170

Open janisdombr opened 6 years ago

janisdombr commented 6 years ago

I develop chrome extention to use hotkeys and to trade using several account by API. Firstly I tried connect to API using simple XMLHttpRequest and sha256 library. I checked that signature is working correct (using your Manual examples). This way didn't works (all requests, get orders or post - 403 Forbidden).

var verb = "POST"; var apiKey = ""; var apiSecret = ""; var expires = parseInt((new Date().getTime() + (60 * 1000))/1000); //'1518064238';// var req = new XMLHttpRequest(); var postBody = '{"symbol":"XBTUSD","leverage":3}';//JSON.stringify(data); var path = '/api/v1/position/leverage'; var signature = sha256.hmac.create(apiSecret).update(verb + path + expires + postBody).hex(); req.open(verb, "https://www.bitmex.com" + path, true); req.setRequestHeader('Content-Type', 'application/json'); req.setRequestHeader('Accept', 'application/json'); req.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); req.setRequestHeader('api-expires', expires); req.setRequestHeader('api-key', apiKey); req.setRequestHeader('api-signature', signature); req.send(postBody);

Then I included ccxt library to get orders and it works.

bitmex = new ccxt.bitmex({ apiKey: apiKey, secret: apiSecret }); (async function () { orders = await bitmex.fetchOrders('BTC/USD', new Date().getTime() - (10 24 60 60 1000), 1, { open: true, reverse: true }); } })();

But when I use another operations with "trade" permissions, I always get 403 forbidden error. Not matter what API keys I use (with any permission level include withdraw). I cancel all sequrity settings in account but nothing changes. Can you check why can it happen? All this function failed: createLimitBuyOrder, privatePostPositionLeverage, cancelOrder This function works: fetchOrders, fetchBalance ccxt.browser version 1.14.265 I use Chrome browser 67.0.3396.99 64bit

DELETE https://www.bitmex.com/api/v1/order?orderID=a5b4f5c8-4bcd-f36f-0ddb-070c723a061e 403 (Forbidden) Uncaught (in promise) Object.assign: bitmex DELETE https://www.bitmex.com/api/v1/order?orderID=a5b4f5c8-4bcd-f36f-0ddb-070c723a061e 403 Forbidden (possible reasons: invalid API keys, bad or old nonce, exchange is down or offline, on maintenance, DDoS protection, rate-limiting)

janisdombr commented 6 years ago

Duplicate of #171 probably same situation

CryxxsRun commented 6 years ago

did you create the API key with order permission? That's the root cause of my 403 errors

janisdombr commented 6 years ago

Of course. I create API key with order permission, then to test I create 5 more keys with order and withdraw and any kind of keys and test them all. As I said in first my message

ryanfox commented 6 years ago

The issue with CCXT should be brought up with their issue tracker.

As for your original issue - are you able to perform those operations via the API explorer?

janisdombr commented 6 years ago

This is not CCXT issue. I just realized (today) that it was your kind of "protection" from hack, and if you receive request from your own website and it's GET request, you let it go. If any another - you block it with 403 error. I made additional layer on my web server to redirect all requests and all it works. So, if I use Chrome Extention to make hotkeys for your website it's impossible to send requests to API. It's little bit ridiculous because I don't use cookies (and can't do it) and use auth with API keys... So, for now I have to use request layer to my webserver and loose very expensive time (about half second) and my extension can't work without my server support, it's sad. If you will change your policy of reject all requests except GET from your own domain it will be very nice. So. I'll share here project when I finish it.

To answer you: yes, via API explorer all works good. And now through my webserver all operations works.

ryanfox commented 6 years ago

I'm not sure what issue you are running into - other requests than GET are accepted.

If you open the console while on testnet.bitmex.com, you can see POST and DELETE requests being made if you create or cancel an order.

janisdombr commented 6 years ago

You can download my project to understand what did I mean. I wrote Chrome extention wich runs when I use https://www.bitmex.com/app/trade your website to trade. This extention use hotkeys to make quick orders and send it to several accounts using API. In this case this XMLHttpRequest looks like sent from website (has in Request Headers "Host: www.bitmex.com"). So this Header + POST or DELETE or PUT methods => 403 error.

ryanfox commented 6 years ago

Have you looked at the headers sent when you use the web interface normally? For example, placing an order on testnet.bitmex.com sends a POST request with the header Host: testnet.bitmex.com.

I think it's pretty unlikely the Host header is causing the issue.

janisdombr commented 6 years ago

May be not Host header but cookie? When I use web interface normally all requests to your server use this headers using x-csrf-token/Cookie auth:

POST /api/v1/position/leverage HTTP/1.1 Host: testnet.bitmex.com Connection: keep-alive Content-Length: 32 Origin: https://testnet.bitmex.com x-csrf-token: otY8dY8H-voyy9UmAJEkQmG9Kk-FJ9LwcXyo User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36 content-type: application/json accept: application/json x-requested-with: XMLHttpRequest Referer: https://testnet.bitmex.com/app/trade/XBTUSD Accept-Encoding: gzip, deflate, br Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7 Cookie: __cfduid=d3a0bb3b9e4fdf54a6fffce6a35c5d1551530043146; u=s%3A378ffd6e-153f-4e63-9c29-c16762173c25.xuOn0PJNGJEl78A1GIo12TSjVLdx0IoynGFIQFCmQVw; ls=s%3A1.iRYoszp6DdFM6GrGvce7RDZzQY0LytKwsO2Ptr7cSp0; connect.sid=s%3AdrtCay6IMbj0EsOaRrUxBBTiNtHN0el8.NDdR3WUCixMGYtsYFdTmNvfAnXVO2RzrYycU2Dc1rBA

But when in extention I use POST request with Api auth, Cookie also automatically adds:

POST /api/v1/position/leverage HTTP/1.1 Host: testnet.bitmex.com Connection: keep-alive Content-Length: 32 Origin: chrome-extension://ikilpdbipkcmekfpfimbadlnccndkmbc User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36 Content-Type: application/json api-signature: a90146e009c6ddf043136069db9081e7b4bf67fd6c3bf284186470245ad8c9f0 Accept: application/json X-Requested-With: XMLHttpRequest api-key: QDkd5fYEVScG7sRhaoCW_UYD api-expires: 1532555093 Accept-Encoding: gzip, deflate, br Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7 Cookie: __cfduid=d3a0bb3b9e4fdf54a6fffce6a35c5d1551530043146

And in second way answer is:

--> HTTP/1.1 403 Forbidden Date: Wed, 25 Jul 2018 21:43:52 GMT Content-Length: 0 Connection: keep-alive Strict-Transport-Security: max-age=31536000; includeSubDomains

When I request from another page (inject extention to github.com) and delete cookies from bitmex - same situation. Change IP using proxy - same 403 error.

But using same api and data in PHP CURL all works fine... don't know why. Can you download my extention and check it? May be header "Origin: chrome-extension:" fault ?

STRML commented 6 years ago

The issue is indeed the Origin header, which we check for CSRF reasons.

janisdombr commented 6 years ago

Is it possible to change this check and add exeption if API auth is enable? Because all GET requests works with same Origin header

STRML commented 6 years ago

I believe you can modify it to the correct origin via onBeforeSendHeaders.

janisdombr commented 6 years ago

What do you mean correct origin? chrome-extension://... is correct and I can't change it because of browser sequrity. Refused to set unsafe header "Origin" If you can do it, please, help me to do that.