Why is cross-domain JSONP safe, but cross-domainJSON not? - jsonp

I'm having trouble connecting some dots having recently learned of JSONP. Here's my understanding:
Cross-domain XmlHttpRequests for any content (including JSON) is banned, due to the same origin policy. This protects against XSRF.
You are permitted to have a script tag with a src that returns JSONP - some JSON padded inside a call to a Javascript function (say 'Foo')
You can have some implementation of 'foo' on the page that will get called when the JSONP data is returned, and you can do things with the JSON data that function is passed
Why is it OK to receive cross-domain data if it came via JSONP, but not if it came via JSON?
Is there an assumption that JSON is prone to permitting XSRF but JSONP is not? If so, is there any reason for that other than JSONP being some de-facto data format that won't ever provide data that enables XSRF? Why JSONP and not some arbitrary root tag on XML instead?
Thank you in advance for your answers, please make my brain work again after failing to figure this one out.

I understand this question to be about why the browser considers JSONP safe, not about whether it is safe (which it isn't). I will address this question step by step.
Regular ol' AJAX
To perform a regular AJAX request, the browser creates an XHR object, points it at the URL and pulls the data. The XHR object will only trust data from the same domain. This is a hard limitation. There is no getting round it in current browsers (edit - you can now use CORS).
Solution - Don't use XHR
Since XHR is subject to the same domain poilicy, we can't use XHR to do cross domain AJAX. Luckily, there are other ways to hit a remote server. We could append an image tag to the page for example. We can also append a script tag and give it a src attribute that points to the remote server. We can pull JQuery from a CDN for example and expect it to work.
How JSONP works.
When we make a JSONP request, our code dynamically appends a script tag to the page. The script tag has a source attribute which points to the remote JSONP API url, just as though you were inserting a script from a CDN.
The JSONP script returned by the server is wrapped in a function call. When the script is downloaded, the function will be executed automatically.
This is why we have to tell the JSONP the name of the callback function we want to wrap the script in. That function will be called once the script has downloaded.
Security concerns
There are some fairly big security concerns here. The script you are downloading could take control over your page and put your users at risk. JSONP is not safe for your users, it is just not blocked by the web browsers. JSONP really is a browser exploit which we are taking advantage of. Use with caution.
Used wisely, JSONP is pretty awesome though.

I don't know how the perception that JSONP is safe came up but see
JSON-P is, for that reason, seen by many as an unsafe and hacky
approach to cross-domain Ajax, and for good reason. Authors must be
diligent to only make such calls to remote web services that they
either control or implicitly trust, so as not to subject their users
to harm.
and
The most critical piece of this proposal is that browser vendors must
begin to enforce this rule for script tags that are receiving JSON-P
content, and throw errors (or at least stop processing) on any
non-conforming JSON-P content.
both quotes from http://json-p.org/ .
other links with some useful information about JSONP/security:
http://beebole.com/en/blog/general/sandbox-your-cross-domain-jsonp-to-improve-mashup-security/
Cross Domain Limitations With Ajax - JSON
JSONP Implications with true REST
all these tell 2 things - basically it is not considered "safe" but there are ideas on how to make it "safer"... though most ideas rely on standardization AND specific check logic to be built into browsers etc.

Related

Wordpress widget with xml asynchronous integration

I have a task to do where I need to make calls to an external xml api to fetch data for an event calendar in the sidebar of a site. The date will be changed with JavaScript and then i need to make another call to refresh the data. Can somebody give me an idea about how to cleanly set up an action or function somewhere that I can direct an Ajax action to? It's easy to set up a widget with the correct HTML etc but where does the Ajax connect to? Ideally when the content initially loads on the page it would use the same function that the post is going to use to generate the HTML on the server side.
Any tips would be appreciated. This is an xml api...no option for json or jsonp so credentials including a token and user I'm assuming will have to go somewhere in my widget, something like a proxy function?
It sounds as if you're asking about making cross-domain AJAX requests, AKA the "same origin policy."
The same origin policy prevents document or script loaded from one origin from getting or setting properties of a document from a different origin (domain). See http://www.mozilla.org/projects/security/components/same-origin.html for a more detailed description of the policy.
See Ways to circumvent the same-origin policy for a good description of the options available to circumvent this limitation.
The short answer is that unless you have control over the domain to which you're making AJAX requests, your best bet is probably to set up a simple proxy that lives in the same domain where your AJAX is running, which will forward requests to the destination. Doing a google search on "simple AJAX proxy" will get you a host of results, including pre-built proxies in a variety of languages.

Why is CORS based on the target server? Why do I have to use JSONP?

I would like a concrete example in an answer if possible.
For explanations sake we have three players here.
My Server (myserver.com)
Client Server (myclient.com)
Client User (accessing data through myclient.com)
I'm making a web service available to my clients that allows them to retrieve their data in JSON format. In order for their websites to work they have to use the standard XOR workarounds - either making the request server-side or relying on me to set
Access-Control-Allow-Origin: http://myclient.com
So two part question here. First, why do I set the origin policy at myserver.com? Why does my server care who it serves content up to? Shouldn't it be myclient.com that sets this? Concrete example here would be great.
Part two, I understand that JSONP works around this, but I'm worried about using it because I don't understand the security implications from part one. What is the point of JSONP if I can just set Access-Control-Allow-Origin: *?
Lots of questions!
JSONP is definitely dangerous if you intend to serve user-specific content. If the content the server is serving is completely public, and (probably) read-only, JSONP is a wise choice. Don't use it for anything that assumes a 'logged in state' or authentication/authorization.
CORS is definitely much better than JSONP, but it's not supported in every (older) browser. If you want to support as much as possible, you will need some kind of fallback. CORS allows you to do requests other than GET, which greatly improves flexibility.
The reason the target server needs to allow this, is mainly because javascript running on domain A, should not be able to access domain B. If domain A could 'allow' this, it implies you could create javascript applications that have access to the sandbox of any public server. Only the owner of domain B can explicitly allow the owner of domain A to access their content.
Your argument (why does domain B care who accesses their resources) would normally be valid. But this is not to protect domain B, it is to protect the end-user. Domain A should not be allowed to perform requests on behalf of the end-user to Domain B without explicit permission.
And just to be sure: unless you understand the security implications of JSONP quite well, CORS is likely a much safer choice.

How to use regular urls without the hash symbol in spine.js?

I'm trying to achieve urls in the form of http://localhost:9294/users instead of http://localhost:9294/#/users
This seems possible according to the documentation but I haven't been able to get this working for "bookmarkable" urls.
To clarify, browsing directly to http://localhost:9294/users gives a 404 "Not found: /users"
You can turn on HTML5 History support in Spine like this:
Spine.Route.setup(history: true)
By passing the history: true argument to Spine.Route.setup() that will enable the fancy URLs without hash.
The documentation for this is actually buried a bit, but it's here (second to last section): http://spinejs.com/docs/routing
EDIT:
In order to have urls that can be navigated to directly, you will have to do this "server" side. For example, with Rails, you would have to build a way to take the parameter of the url (in this case "/users"), and pass it to Spine accordingly. Here is an excerpt from the Spine docs:
However, there are some things you need to be aware of when using the
History API. Firstly, every URL you send to navigate() needs to have a
real HTML representation. Although the browser won't request the new
URL at that point, it will be requested if the page is subsequently
reloaded. In other words you can't make up arbitrary URLs, like you
can with hash fragments; every URL passed to the API needs to exist.
One way of implementing this is with server side support.
When browsers request a URL (expecting a HTML response) you first make
sure on server-side that the endpoint exists and is valid. Then you
can just serve up the main application, which will read the URL,
invoking the appropriate routes. For example, let's say your user
navigates to http://example.com/users/1. On the server-side, you check
that the URL /users/1 is valid, and that the User record with an ID of
1 exists. Then you can go ahead and just serve up the JavaScript
application.
The caveat to this approach is that it doesn't give search engine
crawlers any real content. If you want your application to be
crawl-able, you'll have to detect crawler bot requests, and serve them
a 'parallel universe of content'. That is beyond the scope of this
documentation though.
It's definitely a good bit of effort to get this working properly, but it CAN be done. It's not possible to give you a specific answer without knowing the stack you're working with.
I used the following rewrites as explained in this article.
http://www.josscrowcroft.com/2012/code/htaccess-for-html5-history-pushstate-url-routing/

What is the best way to upload files to another domain from a browser? [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I am creating a web service of scheduled posts to some social network.Need help dealing with file uploads under high traffic.
Process overview:
User uploads files to SomeServer (not mine).
SomeServer then responds with a JSON string.
My web app should store that JSON response.
Option 1: Save, cURL POST, delete tmp
The stupid way I made it work:
User uploads files to MyWebApp;
MyWebApp cURL's the file further to SomeServer, getting the response.
Option 2: JS magic
The smart way it could be perfect:
User uploads the file directly to SomeServer, from within an iFrame;
MyWebApp gets the response through JavaScript.
But this is(?) impossible due to the 'Same Origin Policy', isn't it?
Option 3: nginx proxying?
The better way for a production server:
User uploads files to MyWebApp;
nginx intercepts the file uploads and sends them directly to the SomeServer;
JSON response is also intercepted by nginx and processed by MyWebApp.
Does this make any sense, and what would be the nginx config for, say, /fileupload Location to proxy it to SomeServer?
I don't have a server to use to stand in for SomeServer for me to test out my suggestions, but I'll give it a shot anyway. If I'm wrong, then I guess you'll just have to use Flash (sample code from VK).
How about using an iFrame to upload the file to SomeServer, receive the JSON response, and then use postMessage to pass the JSON response from the iFrame to your main window from your site. As I understand it, that is pretty much the motivation for creating postMessage in the first place.
Overall, I'm thinking of something like this or YUI's io() module but with postMessage added to get around the same origin policy.
Or in VK's case, using their explicit iFrame support. It looks to me like you can add a method to the global VK object and then call that method from the VK origin domain using VK.callMethod(). You can use that workaround to create a function that can read the response from the hidden iFrame.
So you use VK.api('photos.getUploadServer', ...) to get the POST URL.
Then you use JS to insert that URL as the action for your FORM that you use to upload the file. Follow the example under "Uploading Files in an HTML Form" in the io() docs and in the complete function, use postMessage to post the JSON back to your parent window. See example and docs here. (If it doesn't work with io(), you can certainly make it work using the roll-your-own example code if I'm right about VK.callMethod().)
Then in response to the postMessage you can use regular AJAX to upload the JSON response back to your server.
I can see only two major approaches to this problem: server-side proxying and javascript/client-side cross-site uploading. Your approaches 1 and 3 are the same thing. It shouldn't really matter whether you POST files with means of cURL or nginx - not performance-wise anyway. So if you already implemented approach 1 from your question, I don't see any reason to switch to 3.
In regards to javascript and Same Origin Policy, it seems there are many ways to achieve your goal, but in all of these ways, either your scenario must be supported by SomeServer's developers, or you have to have some sort of access to SomeServer. Here's an approximate list of possibilities:
CORS—your domain must be allowed to access SomeServer's domain;
Changing document.domain—this requires that your page and target page are hosted on subdomains of the same domain;
Using a flash uploader (e.g. SWFUpload)—it is still required that your domain is allowed via the cross-domain policy, in case of Flash, via a crossdomain.xml in the root of SomeServer's domain;
xdcomm (e.g. EasyXDM)—requires that you can upload at least an html page to the target domain. This page can then be used as a javascript proxy for your manipulations with SomeServer's iframe.
The last one could, actually, be a real possibility for you, since you can upload files to SomeServer. But of course, it depends on how it's implemented—for example, in case there is another domain the files are served from, or if there are some security measures which won't allow you to host html files, it may not work out.

Do REST API URLs have to look like this?

Is it true that to implement a RESTful API, one has to implement a URL structure that looks like this
http://example.com/post/
http://example.com/post/123
where the /123 would be used for edit, delete
Another way to ask the question is: can a URL that looks like this be called RESTful?
http://example.com/script.php?method=get_title&blogid=123
You don't have to design your URI structure like that. It could also be /some_obscure_string/base64_encoded_title/unique_id. This could also be RESTful, depending on several other factors.
But there are several best practices on how to design URIs in a RESTful web application and being as simple and as human readable as possible is one of them.
Your example http://example.com/script.php?method=get_title&blogid=123 could also be RESTful, but the query parameters indicate that some kind of RPC- or RMI-over-HTTP is used instead.
To sum it up: Don't put too much thought into your URI design. This will come automatically with a good and proper RESTful design of your application.
The Idea behind REST is that every resource has it’s own URL and you use the different HTTP methods to interact with those resources. It makes sense to define the URL structure so that the hierarchy between different resources is reflected in the URL, but you don’t have to.
If you have URLs like this
/all-posts/
/first-post
/some-stuff/second-post
/third-post
you still could provide an RESTful API to this. The Idea is that a GET to /all-posts/ returns a list of the URLs of every post object and the client uses those URLs to interact with the resources. Basically the URLs should be treated as opaque data by the client.
As long as the URL that is embedded in the client doesn’t change you also could change the structure without having to change the client.
Your example URL probably doesn’t belong to a RESTful API, since it contains a method get_title. In REST a URL represents a thing. What is to be done with the thing (should it be modified, should it contents be retrieved, ...) is not part of the URL, for that REST uses the different HTTP methods.
A key aspect of REST is that the url is the resource. a uri like
http://example.com/script.php?etc-etc-etc
doesn't put the resource identifier in the resource portion of the uri. that's not to say that a RESTful API shouldn't ever use get parameters; in fact, that's just fine:
http://example.com/posts?sort=date_asc&offset=20&limit=10
might be a great way to get the URI's of the 3rd page of oldest posts. However, using get parameters in this way should only be used in requests where the method is also GET. PUT and especially POST methods should really use simple uri's with the resource that will be affected in only the path portion.
RESTful URI design is all about resources access and they should be structured in the RESTful manner, so you should not have any query strings.
e.g. of GET
authors/
authors/1
authors/1/books
authors/1/books/10
authors/1/books/10/summary
etc.
Anything and everything is called RESTfull these days, just look at some of the responses by it's inventor Dr Roy Fielding and you'll get some ideas. It is worth doing some reading on the subject.
P.S you do not need post,get etc in your URIs, HTTP protocol is at present mostly used for consuming REST APIs and you can pass verb as a part of the call. Also there is a concept of content negotiation i.e you can request any available format from REST API (json,xml atc).
The REST concept is really based on the fact that it is URL driven, and not driven by large data-blobs. With REST, you don't have to pass a giant soap request to invoke a method - your method call/object creation/whatever you want to do is invoked simply by the URL, and the verb you used vs that URL.
Example URLs:
GET http://del.icio.us/api/
GET http://del.icio.us/api/peej/tags/
GET http://del.icio.us/api/peej/tags/test
DELETE http://del.icio.us/api/peej/bookmarks/[hash]
The structure of your URLs doesn't matter. What does matter is that each URL identifies exactly 1 resource. Each resource can have multiple URLs that point to it but each URL should only point to 1 resource.
This can be helpful. Ref:
RESTful service URLs