API: WebControl - A REST API for Sponge

WebControl

WebControl opens up a RESTful API which will securely allow server owners and developers to write web, mobile, and desktop applications which can execute commands, get information from, and control the Sponge server through a web API. Here’s an example.

POST /wc/chat/broadcast HTTP/1.1
Content-Type: application/json
Content-Length: ...

{"_key": "dcc9476d5b901f788357ad0dd09801e4c01dd13fc887fdfdc528d53770a5187b",
 "_username": "helloworld",
 "data": {"text": "Hello, world!"}
}

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: ...

{"success": true}

Through WebControl’s API, you can do things like send chat messages, send private messages, teleport players, spawn mobs, interact with the world, get data about the world and players – basically anything Sponge’s API will allow you to do.

Security

Security will take some time to figure out. Take everything here with a grain of salt, but rest assured that WebControl will be safe and secure, so long as you take the proper precautions with it.

Download

Nothing yet… but if you want, you can watch and participate in development on my GitHub: GitHub - tman0/WebControl: A RESTful API for Sponge
Documentation will be available soon.

Not all requests to your API will be POST requests(some will be GET or something similar), so the key should be in the querystring and not in the POST body.

Now, more on the keys, just don’t share your hashes of passwords, that’s an extremely bad idea. First, allow basic HTTP auth on any request for one-off things by people testing your API. Then, use a long, cryptographically strong session string that users can authenticate with that expires daily/bi-daily/weekly. They should be able to generate a new session string to use anytime they want as well as refresh all registered session strings if they feel as if their account has been compromised.

7 Likes

I think you should start with Apiary / API Blueprint. It does testing AND docs. On the other hand, I’d LOVE to help.

Not all requests to your API will be POST requests(some will be GET or something similar), so the key should be in the querystring and not in the POST body.

Now, more on the keys, just don’t share your hashes of passwords, that’s an extremely bad idea. First, allow basic HTTP auth on any request for one-off things by people testing your API. Then, use a long, cryptographically strong session string that users can authenticate with that expires daily/bi-daily/weekly. They should be able to generate a new session string to use anytime they want as well as refresh all registered session strings if they feel as if their account has been compromised.

Thanks for the input. I’m still up in the air as to what sort of security system I want to put in. This will likely be what I end up using, though.

I think you should start with Apiary / API Blueprint. It does testing AND docs. On the other hand, I’d LOVE to help.

I like it. I’m going to get going on documentation very soon. You’re more than welcome to submit pull requests or look through my code for some TODOs - I’ve already got my first in there. I’ll make some issues on Github for the features, and if you want to claim any just let me know on there.

Also, just a heads up: if anyone forked the repo, please delete it and fork it again. I had to delete and recreate the repo on Github.

If you are using HTTP and RESTful services, I would argue that the key should be in the HTTP headers, actually. The key is not really anything to do with the request, it’s more metadata when you think about it, and it has no bearing on the actual action you are going to make.

For example, say I want to get player x from the server. I might choose the route:
GET server:port/players/1
RESTful principles state that for a GET request, if the URL doesn’t change, you should get the same object. If you have a changing key on the end of that…
GET server:port/players/1?key=blah
you actually break that principle. Similar with POST/PUT requests, the URL should define the location and restrictions of the object and nothing more, and should never change.

You’ll also want to look at HMAC or some similar algorithm to verify the integrity of the message. That way, if the HMAC digest is sniffed, the only thing that can actually be done is a replay attack - when I helped write a RESTful API recently, we included a UTC timestamp and a 10 minute window so that we could save messages in a cache a detect such attacks.

Looks interesting. I might be interested in contributing at some stage. My advice for now is to not worry about security for now, and get the basic calls in, flesh out what you want the system to do. You can work on the security aspects later. If done right, the security can just be “bolted on”.

1 Like

I’m mostly modeling this based on other APIs, including github’s. But you are right, it can be provided as a header as well, this slipped my mind. I think the querystring option is provided for one-off testing.

Ah, that’s OAuth, which is a completely different thing! The idea of OAuth is that a temporary key is sent to a server from a server via a one time URL on the client, which allows server-server communication.

I had fun trying to learn about that recently…

I do know what OAuth is. You’re talking about the OAuth handshake and web flow, not actual API usage with OAuth. Github uses an OAuth token obtained after the original handshake which is functionally similar to the random session string I suggested. Regardless, even if it were something different, it’s still authenticating somehow using the querystring.

EDIT: See Github’s authorization endpoint, which is the exact same as the endpoint I suggested eariler.

I know exactly what I’m talking about. I was responding to your suggestion:

Your suggestion was to include the key in every request as a GET parameter. My point was that doing that is not the way it should be done in a RESTful manner. Indeed, in the API I recently helped build, we did something similar to Github’s authorisation endpoint, then used the private secret to generate the HMAC signature.

We could go in circles about this - but we’re pretty much already agreeing on the points anyway! Apologies for any confusion on my end!

My other concern would be encryption - no amount of hash based authorisation is going to help if you try to authenticate in the clear. That’s going to need some thinking about at some point.

Well, this is great! I used to use JSONAPI with bukkit… The plugin is similar and should be ported. In any case, I’m bringing it up because it’s open source and can be of help.


As long as the MC server and the Web Server are in the same network (or machine), there shouldn’t be any problem, but when the Internet is involved and because sensitive data can indeed be exchanged it would be nice if this data could travel over a secure connection…