Are there any security issues that should be considered when using JSONP?
Yes, you need to be careful, but when used properly with trusted services it's relatively safe.
Here's a summary of the security issues with JSONP, as I understand it:
From the consumer's perspective:
From the provider's perspective:
Update: JSONP is a common hack to do cross-domain requests. Modern browsers now have Cross Origin Resource Sharing, and IE8+ have XDomainRequest which is similar. See http://enable-cors.org/ for more info.
JSONP is just a script include that allows you to use a callback. You should however be aware of Cross-site request forgery (CSRF).
As long as you control the script and the server, JSONP isn't anymore insecure than a script include. Unless you have a JSONP-service that returns sensitive data to logged in users. A malicious site can send a request to the service (hoping that the user is logged in on your site), and retreive the data. The service can check the referrer of the request, but it is possible to spoof the referrer using flash (thanks Chris Moschini).
Imagine this senario: - A user logs into his internet banking account. Storing a session cookie in the users browser. This site has a jsonp service with sensitive info about the user and his accounts. - Other sites won't know that the user is logged in, but they could do a wild guess and try to access the jsonp service. Since the user has a session cookie, the browser will get a response, and there's nothing stopping the site from doing an ajax post to save the sensitive data on their server.
Update June 28th 2012: If you want to protect against CSRF attacks you should read this in depth blog post by a security expert: http://erlend.oftedal.no/blog/?blogid=130
There are security issues for both sides. The most serious one is for the site including JSONP.
If you are including a from another domain (which you do not control), that domain can change up the script at any time. They can make the javascript do anything in the context of your webpage, that your own javascript could do. There is no way around this if you use JSONP. You should look into cross-domain communication using iframes, which is best done by the excellent EasyDXM library.
If you are offering a webservice that handles JSONP, you have to protect from Cross-Site Request Forgery (CSRF). This is where your webservice returns sensitive information to logged-in users. If a user has logged into your site, any other site can generate a GET request to the JSONP service, and YOUR domain's cookies are submitted with the request -- in essence, authenticating the logged-in user -- except that now, the remote domain gets the response and is able to read the sensitive data!
The best way to protect against CSRF is to generate a nonce (a hard-to-guess, randomly generated number) and store it in the session. Output this nonce in all your forms on YOUR webpages, and include it in all JSONP requests on YOUR pages. On the server, make sure that the nonce is present and correct in the request (whether it be a GET, POST, etc.) Other domains will be unable to guess this nonce, and thus unable to get the sensitive information, despite the cookies being sent.
Finally, there is another sort of security issue: JSONP simply does not support user authentication in the browser, of the kind that is possible with OAuth. You can, of course, have the server get some kind of access token (like with OAuth) and use that. However, if you want to do authentication entirely in the browser, you have to use cross-domain communication with iFrames. I think this is how OAuth 2.0 does it. Here's how you set it up: pages hosted on your site have full access to your server. Have a javascript library which loads EasyDXM and uses it to set up a hidden iframe to your site, and talk to it using that.
JSONP is definitely not safe, as it's simply running whatever it gets cross-domain as JavaScript.
solution! solution!
Create an iframe, preferably a sandboxed one, and load JSONP there. Catch the result and pass it up via window.postMessage
And yes, somebody got this idea first, as usual :)
The blog post is no longer there, but I'm keeping the link here for credit:
http://beebole.com/blog/general/sandbox-your-cross-domain-jsonp-to-improve-mashup-security/
edit: wayback machine link
It used the window.name hack for iframe communication, but that was for IE6 and 7.