Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<h1>Updated Answer</h1> <p>Addressing your questions (as opposed than going off on a bit of a tangent in my original answer :D), here's my opinions:</p> <p>1) My main opinion on this is that I dislike <code>d</code>. As a client consuming the API I would find it confusing. What does it even stand for anyway? data? </p> <p>The other options look good. <code>Columns</code> is nice because it mirrors back to the user what they requested.</p> <p>If you are doing pagination, then another option might be something like <code>page</code> or <code>slice</code> as it makes it clear to the client, that they are not receiving the entire contents of the collection.</p> <pre><code>{ "offset": 0, "limit": 100, "page" : [ ... ] } </code></pre> <p>2) TBH, I don't think it makes that much difference which way you go for this, however if it was me, I probably wouldn't bother sending back the envelope, as I don't think there is any need (see below) and why make the request structure any more complicated than it needs to be? </p> <p>I think POSTing back the envelope would be odd. POST should let you add items into the collection, so why would the client need to post the envelope to do this?</p> <p>PUTing the envelope back could make sense from a RESTful standpoint as it could be seen as updating metadata associated with the collection as a whole. I think it is worth thinking about the sort of meta data you will be exposing in the envelope. All the stuff I think would fit well in this envelope (like pagination, aggregations, search facets and similar meta data) is all read only, so it doesn't make sense for the client to send this back to the server. If you find yourself with a lot of data in the envelope that the client is able to mutate - then it could be a sign to break that data out into a separate resource with the list as a sub collection. Rubbish example:</p> <p><code>/animals</code></p> <pre><code>{ "farmName": "farm", "paging": {}, "animals": [ ... ] } </code></pre> <p>Could be broken up into:</p> <p><code>/farm/1</code></p> <pre><code>{ "id": 1, "farmName": "farm" } </code></pre> <p>and</p> <p><code>/farm/1/animals</code></p> <pre><code>{ "paging": {}, "animals": [ ... ] } </code></pre> <p>Note: Even with this split, you could still return both combined as a single response using something like <a href="https://developers.facebook.com/docs/reference/api/field_expansion/" rel="nofollow noreferrer">Facebook's</a> or <a href="http://developer.linkedin.com/documents/field-selectors" rel="nofollow noreferrer">LinkedIn's</a> field expansion syntax. E.g. <code>http://example.com/api/farm/1?field=animals.offset(0).limit(10)</code> </p> <p>In response, to your question about how the client should know what the JSON payload they are POSTing and PUTing should look like - this should be reflected in your API documentation. I'm not sure if there is a better tool for this, but <a href="http://swagger.wordnik.com/" rel="nofollow noreferrer">Swagger</a> provides a spec that allows you to document what your request bodies should look like using <a href="http://en.wikipedia.org/wiki/JSON#Schema" rel="nofollow noreferrer">JSON Schema</a> - check out <a href="https://github.com/wordnik/swagger-core/wiki/datatypes" rel="nofollow noreferrer">this page</a> for how to define your schemas and <a href="https://github.com/wordnik/swagger-core/wiki/parameters" rel="nofollow noreferrer">this page</a> for how to reference them as a parameter of type <code>body</code>. Unfortunately, Swagger doesn't visualise the request bodies in it's fancy web UI yet, but it's is open source, so you could always add something to do this. </p> <h1>Original Answer</h1> <p>Check out <a href="http://haacked.com/archive/2009/06/24/json-hijacking.aspx#84979" rel="nofollow noreferrer">William's</a> comment in the discussion thread on that page - he suggests a way to avoid the exploit altogether which means you can safely use a JSON array at the root of your response and then you need not worry about either of you questions.</p> <p>The exploit you link to relies on your API using a Cookie to authenticate a user's session - just use a query string parameter instead and you remove the exploit. It's probably worth doing this anyway since using Cookies for authentication on an API isn't very RESTful - some of your clients may not be web browsers and may not want to deal with cookies.</p> <h2>Why Does this fix work?</h2> <p>The exploit is a form of CSRF attack which relies on the attacker being able to add a <code>script</code> tag on his/her own page to a sensitive resource on your API. </p> <pre><code>&lt;script src="http://mysite.com/api/columns"&gt;&lt;/script&gt; </code></pre> <p>The victims web browser will send all Cookies stored under <code>mysite.com</code> to your server and to your servers this will look like a legitimate request - you will check the <code>session_id</code> cookie (or whatever your server-side framework calls the cookie) and see the user is authenticated. The request will look like this:</p> <pre><code>GET http://mysite.com/api/columns Cookie: session_id=123456789; </code></pre> <p>If you change your API you ignore Cookies and use a session_id query string parameter instead, the attacker will have no way of tricking the victims web browser into sending the session_id to your API.</p> <p>A valid request will now look like this:</p> <pre><code>GET http://mysite.com/api/columns?session_id=123456789 </code></pre> <p>If using a JavaScript client to make the above request, you could get the session_id from a cookie. An attacker using JavaScript from another domain will not be able to do this, as you cannot get cookies for other domains (<em><a href="https://stackoverflow.com/questions/8834436/how-to-get-cookies-from-a-different-domain-with-php-and-javascript#tab-top">see here</a></em>). </p> <p>Now we have fixed the issue and are ignoring session_id cookies, the script tag on the attackers website will still send a similar request with a GET line like this:</p> <pre><code>GET http://mysite.com/api/columns </code></pre> <p>But your server will respond with a <code>403 Forbidden</code> since the GET is missing the required session_id query string parameter. </p> <h1>What if I'm not authenticating users for this API?</h1> <p>If you are not authenticating users, then your data cannot be sensitive and anyone can call the URI. CSRF should be a non-issue since with no authentication, even if you prevent CSRF attacks, an attacker could just call your API server side to get your data and use it in anyway he/she wants. </p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload