Secure Access to Authenticated REST Server through Backbone.js?

11,758

Solution 1

Okay I had a discussion with my colleague and came up with the best idea so far:

Make a simple controller in your Client Side (site) and name it as RESTAPI, it will just act as a wrapper to your actual REST Server.

When a user logs into your site, his session get's created. The RESTAPI controller knows credentials to your HTTP Authed actual REST server and it hits REST Server on backbone's behalf.

Example: If I have to fetch

/messages/sent

from REST Server, now instead i'll hit this url in backbone collection

site/restapi/messages/sent

The RESTAPI Controller also first checks that the requesting user has a proper session on the site and weather he is allowed to fetch the resource or not.

So no worries about insecure cookies or leaving your REST Server pass in plain JS or using any other obscure method :)

Solution 2

HTTP Basic authentication is prone to eavesdropping and man-in-the-middle attacks. It's recommended to use HTTPS.

However, if that's not an option you can always send a cookie back to the client and have the username/password entered there to prevent it from being displayed in the JS file. Goes without saying that the password should at least be encrypted/hashed for security reasons. Then, the onus will be on the server side to get the authentication details from the cookie.

Now, if you don't have any control on modifying the server side code, you are pretty much left with no option other than burying the credential details in a global ajaxSend() method that will send the username/password details with every AJAX request. You could just put this in some other .js file and make it hard to find, but you are pretty much restricted to that form of security. Although, cookies don't make your life any safer. (It'd be good if the password is hashed/encrypted).

The other thing you could do is to have a slightly more complicated form of security: Have the server send a nonce back with every response - the nonce would be 'signed' by the server using the server's secret key and you can use that to 'encrypt' the username/password on the client side for every request. Your server would then have to constantly decrypt the credentials. This is less prone to man-in-the-middle but still not foolproof.

HTTPS would save you from each of the above if it's an option for you.

Hope this helps.

UPDATE (as per comment): The essence of restful-ness is the absence of state on the server. I.e., no sessions! Hence you need to send the user credentials with EVERY request the client makes of the server. If you have a login page then it's very hard to be truly restful since there is no 'resource' called login. However, here's what you can do:

  1. User visits login page, enters credentials and clicks 'login'
  2. Send POST request to server with these credentials - probably to /Login
  3. Have the server return the requested resource for which authentication was needed AND set the cookie with the valid credentials to use in the 'next' request
  4. Every subsequent request will be directed to the corresponding resource at a particular URL with a particular action (GET, PUT, POST, DELETE...). The server should check the authentication data from the cookie and decide if the user is authenticated and perform further authorization to grant access if the need be.

Every request must identify itself without having the server maintain the session - that's the spirit of statelessness (and restful-ness ;)

Share:
11,758
DivinesLight
Author by

DivinesLight

Traversing digital plane as real life is full of deceit.

Updated on June 15, 2022

Comments

  • DivinesLight
    DivinesLight almost 2 years

    I've had this REST Server (written by myself) that is secured by simple HTTP Authentication.

    Now I re-wrote the app using backbone.js and I am unsure how to go about authenticating my client. If i do it in JS user/pass would be visible.

    So how should I modify my server or my client side JS to be secure?

    Previously I just gave user & pass in PHP for each request to REST Server, please guide me, Thanks.

  • DivinesLight
    DivinesLight over 12 years
    Thanks for in-depth overview and it surely helps. But, sorry I forgot to mention (edited question now) that I have full access to server and I can change it so that my setup is fool proof. Any suggestions on that? You can write another answer or edit this if you wish to.
  • PhD
    PhD over 12 years
    @BlackDivine - the same steps hold :) I have shown 3 ways of doing it - only client (ajaxSend), only server (cookie) and hybrid (constant encrypt/decrypt using server nonce)
  • DivinesLight
    DivinesLight over 12 years
    I like Cookies option most for the time being, Can you please confirm this apporach is better? That we create sessions on server, whenever a user successfully logs in, the session is created on the rest server and as long as the session is alive the user can use the REST API. Now will sending the login POST through ajax will create session for the user on the server or my website? Because I have 2 servers, 1 is REST the other hosts website which runs backbone app. Many Thanks!
  • DivinesLight
    DivinesLight about 12 years
    Can you please read my answer below @Nupul? and give me your feedback?
  • thenetimp
    thenetimp over 11 years
    Doesn't that kind of break the whole RESTFULness of the server? I mean if you're going to go that route may as well just do session handling on the server. Don't get me wrong I am still in the dark about if I pass credentials everytime, storing them on the client to pass each time isn't necessarily the brightest idea.
  • Ben Thurley
    Ben Thurley over 11 years
    I had to lookup "nonce", the word has a very different meaning in the UK!
  • miguelcobain
    miguelcobain over 11 years
    There is nothing wrong about passing credentials in every request. In REST, every request should be self describable (in order to remove the need of sessions in the server). If a resource is protected, the credentials are a part of the request "description", and as such should be sent with it. You can just ask the user his credentials and pass them on every subsequent request. To OP, don't use sessions, please. You're destroying the REST beauty with it. You don't need sessions and by not using them you're keeping your system much more scalable.
  • MusikPolice
    MusikPolice about 11 years
    Can you provide an example of the backbone.js code that you wrote for this implementation? I'm having a problem getting it to work. You can see my progress in this question