I'm trying to find if there's a good way to prevent CSRF on a javascript widget embedded on customers' websites.
The widget would enable end users to make requests against our customers' accounts via JSONP to a a PHP server which proxies those requests to our (non-public) API.
To this point, I haven't come up with a surefire way to ensure all requests are coming from only our customers' websites. Some ideas I've had:
- Tokens generated on the server side and passed back along with each subsequent JSONP request (not sure how to authenticate the initial request though, since the first token would be readable in JS and anyone could request the 'next' token)
- Checking the Referer header (unreliable, can be spoofed or simply not passed by the browser)
- Using SSL (would of course help but not solve the problem of CSRF)
Is this at all possible? I've come across Fotomoto's widget which seems to allow the same type of functionality we are looking for, but am not sure how they're doing it.
You will never find a solution that ensures that requests that come from random third parties (users) are in fact initiated by accessing your customers' website. If your security relies on that, then you have to remove that assumption. (If you really mean "ensure that requests are coming from only our customers' websites" servers then this is trivial: SSL with client-side certificates. But I assume you mean "coming from random user machines with the intent to use our customers' websites.")
What you should be looking for how to prevent users from being tricked (CSRF). So for instance, the fact that Referer can be spoofed is irrelevant for this problem. The only question is whether there is a browser that has a flaw that would allow a third party to trick a user into creating a spoofed Referer. So you should check Referer as necessary but not sufficient. That is to say, if Referer is wrong, hang up on the caller. But the fact that Referer is right does not mean you're actually receiving a legitimate request. Most CSRF I believe is due to failure to check Referer, not browser bugs.
The Wikipedia article on CSRF has a decent summary of the obvious prevention techniques. Just checking Referer is a big first step.
By definition this is a "Cross Site Request". It is important to note that whether or not a CSRF request is a vulnerability is highly dependent on what the request does. For instance if the attacker can force the client into making a search request then this probably doesn't do anything useful to the attacker. If the attacker can change the admin's password, then you have a very serious problem.
So without knowing what these requests do, its impossible to say how it should be protected. That being said I think that reCapthca is a good example of how asymmetric cryptography can be used to ensure that the server authorizes a client's translation with a 3rd party. But without more information I have no idea how this could help you.