0

I am hosting a simple website that does nothing more than to call an API when a button is clicked. The API im calling (Home assistant) requires the password to be included in the header. This works fine when testing, but how do i do this in a secure manner?

My ajax call to the API currently has the password in cleartext, and can be viewed by anyone who inspects the .js file.

    function ToggleAPI(){
    $.ajax
    ({
      type: "post",
      url: "https://exampledomain.org:8123/api/services/switch/toggle",
      dataType: 'json',
      headers: {
            'x-ha-access': 'MyPasswordThatCanBViewdByAnyone',
            'content-type': 'application/json'
        },
      async: false,
      contentTtpe: 'application/json',
      data: JSON.stringify( {
        "entity_id": "SomeId"
      }),
      success: function (data){
        console.log("Sucess",data);
      },
      error: function(err){
          console.log("Error",err);
      }
    });

}

The API is running on the same computer as the web-server hosting the site. (The setup is raspberry pi running Home Assistant, and a NGINX server hosting the website)

What is the correct way of calling the API and provide the password, without having it in the .js file?

chba
  • 33
  • 4
  • You have to use webApi gateway in this case.this secure header should be add on gateway side based on some criteria. – NullPointer Jun 30 '18 at 17:13
  • You use a JWT: https://jwt.io/introduction/ – Asons Jun 30 '18 at 17:15
  • So Nginx proxies the ajax request to the Pi? – miknik Jun 30 '18 at 17:20
  • Also look at this answer: https://stackoverflow.com/questions/319530/restful-authentication/7158864#7158864 – Asons Jun 30 '18 at 17:22
  • So the case is that Home Assistant serves an API in which I cannot control, only consume. I see that a token would be preferable, but I cannot see how I can implement it in my current setup. @miknik Nginx hosts the html and js file, so yes it provides the request to the Home Assistant instance also running on the pi. – chba Jun 30 '18 at 17:32

1 Answers1

0

First up you want to route everything through Nginx and disable public access to the Pi. Bind the network interface of the Pi to only listen for requests on your local network and firewall external requests to block all ports except 80 (or 443 if you have SSL).

Within the server block for your website in your Nginx conf file you can now set up a location which will proxy requests to the Pi. URL doesn't have to match the URL on the Pi if you want it to be something more memorable. Something like this:

location /switch{
proxy_pass http://pi.ip.address.here:8123/api/services/switch/toggle/;
proxy_set_header x-ha-access MyPasswordThatCanBViewdByAnyone;
proxy_set_header X-Real-IP $remote_addr;
}

Restart Nginx and now a request to https://exampledomain.org/switch will be proxied by Nginx to your Pi, with the password header added and original client IP in the X-Real-IP header

miknik
  • 5,748
  • 1
  • 10
  • 26
  • No **standard basic authorization header** man.Check the API link – NullPointer Jun 30 '18 at 17:38
  • Check edit, you can add whatever header you like in Nginx – miknik Jun 30 '18 at 17:38
  • Thank you! I think this answer got me in the right direction. I will read up on the Nginx docs and see how I can add the headers. – chba Jun 30 '18 at 17:45
  • Is this URL being proxied by Nginx, or does it actually point straight at the Pi? `https://exampledomain.org:8123/api/services/switch/toggle` Judging by the port number Im guessing the latter? – miknik Jun 30 '18 at 17:51
  • no proxies set up, it actually points straight to the PI via the public domain. Note that the site itself will be password protected. – chba Jun 30 '18 at 17:59
  • OK, you'll need to proxy it through Nginx. I'll edit my answer – miknik Jun 30 '18 at 17:59
  • Ok, so just using the default Nginx site setup in /sites-available/default I would add the headers here? Inside the nested server{ location / { proxy_set_header x-ha-access MyPasswordThatCanBViewdByAnyone; } } – chba Jun 30 '18 at 18:13
  • Edited with more info – miknik Jun 30 '18 at 18:18
  • You might have to drop the final slash from `proxy_pass http://pi.ip.address.here:8123/api/services/switch/toggle/` or add a slash to `location /switch`. One way around it adds the request URL to the end of the proxy url and the other way around it doesnt, and I can never remember which is which. – miknik Jun 30 '18 at 18:30