Search code examples
javascripthttpsecurityauthenticationanalytics

How can I protect an HTTP POST request from only being received by an approved javascript client?


I have a URL that will accept POSTed data and store a record of it — this is for analytics. I need to secure that against anyone in the world from POSTing to it, but what possible authentication mechanism can I use that it is safe to expose the details of? I don't think the javascript can access any secret data without making it public.

I could base it off any HTTP header, but these can all be spoofed, right?

If it helps, both client and server are https.

Edit: I think I need to state the problem more explicitly; sorry, I thought I could explain it concisely, but it's clearly not coming across! Imagine the following:

  1. A static page at https://example.com/index.html includes a script, https://example.com/script.js.

  2. The script makes a request to another remote URL, e.g.

    ajax_call('https://stats.example.com/stats.php', 'some data');
    
  3. The stats.php script simply writes 'some data' to a file

Now, the flaw is that anyone can simply POST anything to stats.php and it will write to the file. I want to restrict that to just my 'client', i.e. https://example.com/index.html.

If I could, I would do something like this in stats.php:

if ($_SERVER["HTTP_REFERER"] == 'https://example.com') {
    do_stuff();
} else {
    die('not allowed');
}

but I've always been under the impression that HTTP_REFERER (and other similar headers) could just be spoofed, so that woud be pointless.


Solution

  • I need to secure that against anyone in the world from POSTing to it, but what possible authentication mechanism can I use that it is safe to expose the details of?

    If the endpoint needs to be accessed by the browser of everybody who visits a public website, then you can't.

    The browser is completely under the user's control. They can inspect everything the browser does. They can then recreate that using some other HTTP client.

    If you trust the browser enough to let it make the request to your analytics API then you must trust the owner of the browser too. It is impossible to separate them.


    The best you can do is analyse the data sent to the analytics API for usual or impossible patterns of behaviour.