I have a facebook application, and some functionalities require some sripts running via ajax. Is there a way to ensure that the script is only called from inside my app? I use jquery for the ajax calls like this:
$.post('script.php', {var1: val1, var2: val2}, function(data){...});
.
The code inside script.php runs some sql queries and just check that all requested variables are passed through the ajax call.
What else should i check so that the script can only execute if called from my app and not by explicit calls?
Thanks in advance.
There are very few ways that you can make sure with 100% certainty that the Ajax request is being called from your app. If that was a mission-critical (high-security) requirement, then I would secure it the same way that I would secure any particular web resource:
- Use SSL
- Require a login gateway to establish a session
- Check the validity of that session before allowing the request to process
If you don't want to go through the hassle of establishing a session, then there are less certain, but still quite helpful means of preventing access (causal access, that is):
Check for the presence of two request headers: Referrer and X-Requested-With. Referrer should contain the URL of your base page, and X-Requested-With should contain XMLHttpRequest. These can be faked, but it would require a much more determined "attacker" than someone simply browsing to the URL directly.
I don't think you can completely eliminate all calls outside the context of your page.
- You can't base it off the source of the request if it is callable from any machine
- You can't base it off the contents of the request as that can be network-sniffed and forged
If you can restrict to specific machines/IPs, then simply do that. Keep a list of white-listed machines server-side, and make sure the request comes from one of those.
The best you could do besides this is require authentication, in which case you could throttle request volume per-account.
Well a rotating public/private key would help ensure identification, maybe encrypt the data stream using a private key.
On some of my more secure applications i assign a public key to a specific IP address. If that IP does not provide that key in the request stream, I treat it as an illegal request and ignore it.
To go one step further you can lock down your requests at the server level for that path to that specific ip/host name.
It just really comes down to how secure/usable do you want your web service to be.
What you want to do is employ mutually-authenticated SSL, so that your server will only accept incoming connections from your app and your app will only communicate with your server.
Here's the high-level approach. Create a self-signed server SSL certificate and deploy on your web server. Then create a self-signed client and deploy that within your application in a custom keystore included in your application as a resource. Configure the server to require client-side SSL authentication and to only accept the client certificate you generated. Configure the client to use that client-side certificate to identify itself and only accept the one server-side certificate you installed on your server for that part of it.
If someone/something other than your app attempts to connect to your server, the SSL connection will not be created, as the server will reject incoming SSL connections that do not present the client certificate that you have included in your app.
Note that this depends on how well your app can protect the client-side certificate and the associated private key.