1

I am using AmCharts Wordpress plugin to generate graphs on a Wordpress page. To have the graph load its shape and (external) data, AmCharts uses Javascript to load on the client side when generating the graph. However, this javascript also contains the URL to the API used to retrieve the external data.

This means that anyone can easily view the web site source code and see this link. This is a risk as anybody can now manipulate the URL and download our full database with data.

I have added the first part of the JavaScript code below. the URL part I like to obscure is https://api.xxxxxxx.com/

Any way this is possible? What options are available?

Thanks for any help!

 try {    
    // Themes begin

    var chart = am4core.create("amchart1", am4charts.XYChart);
    var from = Math.round(+new Date() / 1000) – 2629743;
    var to = Math.round(+new Date() / 1000) + 2629743;

    chart.dataSource.url = 'https://api.xxxxxxx.com/' + from + '/' + to;

    chart.dataSource.events.on(“parseended”, function(ev) {
    // parsed data is assigned to data source's data property
    var data = ev.target.data;
    for (var i = 0; i < data.length; i++) {
       if(data[i]["realtime_value"] == 0)
          delete data[i]["realtime_value"];
    }

    console.log(‘data’, data);

    });

    // create date axis

...
squaleLis
  • 6,116
  • 2
  • 22
  • 30
xbmcgotham
  • 33
  • 3
  • 1
    That's the case with *anything* you use in JavaScript - everything is publicly accessible. Any code you write to obscure it through JS can easily be reversed engineered as the user has access to the code used to hide it in the first place. You're better off solving this problem at the server stack level (PHP or whatever) by implementing security or additional logic to prevent abuse when the URL is accessed. – xorspark Mar 08 '19 at 11:43
  • @xorspark thanks for your response. I have been searching for additional logic, without any luck. Anything more specific you could refer to? – xbmcgotham Mar 08 '19 at 16:00
  • 1
    Look into resources in how to build and secure an API, rate limiting/throttling, adding tokens, etc. Note that [you can't _completely_ prevent abuse](https://softwareengineering.stackexchange.com/questions/251707/client-side-coding-how-to-prevent-malicious-use), but you can at least minimize the impact. – xorspark Mar 08 '19 at 18:18

2 Answers2

1

I'm not familiar with the WordPress plugin or how it works, so all of this is completely neglecting the WP plugin.

My first thought is to grab the data server side and dish out it out on page load. This way the API url is obfuscated and the user is saved another HTTP call as the data is already present on the page.

If that is not an option, instead of providing the API call directly, create a script on your server that functions as a reverse proxy to the API. Your clientside calls will get the URL to your server and it's up to you how you want to secure it to whatever extent.

E.g. chart.dataSource.url = 'https://your.site/reverse-proxy/' + from + '/' + to;. Then at https://your.site/reverse-proxy/ you check and clean the from & to inputs, grab the data from 'https://api.xxxxxxx.com/' + from + '/' + to (e.g. via curl), and send it back to the client with appropriate e.g. JSON headers.

Any of these ideas work for you?

notacouch
  • 3,657
  • 1
  • 19
  • 27
  • 1
    Thanks for the explanation, appreciated. The only thing I would think of is that the reverse-proxy would still be readable and you will end up with the same issue? – xbmcgotham Mar 14 '19 at 08:29
  • The reverse proxy is readable, but you can change its parameters and how you secure it, e.g. only requests from such and such page, or instead of `from`/`to` it could be somehow more specific to your charts. Basically you can do whatever it is you want to try and obscure the parameters. – notacouch Mar 14 '19 at 17:59
  • 1
    Thanks for explaining. I will have to dig deeper into this. For the time being I found another option which builds in an extra step in between which will retrieve the MYSQL data and outputs it to JSON on the page load. – xbmcgotham Mar 15 '19 at 15:21
  • Yes, I saw your answer. If that is a viable option that is indeed the best way to go, though instead of using mysql methods directly, if WordPress or any other PHP library is already active on the page, I'd try and lean on whatever database querying utilities they have, especially once/if the queries are affected by user input/interaction. This way the queries can be cleaned/protected. – notacouch Mar 15 '19 at 19:02
1

Thanks all for your help. Appreciated. In the end it seems that the only real safe option is to retrieve it first Fetch your data from a DB table using a SELECT query, then create an array that you can JSON-encode in an amCharts compatible format. Might be as simple as this:

<script>

<?php
  $sth = mysqli_query("SELECT ...");
  $rows = array();
  while($r = mysqli_fetch_assoc($sth)) {
    $rows[] = $r;
  }
  print "var data = " . json_encode($rows) . ";";
?>

console.log('data from server', data);

</script>

Your actual output should then look like this:

<script>
var data = [{
  "category": "1",
  "value": 5
}, {
  "category": "4",
  "value": 10
}];
console.log('data from server', data);
</script>

All your users will see in the source code is this JSON array. No URLs, no server details.

xbmcgotham
  • 33
  • 3
  • Yes, this is what I meant when I said "My first thought is to grab the data server side and dish out it out on page load." – notacouch Mar 14 '19 at 18:00