Restricting RESTful API Access To HTTP Request From Within Domain

I believe I asked this question before, but I’ll try again.

Anyway, I have your standard MVC based web application with a model layer. I would now like to to expose that model layer directly to my client side interface via AJAX. However, all the AJAX request will really do it hit a URL that returns JSON or XML data. So at this point my REST API exposes ALL data access methods throughout my application to the public, by hitting the endpoint. This is obviously no good. So I was wondering if there is a reliable and secure way to restrict the REST API access to the site, or more specifically an internal HTTP request via AJAX. I’m not sure this is possible, but It would be the ideal solution.

Just to have a better idea of what I’m trying to do is essentially decorate JQuery with a data access method specific to my application. So that the below code would essentially make a HTTP request to find a node with the id of 90.


$.app.dao({
	pkg:'Component.Node.DAO.DAONode'
	,method:'findById'
	,args:[90]
	,success:function(...) {
	}
	,error:function(...) {
	}
});


pkg: being the path to the DAO to instantiate
method: the method to call
args: arguments for the method call, in this case 90

success: standard JQuery success callback
error: standard error callback

What the above code will do is generate a standard jQuery AJAX request like the below:


$.ajax({
       url:'http://www.myapp.com/dao.php/Component.Node.DAO.DAONode/findById/90/'
      ,dataType:json
      ,success: success // the callback passed by the dao decorator
      ,error: error // the callback passed by the dao decorator
});

However, the issue becomes that anyone can easily hit the url: http://www.myapp/dao.php/Component.Node.DAO.DAONode/findById/90/ to get the data. I don’t want this, at all, since I will be calling methods that expose vital data and perhaps perform actions that I want to control internally.

So, is there a reliable way to only allow HTTP requests within the domain to access my REST API? In the end I only want to allow internal access to my applications REST API layer. The whole point of this is to allow client-side code to perform data access operations directly, bypassing the controller layer. However, do that I need to make sure that no one can hit the API endpoint directly.

Thanks

You could try long polling, but that’s rather tricky. You’d still need to authenticate at the start of the polling request though.

Another possibility is web sockets, but that’s only feasable if IE support isn’t required. The larger problem is this solution is experimental by nature since web sockets haven’t been finalized.

Both of these require a persistent PHP script to run, which is an unusual use case.

I was just thinking out loud really.

How about naming it something more general instead of “secret”? That’s like picking your user password as “password”.

Also by minifying your javascript, it will be harder to reverse engineer. It’s not 100% bullet proof but it helps.

You have any examples of how that can be done without exposing the key to the user?


		$.app.dao({
			pkg:'Component.Taxonomy.DAO.DAOTaxonomy'
			,method:'fetchTerms'
			,args:[3,'Vocabulary']
                        ,secret: 'tyr673g#452)))9088jdk^5thd'
			,success:function(data,status,xhr) {
				alert(data[0].system_name);
			}
		});

See the problem?

That is what I would like to avoid, adding a API per operation permission layer on top of the data access layer.

Well I’ll give it to you straight. The two goals you want to achieve here are at ends of one another. You cannot have both.
You could check for the AJAX header and all that stuff but that is easily spoofed.

Expose your model to JavaScript and you expose it to the world, there is no way around that.

How about an API key? Just don’t generate any other keys except for internal use.

No. The method of the request is defined by the HTTP 1.0 protocol, if you add more the behavior is undefined. The difference between GET and POST not only affects client and browser but any proxies in between. Adding an undefined method could cause them to bork en route.

I do something similiar but all javascript traffic goes over POST. Each post request is still going to hold the PHPSESSID from the $_COOKIE array so Sessions can be started normally. So your javascript will still need to start a user object and use it to check permissions for what javascript attempts.

But all this has little to do with GET or POST.

You cannot avoid it if you want your application to be secure. End of story.

Not directly though HTTP…that is not possible unless you are using your own protocol. AJAX is though HTTP hence the name XMLHttpRequest.

I can’t believe there is no other way to deal with this than adding programmatic permissions. That really isn’t an option for me. I rather dump this whole idea all together than add permissions like that, as my data access methods are pretty generic. It would be almost impossible to just account for all possible actions.

Well, I need to be 99.9% bullet proof considering it will expose the applications entire data access layer to the public, if it is not. Obfuscation could be added as an additional measure, but by itself its pretty weak.

Is there anyway to perhaps not allow access to the script/endpoint (dao.php) using htaccess rules? I’m not sure if its possible to write a rule to essentially say if not an AJAX or internal(?) request don’t allow. I don’t think its possible, but worth asking.

no, yes, maybe who knows? The initial idea was to make this generic, but if I can’t find a away to secure it than I’m probably just going to scrap it or only use it for specific circumstances. For example, in some case I may be using a list method for non-authenticated users. many times there is data that is returned that I rather not make available to someone directly hitting the endpoint. Although, not critical to security it would just be nice to make sure no one can access the functionality directly through HTTP. Though, I’m thinking this is less and less likely.

Are the users who have access to this AJAX application authenticated through PHP?