SitePoint Sponsor

User Tag List

Results 1 to 13 of 13
  1. #1
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2006
    Location
    Augusta, Georgia, United States
    Posts
    4,139
    Mentioned
    16 Post(s)
    Tagged
    3 Thread(s)

    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.

    Code JAVASCRIPT:
    $.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:

    Code JAVASCRIPT:
    $.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.N...e/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

  2. #2
    . shoooo... silver trophy logic_earth's Avatar
    Join Date
    Oct 2005
    Location
    CA
    Posts
    9,013
    Mentioned
    8 Post(s)
    Tagged
    0 Thread(s)
    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.
    Logic without the fatal effects.
    All code snippets are licensed under WTFPL.


  3. #3
    SitePoint Zealot
    Join Date
    Apr 2010
    Posts
    106
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    How about an API key? Just don't generate any other keys except for internal use.

  4. #4
    I solve practical problems. bronze trophy
    Michael Morris's Avatar
    Join Date
    Jan 2008
    Location
    Knoxville TN
    Posts
    2,023
    Mentioned
    62 Post(s)
    Tagged
    0 Thread(s)
    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.

  5. #5
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2006
    Location
    Augusta, Georgia, United States
    Posts
    4,139
    Mentioned
    16 Post(s)
    Tagged
    3 Thread(s)
    Quote Originally Posted by proxi
    How about an API key? Just don't generate any other keys except for internal use.
    You have any examples of how that can be done without exposing the key to the user?

    Code JAVASCRIPT:
    		$.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?

    Quote Originally Posted by Michael Morris
    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.
    That is what I would like to avoid, adding a API per operation permission layer on top of the data access layer.

  6. #6
    SitePoint Zealot
    Join Date
    Apr 2010
    Posts
    106
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    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.

  7. #7
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2006
    Location
    Augusta, Georgia, United States
    Posts
    4,139
    Mentioned
    16 Post(s)
    Tagged
    3 Thread(s)
    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.

  8. #8
    I solve practical problems. bronze trophy
    Michael Morris's Avatar
    Join Date
    Jan 2008
    Location
    Knoxville TN
    Posts
    2,023
    Mentioned
    62 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by oddz View Post
    That is what I would like to avoid, adding a API per operation permission layer on top of the data access layer.
    You cannot avoid it if you want your application to be secure. End of story.

  9. #9
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2006
    Location
    Augusta, Georgia, United States
    Posts
    4,139
    Mentioned
    16 Post(s)
    Tagged
    3 Thread(s)
    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.

  10. #10
    SitePoint Wizard wonshikee's Avatar
    Join Date
    Jan 2007
    Posts
    1,223
    Mentioned
    3 Post(s)
    Tagged
    0 Thread(s)
    Are the users who have access to this AJAX application authenticated through PHP?

  11. #11
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2006
    Location
    Augusta, Georgia, United States
    Posts
    4,139
    Mentioned
    16 Post(s)
    Tagged
    3 Thread(s)
    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.

  12. #12
    . shoooo... silver trophy logic_earth's Avatar
    Join Date
    Oct 2005
    Location
    CA
    Posts
    9,013
    Mentioned
    8 Post(s)
    Tagged
    0 Thread(s)
    Not directly though HTTP...that is not possible unless you are using your own protocol. AJAX is though HTTP hence the name XMLHttpRequest.
    Logic without the fatal effects.
    All code snippets are licensed under WTFPL.


  13. #13
    I solve practical problems. bronze trophy
    Michael Morris's Avatar
    Join Date
    Jan 2008
    Location
    Knoxville TN
    Posts
    2,023
    Mentioned
    62 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by oddz View Post
    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.
    You could try long polling, but that's rather tricky. You'd still need to authenticate at the start of the polling request though.

    http://en.wikipedia.org/wiki/Push_technology

    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.

    http://en.wikipedia.org/wiki/WebSockets

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


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •