403 response code for any POST request to Interactive Brokers Client Portal Web API
Asked Answered
R

5

8

I try use Interactive Brokers Client Portal Web API:

  • I succesfully start gateway and login.
  • I succesfully make GET requests to various end-points.
  • When I make POST request to any end-points, I receive 403 response code.

For example, I try update currently selected account:

// it is need for change User-Agent as recommended*
chrome.webRequest.onBeforeSendHeaders.addListener(function (details) {
    for (var i = 0; i < details.requestHeaders.length; ++i) {
        if (details.requestHeaders[i].name === 'User-Agent') {
            details.requestHeaders[i].value = 'Console';
            break;
        }
    }
    return {requestHeaders: details.requestHeaders};
}, {urls: ['<all_urls>']}, ['blocking', 'requestHeaders']);

// it is code of make of POST request
var data = {};
data['acctId'] = 'U1234567';
var xhr = new XMLHttpRequest();
xhr.open('POST', 'https://localhost:5000/v1/portal/iserver/account', true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(data));
xhr.onreadystatechange = function () {
    if (xhr.readyState == 4) {
        sendResponse({Status: xhr.status + '_' + xhr.responseText}); // I have "403_" response
    }
};

*: Making POST request from console app results in Error 403 - Access denied

Headers of my request:

Cookie: SBID=xskr4cf7kflki7wrzzy; XYZAB_AM.LOGIN=29c2d567b3a3f23d8d02bdd5ef78d0c8c2694438; XYZAB=29c2d567b3a3f22d8d12bdd5ef78d0c8c2694438; api=673d21e86cf499f04b985446a90a844b; ibkr.nj=286565962.20480.0000
Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7,uk;q=0.6
Accept-Encoding: gzip, deflate, br
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: none
Origin: chrome-extension://jnblchdcckkmedocgchlfmfhbaihjdnl
Accept: */*
Content-Type: application/json
User-Agent: Console
Content-Length: 21
Connection: close
Host: localhost:5000

Body of my request:

{"acctId":"U1234567"}
Rabia answered 15/12, 2020 at 11:41 Comment(0)
H
4

As described above, we can resolve this by adding 'User-Agent': 'Console' to the header. You can use Python requests to send the header alongwith as below.

import requests

headers = {'User-Agent': 'Console', 'content-type': 'application/json'}

response = requests.post(url, data=data, headers=headers, verify='path to .pem file or False if SSL is not needed')

where url is the string containing the post URL and data is the json data you need to submit to POST request.

Headstream answered 2/9, 2021 at 9:6 Comment(0)
M
2

I resolved this issue by populating the User-Agent and sending an empty string as the POST payload to ensure the Content-Length header was being set, ex. calls made to the /tickle endpoint.

Monosome answered 14/4, 2021 at 23:51 Comment(0)
R
1

I solved the problem. The fact is that a “Client Portal WebAPI gateway” is not just a gateway, it is a server that allows you to host your HTML-pages with your code on it. After launching the gateway as described here https://interactivebrokers.github.io/cpwebapi/index.html#login and authorization on the https://localhost:5000/ page, you can go to the https://localhost:5000/demo/#/ and see a small demo application with very complex code, which is beyond my primitive knowledge. Therefore, I replaced the index.html file in the root\webapps\demo folder with my own and wrote my own javascript code for the POST-request

var data={};
data["symbol"]="RSG";
data["name"]=false;
data["secType"]="STK";
var xhr=new XMLHttpRequest();
xhr.open("POST", "https://localhost:5000/v1/portal/iserver/secdef/search", true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(JSON.stringify(data));
xhr.onreadystatechange=function()
    {
    if (xhr.readyState==4)
        {
        console.log(xhr.status);
        console.log(xhr.responseText);
        }
    }

and it worked, since now the index.html page of my application and the end-point are on the same domain localhost:5000, so mod_security rejection does not occur and everything works!

Rabia answered 18/12, 2020 at 22:33 Comment(1)
Your workaround only applies by using the same API calls within the same component, which I think is not optimal as you will not be able to build an external application using REST API from the Gateway.Banas
M
0

did you performe insecure https POST requests ?

On my side insecure https GET requests are working fine, but I think it generates "403" for POST requests. On my way to try with a self-signed cert

Microfiche answered 11/1, 2021 at 16:46 Comment(1)
Yes I make insecure https POST requests. I also thought that the reason was an expired certificate, but what was the real reason I described above. Now I see a warning that the connection is not secure, but everything works.Rabia
P
0

The question was marked as resolved, but I managed to resolve the similar issue by simply setting the User-Agent in the header to anything. My current app is NodeJS using the request module. Set the User-Agent to quite literally anything and make sure you handle the insecure SSL certificate.

Precipitancy answered 27/2, 2021 at 5:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.