Web API security basics

When I proposed the lead developer of an open source web application to enable JSONP for the API, the developer replied:

The whole thing sounds easy enough to implement, but I have some doubts that it will open the project to XSS attack of some sort. Don’t really know why, though. 🙂

We mailed a bit more about the risks of cross site scripting and then he wrote the following:

Sadly we can have malicious JS problems since cleaning up of incoming data is optional.

For an unrelated project I asked about authentication for a write-operation in the API and the reply was:

Authentication is not in the API yet. Currently you must include a session cookie along with API requests to perform a write, but the cookie itself is the one you get from logging in [in the web front end] as you would normally.

Which sounds a lot like “we support cross site request forgery out of the box” …
As with normal web applications, web API-security is an important (but complex) issue, which is not always easy to grasp. Based on a basic understanding of things, the following guidelines can go a long way into securing things both on the API-side and the client:

  1. Know who you’re dealing with; disable API-access for your users by default (allowing them to opt-in), provide bullet-proof authentication and session management in the API and throw in a synchronizer token to prevent cross site request forgery
  2. Never trust input from users or external systems; decide what to trust and filter out everything that’s not in that white-list (SQL-code, server-side code, javascript, and even html and css)

If you apply these basic principles to JSONP (make sure to filter the callback-parameter and set the correct content-type in your response) you’ll have a whole lot less to worry about!
More info:

No more jsonp for Google geocoding webservice?

I needed to do some reverse geocoding in a javascript webapp. The Google Maps API worked flawlessly, but it seemed overkill to load all that javascript just to do one lousy reverse geocoding lookup (esp. on a mobile device, my target platform).  I searched some more and found the Google geocoding webservice, which is invoked with a simple HTTP GET request and returns the response in JSON. Version 2 of this service works great, as you can specify a callback-function to do jsonp (a simple method to allow for cross domain ajax requests),
This example request for v2, http://maps.google.com/maps/geo?q=51,4&sensor=false&output=json&callback=parseme, results in a response containing a call to your own “parseme”-function, with the json-object as the payload;

parseme && parseme( {
"name": "51,4",
"Status": {
"code": 200,
"request": "geocode"
},
"Placemark": [ {
"id": "p1",
"address": "Brukkelen 191, 9200 Dendermonde, Belgium",
...
]})

But a month ago Google announced a new version of their geocoding webservice and the documentation for V2 mentioned that it was deprecated in favor of the Geocoding V3 Web Service. so I switched to the new API, only to discover that callbacks aren’t supported any more.
An example request for v3 http://maps.google.com/maps/api/geocode/json?latlng=51,4&sensor=false&callback=parseme results in nothing but the javascript-object:

{
"status": "OK",
"results": [ {
"types": [ "street_address" ],
"formatted_address": "Brukkelen 191, 9200 Dendermonde, Belgium",
...
]})

And that, my dear fellow travellers, sucks big time. JSON without the P means we’re back to useless proxy-scripts on our servers. So until Google lets Jason pee (sorry folks, I just had to write this) in the V3 geocoding webservice, I’ll continue using the deprecated V2 with sweet -but undocumented- callback!