The question
I have a service that pushes content to users. To provide this content to their users, customers will include a script on their site. Their script sends a token to my server to identify which customer it is, but here’s the problem: if anyone copies the script from the user’s site, they can receive this live content, and the customer is billed for users that are not on their site. So, is there a way to ensure that the script is only included on their website? How does google analytics achieve this?
I have an idea, but I don’t know if this would be completely secure.
- The customer tells me any domains (including subdomains) that they would like to include my script on.
- I give the user a very small text file that they store on their servers.
- Once my script is loaded, it checks for window.location.host, and tries to fetch the text file from the root of the hosting domain.
- If the file is found, and the contents match the content I generated when I gave the customer the file, I activate the service.
would this work?
Why I can not use window.location
Let’s say that my script reads window.location, and sends that to the url mydomain.com?token=ABC&locationhost=goodcustomer.com
Now, the owner of baduser.com wants to abuse the account of gooduser.com, so he includes gooduser.com’s script. The script now sends an ajax request to mydomain.com?token=ABC&locationhost=badcustomer.com
This would not start the service, because badservice.com is not the domain that the owner of goodcustomer.com entered when he signed up. This is easy to circumvent, because badcustomer.com’s owner can take a look at my script, notice that it is sending a request to validate the url, and just send his own request. So he would send a request to mydomain.com?token=ABC&locationhost=goodcustomer.com. My server sees this request, compares the locationhost to the domain associated with the token, and starts giving the content meant for goodcustomer.com’s users, to badcustomer.com’s users. My server has no way of knowing wether the request was sent by my own script, or by a user trying to impersonate the actual customer.
You cannot make a secure solution to this only with scripts that runs in the end users browser. Someone that want to mimic your customers web site will always be able to do that by creating a copy of every script or file that you send to the browser. You will need to do something on your customers server. That is, your customer must have some kind of secret that is not sent to the browser.
One way to do this would be to give the customer a server side script that generates a one-time token. Let your script call this server-side script to get the token and include this token in the request to your server. Your server must check that the token is correct before it generates the data.
A one time token can be made by sending each customer a 20 character long password. Let the server-side script read the password, add the date and time and hash this value using i.e. SHA-256. It would be quite hard to create a false token if you don’t know the password. It would be even better if you add a counter in the server side script. Let the counter increment with one for each request. However, a counter will introduce some syncronization problems if the counter on your site comes out of sync with the counter on the customers site.