Securing an API?

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?

1 Like

OOOOPS sorry totally glossed over your question.

Follow the ticketing system they discuss here -

There are several other useful points. I’d suggest researching further but Heroku are generally a decent source.

1 Like

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.

Sounds good to me. Just make sure you’re only storing a hash of the password on the server.

1 Like

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.

If I’m using helmet with cors, do I still need to use jwt middleware?

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.

> SecureRandom.hex 32
=> "4e6520955a2acc0573f002172f449f8530c2361e3e2b88d89c5df76447aacb78"

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.

Unless I am thinking wrong.

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?

1 Like

IT just means that non auth clients can hit your endpoint and fetch data from the api. Totally fine to do so, unless its sensitive data.

I thought that the session might keep it secure for an example of a website?

If the session had something to indicate that the current user is logged on and who the user is.

I’ve been running 40 hours without sleep - I’ll respond properly tomorrow!!!

1 Like

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.

1 Like

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.

@SgtAwesomesauce

1 Like

Give me some time here guys - I think I’ll put a live-stream for you guys and schedule a time so you can Q&A me on this, and I can explain better.

1 Like

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.

1 Like

Haha…