I’m making an API to read/write attributes from my ArduPilot drone using WebSockets. The idea is I will be able to easily produce web apps to manipulate functions on the drone (i.e. a web app for gimbal control, other features that the controller sucks at)
Obviously there is inherent risk with this, and I’m not going to go give this thing a public IP where everybody can access it. It will stay within a small local network. But just for giggles, what would be the best practices for securing such a thing? An API controlling a physical thing seems fairly high-risk compared to your typical web API that fetches weather data or info about stocks.
Right now, to get access, clients have to send a hello message with a pair of 20 character keys (essentially a username and password) that have to match up with a set on the server side. And the WebSockets connection will be encrypted so that’s not an issue. Is there a better way I should handle the whole key thing? Any inherent massive flaws I’m missing?
Again, this is not going to be used to do anything super dangerous, I’m just a college kid screwing around with programming/security for drones.
API security basics - you want to send an authenticated token as part of the header. This is called token-based authentication. Quick example.
curl -H "Authorization: Basic <ACCESS_TOKEN>" -X POST https://specialitymeats.com/sausage/list
You’ll want to setup the authentication ideally as middleware, or something baked into a root controller so that any access via sub-controllers are by default authenticated. I typically authenticate a namespace by default in this manner /api/v1/meats…
CAVEAT above example should be GET typically, but that doesn’t matter in my contrived example…
Is that still true with WebSockets though? I understand why you’d want to send a token with an HTTP request since it’s a new connection at the TCP level every time. But since WebSockets is continuous and full-duplex and SSL encrypted…is it still necessary?
Tad older, but some interesting coverage on the topic
In the past I’ve enjoyed developing in Spring as well, and these guys are definitely into security - it’s a 2018 post too. Irrespective of tech stack, the general approach is there to take away.
In this case, why? It’s not a word, it’s a randomly generated string like an API key. And since this will be accessed from JavaScript clients, I’d have to store the password on the clients in plain text unless I want to send the hash over the network. But then does that actually help anything? One randomly generated string is as good as another in this case, it would seem. Correct me if I’m overlooking something though.
Not sure what you mean about ‘password’, but in Ruby at least you can use BCrypt to generate hashes (of passwords) and there’s a simple API to compare said hash to a password.
For tokens, I like to use this, longer the better.
Does storing it in a hash really do any good though? Since the password would either have to be stored in a hash on the client-side (in plain text, since it’s JavaScript) or stored in plain text and then turned into a hash? You’re either storing your password in plain text on the client side or you’re vulnerable to a pass-the-hash type attack, but it doesn’t really matter because WebSockets is encrypted.
Uh no - you never store passwords in any form on the client side. Always rely on the backend.
One example is taking the session ID and using Bcrypt to treat that as a password - let’s call the result ‘session hash’ right? You can send this token in XHR (JS) requests for every payload.
The backend controller has to only then compare the session hash with the session ID (performing a ‘decrypt’, essentially); if there’s a mis-match you can guard agains XSRF and other things.
May not answer your question directly (as I don’t completely follow why you want to store password hashes client side) but thought I’d share the example in any case - as I’m sticking to your original question on “How to secure API calls”
This is pretty random and probably a dumb question @bsodmike but how does this secure a web api this say for a website by using a token? I have done this before in an internship or I should say I know it was being used but if you are using a raw api what could happen if you dont use the token?
I would do that, but I also don’t want to leave the door open to DoS attacks since this API will be running on a fairly compact low-power Linux machine.
Very remote chance of anything going wrong, but I don’t need it, so figured I might as well leave it out.
Agreed!! NEVER have a non-authed API, that’s just silly.
Also, proper TLS end-to-end is a must. Once I screwed something up on Digital Ocean, since I’m 99% of the time in AWS VPCs, forgot that VPCs provide you some isolation by default
Some one “accessed” my local (local to the DO droplet that is…) Redis install and installed a password. I only realised cause I got errors saying it couldn’t connect to Redis. I later figured it out and immediately fixed the flaw…
Thankfully I was only using it as a job-queue to process emails being sent out (as Ruby’s main thread locks when handling requests in Rails) — so background-job queuing is very common a la Resque/Redis or Sidekick etc.
This is one that catches newbies rather easily with Docker (it’s internal network gets exposed on bare-metal, on inet docker0). Very dangerous to the uninitiated.
Yep! even if you have open registration, a non-auth’d API gives people like me a significantly lower barrier to entry. You’ll know I’m in when I replace your sausage model with a dead bird model.