3

I have a simple website that's hosted on an Azure Web App that's literally just one .html file, one .css file, and one .js file. It uses the Bing API to get data and chartjs to graph that data on the page.

The issue is I obviously don't want to store the API key in the code anywhere anyone else can find it, so I'm not sure where to put it. I tried setting up an Azure Key Vault and adding the API Key as a secret, so I could just do a REST GET and retrieve the key, but I'm not sure how to setup permissions to allow the server the Web app is on (and only that server) to access it.

The more I research do and reading other similar questions the more I feel like this isn't the best solution out there (couldn't anyone just intercept the response in plain text?), but I'm yet to find a "best practice" for this problem. Any alternative solutions or advice on how to make this work are welcome.

EDIT: The more I'm thinking about this the more I realize using the Key Vault won't work. There is no server side to this application, so the request for the API key will come from any IP. I'm thinking I'm going to have add a whole server side application for this to work. Just to give you an idea of what I've got going on so far here's some pseudo code.

----------index.html----------
<head>
    <script src = "./chart.js"></script>
</head>

<body>
    <canvas id="mainChart" width="400" height="400"></canvas>
    <script src="./app.js"></script>
</body>


----------app.js----------

var BING_API_KEY = "myprivatebingapikey";
var CLIENT_ID = "bingapikeyclientid";

function getData() {
    return new Promise(resolve => {
        var xhttp = new XMLHttpRequest();
        xhttp.open("GET", "https://api.cognitive.microsoft.com/bing/v7.0/myquery", true);
        xhttp.setRequestHeader("Ocp-Apim-Subscription-Key", BING_API_KEY);
        xhttp.setRequestHeader("Accept", "application/json");
        xhttp.setRequestHeader("X-MSEdge-ClientID", CLIENT_ID);
        xhttp.onreadystatechange = function() { 
             if (xhttp.readyState == 4 && xhttp.status == 200) {
                var response = JSON.parse(xhttp.responseText);
                if (!response.value || response.value.length <= 0) {
                    throw Error;
                }
                resolve(parseData(response.value));
            }
        }
        xhttp.send(null);
    });
 }

function parseData(data) {
    // put the data into global variables
}

function graphData() {
    await getData();
    var chart = new Chart(document.getElementById('mainChart'), 
        data: { // all the data from the global variables },
        labels: { // labels from global variables },
        options: { // predefined options }
}

graphData();

The code isn't perfect, but it's just to give you an idea about how it's set up.

James Wood
  • 17,286
  • 4
  • 46
  • 89
TJ_
  • 328
  • 2
  • 13
  • 3
    Yeah, no matter how that key comes to the front-end JavaScript code, it can be intercepted in the request just by using the browser F12 tools. You need some kind of back-end to keep the secret *secret*. – juunas Apr 01 '18 at 19:26
  • @juunas you should post that as an answer – Maria Ines Parnisari Apr 01 '18 at 22:07

1 Answers1

2

It looks like you have realised you will need some kind of server side code to keep your secrets secret. Even if you store your secret in a Key Vault that won't help, anyone could just open a web debugger (F12) and see the secret in plain text.

I would suggest an Azure Function with something like an HTTP trigger. This will enable you to build a very light weight server side web service. Put all your getData() code into the Azure Function (you can provide the implementation in JavaScript), along with your secrets. Call the Azure Function in your JavaScript client side to get the data you need for the chart.

An introduction to Azure Functions

Azure Functions is a solution for easily running small pieces of code, or "functions," in the cloud. You can write just the code you need for the problem at hand, without worrying about a whole application or the infrastructure to run it. Functions can make development even more productive, and you can use your development language of choice, such as C#, F#, Node.js, Java, or PHP. Pay only for the time your code runs and trust Azure to scale as needed. Azure Functions lets you develop serverless applications on Microsoft Azure.

James Wood
  • 17,286
  • 4
  • 46
  • 89