9

I am researching ways to secure a javascript application I am working on. The application is a chat client which uses APE (Ajax Push Engine) as the backend.

Currently, anyone can access the page and make a GET/POST request to the APE server. I only want to serve the chat client to registered users, and I want to make sure only their requests will be accepted. I can use username/password authentication with PHP to serve a user the page. But once they have the page, what's to stop them from modifying the javascript or letting it fall into the wrong hands?

This method for securing a client/server application looks promising: http://abhinavsingh.com/blog/2009/12/how-to-add-content-verification-using-hmac-in-php/

I have another source that says this is ideal for a javascript client since it doesn't depend on sending the private key. But how can this be? According to to the tutorial above, the client needs to provide the private key. This doesn't seem very safe since anyone who has the javascript now has that user's private key. From what I understand it would work something like this:

  1. User logs in with a username and password
  2. PHP validates the username and password, looks up the user's private key and inserts it into the javascript
  3. Javascript supplies a signature (using the private key), and the public key with all APE requests
  4. APE compares the computed signature to the received signature and decides whether to handle the requests.

How is this secure if the javascript application needs to be aware of the private key?

Thanks for the help!

Walderman
  • 132
  • 3
  • 5
  • 1
    Hi Walderman, Saw referer to the post from here so let me take this chance to explain working explained in the blog post. The method explained is more of a flow validation method i.e. if you want to make sure that called ajax/javascript/api was really intended via your application control flow. If the crumb info is missing on server side or is invalid (due to timeout or corruption) you simply ignore the call.... Hope it clears the working. Method explained doesn't ask you to send any private key on the client side.. – Abhinav Singh Feb 02 '11 at 22:20

3 Answers3

2

The answer: You technically cannot prevent the user from modifying the JavaScript. So don't worry about that because you can do nothing about it.

However, the attack you do need to prevent is Cross-Site Request Forgery (CSRF). Malicious scripts on different domains are capable of automatically submitting forms to your domain with the cookies stored by the browser. To deal with that, you need to include an authentication token (which should be sufficiently random, not related to the username or password, and sent in the HTML page in which the chat client resides) in the actual data sent by the AJAX request (which is not automatically filled in by the browser).

PleaseStand
  • 31,641
  • 6
  • 68
  • 95
  • So is this similar to what something like OAuth does, where the server authenticates and then provides an access token to the client for x amount of time? – Walderman Nov 23 '10 at 13:50
  • @Walderman: It doesn't have to be as complex as OAuth. All I'm talking about is putting the authorization token (such as one that is used in a cookie) in either the HTML page or the server's first AJAX response and having the server check all subsequent responses, ensuring that the token is sent (using a method *other* than cookies). – PleaseStand Nov 23 '10 at 21:45
1

How is this secure if the javascript application needs to be aware of the private key?

Why not? It's the user's own private key, so if he is willing to give it out to someone else, it's his problem. It's no different from giving out your password and then saying someone else has access to your account.

If you think about this a bit, you'll realize that you don't need to implement public-key encryption, HMAC or anything like that. Your normal session-based authentication will do, provided the communication channel itself is secure (say using HTTPS).

casablanca
  • 69,683
  • 7
  • 133
  • 150
  • Even if the APE server which receives the ajax requests is secured by HTTPS, any person can still hit https://0.ape.mydomain.com and send data. Currently, they wouldn't even need to be authenticated to do it. The APE server is not aware of PHP sessions, so it would need some other way to verify the client's identity. – Walderman Nov 23 '10 at 03:36
  • @Walderman: In that case, have PHP send a randomly generated temporary key to the client and have the client send this with each request to the APE. You'll need to store this key in a database so that both PHP and the APE have access to it. – casablanca Nov 23 '10 at 03:46
0

HMAC authentication is better served for an API that third parties are going to connect to. It seems like your app would be better served by writing a cookie to the client's browser indicating that they've been authenticated. Then with each ajax request you can check for that cookie.

Edit: I take back a bit of what I said about HMAC being better served for third party APIs. Traditionally with HMAC each user gets their own private key. I don't think this is necessary for your application. You can probably get away with just keeping one master private key and give each user a unique "public" key (I call it a public key, but in actuality the user would never know about the key). When a user logs in I would write two cookies. One which is the combination of the user's public key + time stamp encrypted and another key stating what the time stamp is. Then on the server side you can validate the encrypted key and check that the time stamp is within a given threshold (say 10-30 minutes in case they're sitting around idle on your app). If they're validated, update the encrypted key and time stamp, rinse and repeat.

roto
  • 677
  • 6
  • 11
  • 1
    Thank you. Maybe I'm missing something, but what's to stop an unwanted user from discovering this cookie, and then using it to send requests? – Walderman Nov 23 '10 at 02:58
  • A person could possibly see the cookie, but they would not be able to write that same cookie to your domain unless they are on your domain. If you are concerned about it you can use HMAC and write the combination of the public key and a time stamp encrypted using the private key. This way the private key is never made public either via javascript or the cookies. – roto Nov 23 '10 at 03:18
  • It seems like the consensus here is that I should set some kind of cookie/token/key and send it with each ajax request. Is there a case for using a cookie versus just including the value in the query string? It seems like using a cookie might be more obscure, but if the client disables cookies then my application wouldn't work. – Walderman Nov 23 '10 at 13:57
  • If you include it in a query string you run into the same problem that anyone could see that variable and push a post or get request to your server. It's much more difficult to write a cookie on your domain with those values. But in the end it comes down to security vs usability and understanding your client base to know if they would be willing to have cookies turned on. In my web development experience I haven't run into too many issues from clients having cookies disabled on their browser. – roto Nov 23 '10 at 14:06
  • 1
    As I understand it, cookies have the same problem, only you need to be slightly more determined. Couldn't anyone with the right tools read all of a browser's cookies and then create an http request with the appropriate headers? Granted, the attacker would need to be able to see the cookies (i.e. by sharing a computer with a legitimate client) – Walderman Nov 23 '10 at 14:39
  • Nothing is going to be totally secure and that's something we have to live with but cookies will provide more security over including a value in javascript. The important thing will be making sure your security key has a time stamp included (and encrypted on it) to prevent replay attacks. – roto Nov 23 '10 at 15:04