views:

257

answers:

7

I have a JSON web service to return home markers to be displayed on my Google Map.

Essentially, http://example.com calls the web service to find out the location of all map markers to display like so:

http://example.com/json/?zipcode=12345

And it returns a JSON string such as:

{"address": "321 Main St, Mountain View, CA, USA", ...}

So on my index.html page, I take that JSON string and place the map markers.

However, what I don't want to have happen is people calling out to my JSON web service directly.

I only want http://example.com/index.html to be able to call my http://example.com/json/ web service ... and not some random dude calling the /json/ directly.

Quesiton: how do I prevent direct calling/access to my http://example.com/json/ web service?


UPDATE:

To give more clarity, http://example.com/index.html call http://example.com/json/?zipcode=12345 ... and the JSON service
- returns semi-sensitive data,
- returns a JSON array,
- responds to GET requests,
- the browser making the request has JavaScript enabled

Again, what I don't want to have happen is people simply look at my index.html source code and then call the JSON service directly.

+2  A: 

If you are using Apache you can set allow/deny on locations.

http://www.apachesecurity.net/

or here is a link to the apache docs on the Deny directive

http://httpd.apache.org/docs/2.0/mod/mod_access.html#deny

EDITS (responding to the new info).

The Deny directive also works with environment variables. You can restrict access based on browser string (not really secure, but discourages casual browsing) which would still allow XHR calls.

I would suggest the best way to accomplish this is to have a token of some kind that validates the request is a 'good' request. You can do that with a cookie, a session store of some kind, or a parameter (or some combination).

What I would suggest for something like this is to generate a unique url for the service that expires after a short period of time. You could do something like this pretty easily with Memcache. This strategy could also be used to obfuscate the service url (which would not provide any actual security, but would raise the bar for someone wanting to make direct calls).

Lastly, you could also use public key crypto to do this, but that would be very heavy. You would need to generate a new pub/priv key pair for each request and return the pubkey to the js client (here is a link to an implementation in javascript) http://www.cs.pitt.edu/~kirk/cs1501/notes/rsademo/

Joshua Smith
When people say "JSON" in the context of a web page they usually mean XHR, which Deny will block if used indiscriminately.
Ignacio Vazquez-Abrams
I believe if I used this method, that would deny EVERYONE access to my web site. ... Meaning, this would NOT WORK
FrankLy
@FrankLy: Well, if you do it within a `<LimitExcept POST>`...
Ignacio Vazquez-Abrams
It would only deny EVERYONE access to your web site if you specified to deny everyone. You can add deny/allow based on location.
Joshua Smith
... And where exactly will the hackers be coming from, Joshua?
Ignacio Vazquez-Abrams
From his original question (before the edits) it looked to me like he was wanting to restrict access to that service in such a way that only the server could call the service. He's added edits that clarify and now that interpretation is clearly not correct.
Joshua Smith
+2  A: 

Accept only POST requests to the JSON-yielding URL. That won't prevent determined people from getting to it, but it will prevent casual browsing.

Ignacio Vazquez-Abrams
How to I do POST XmlHttpRequest? I thought you could only do GET requests.
FrankLy
XmlHttpRequest can do any method, including methods you make up. The first parameter when you open a request is the method, which is an arbitrary string.
Dietrich Epp
I use something like jQuery that knows how to POST XHR. http://api.jquery.com/jQuery.post/
Ignacio Vazquez-Abrams
It's not really what POST was meant for, but it'll work...
Matchu
A: 

You'll probably have to have some kind of cookie-based authentication. In addition, Ignacio has a good point about using POST. This can help prevent JSON hijacking if you have untrusted scripts running on your domain. However, I don't think using POST is strictly necessary unless the outermost JSON type is an array. In your example it is an object.

Matthew Flaschen
The reason for using POST is not security. It's due to the fact that the default method browsers use when you stuff a URL in the location bar is GET. If GET isn't allowed at the server then they don't see the JSON.
Ignacio Vazquez-Abrams
Ignacio, take a look at my link. POST can help defeat a particular JSON hijacking attack.
Matthew Flaschen
Sure. But that's not why I suggested it.
Ignacio Vazquez-Abrams
+5  A: 

There are a few good ways to authenticate clients.

  • By IP address. In Apache, use the Allow / Deny directives.
  • By HTTP auth: basic or digest. This is nice and standardized, and uses usernames/passwords to authenticate.
  • By cookie. You'll have to come up with the cookie.
  • By a custom HTTP header that you invent.

Edit:

I didn't catch at first that your web service is being called by client-side code. It is literally NOT POSSIBLE to prevent people from calling your web service directly, if you let client-side Javascript do it. Someone could just read the source code.

Dietrich Epp
Wouldn't the Allow / Deny *not* work because that would deny everyone to index.html which CALLS the JSON request.
FrankLy
Dietrich, exactly - people reading my source code is the concern. So no way to prevent?
FrankLy
Correct, NO way to prevent. It's like handing someone a set of keys and telling them only to open the door on Thursdays.
Dietrich Epp
Agreed, no way to prevent. Other threads have discussed this as well - http://stackoverflow.com/questions/2561999/how-can-i-validate-secure-authenticate-a-javascript-based-post-request and http://stackoverflow.com/questions/2576509/wcf-rest-based-services-authentication-schemes/2576824#2576824
sri
A: 

Here's yet another method using mod_security

http://www.modsecurity.org/documentation/Ajax_Fingerprinting_and_Filtering_with_ModSecurity_2.0.pdf

Azeem.Butt
A: 

I have a similar setup, not sure but I need an aswer as well.

Hank
+1  A: 

Some more specific answers here, but I'd like to make the following general point:

Anything done over AJAX is being loaded by the user's browser. You could make a hacker's life hard if you wanted to, but, ultimately, there is no way of stopping me from getting data that you already freely make available to me. Any service that is publicly available is publicly available, plain and simple.

Matchu