title: Can jsonp be protected with a csrf token?
body: <p>Use case:
  In a same-domain situation, I want to use jsonp for data transport, simply because it happens earlier in the request than any ajax or iframe transport. Also, I want this data to be cached like a regular js file.</p>
  
  <p>I do not want to expose this data to other domains.</p>
  
  <p>So, I thought about the following tricks to prevent csrf:</p>
  
  <ol>
  <li>A csrf token sent as a GET parameter with the request.</li>
  <li>Another csrf token that is stored in a variable, before the jsonp executes. So, the jsonp would only call the function if it finds that variable to have the correct value.</li>
  </ol>
  
  <p>This is a double paranoid solution, because I am not sure if any of these two is bullet-proof.</p>
  
  <p>The questions would be:</p>
  
  <ul>
  <li>Is it safe to send csrf token in a GET param? Or what can I do to make it safe?</li>
  <li>Can someone from a different domain look into the source code of the js, to circumvent trick number (2) ?</li>
  </ul>
  
  <p>To avoid that we start from zero, here is a document I find useful:<br/>
  <a href="https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet" rel="nofollow">https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet</a><br/>
  (but could be that I missed something in there)</p>
  
  <p>Especially interesting: "Disclosure of Token in URL", which I think I have still not fully understood in all its consequences.</p>
  
  <p>EDIT:<br/>
  Other solutions one could think of:<br/><br/>
  &nbsp;&nbsp;&nbsp;3.&nbsp; referrer checking. Not safe enough, afaik. Especially, if the js file is cached on the browser.<br/>
  &nbsp;&nbsp;&nbsp;4.&nbsp; Encryption. Probably not worth the effort..</p>
  
  <p>EDIT II:<br>
  To clarify: "same-domain situation" just means that the html page and the jsonp are served from the same domain. The client machine can be anywhere.</p>
  
  <p>EDIT III:<br>
  I want to be as safe as if I would serve regular json or html/xml (to be requested with ajax or iframe), instead of jsonp. As you probably know, json and html/xml is protected by the same-origin policy, while jsonp is not.</p>
  
  <p>I want to use csrf tokens to achieve the same protection with jsonp. The csrf tokens will obviously be served with the html page.</p>
  
  <p>EDIT IV:<br>
  This is how trick number 2 would look like.<br>
  Page html:</p>
  
  <pre><code>&lt;script type="text/javascript"&gt;
    var token1 = 'upoihjvpaoijpoj';
  &lt;/script&gt;
  &lt;script type="text/javascript" src="xyz/jsonp.js?token2=o8976987698540"&gt;&lt;/script&gt;
  </code></pre>
  
  <p>And then in the xyz/json.js?token2=..:</p>
  
  <pre><code>if (token1 == 'upoihjvpaoijpoj') {
    json_callback(data);
  }
  </code></pre>
  
  <hr>
  
  <p>EDIT V:<br>
  This matter is complex enough, so at least I should add a real-world example. I don't remember the exact use case when I posted this question, so I just write sth that does come close.</p>
  
  <p>A typical example would be a drop-down menu, where we want to load the menu contents with a separate request, because they are the same on every page. However, the menu might contain some links that should only be displayed to specific logged-in users. Let's just assume it is a life-and-death thing that unauthorized visitors may never see those links.</p>
  
  <p>The first idea would be to load the menu with an XHR request. On server side, we can check the cookie / session thingie to check if the user is logged in, and serve a personalized menu.</p>
  
  <p>But, XHR can only start to load once the rest of the page is already there. Javascript, on the other hand, can start loading as soon as the browser parses the html head. So we could hope for a performance benefit, if we serve the menu data with javascript/jsonp instead of XHR.</p>
  
  <p>Now the CSRF scenario:</p>
  
  <ul>
  <li>A user logs in to oursite.com, which creates the session cookie.</li>
  <li>The same user does then visit the attacker site evil.com, which contains a script tag to request the (personalized) oursite.com/menudata.js.</li>
  <li>Due to the same-origin policy, scripts on evil.com can not directly inspect the contents of menudata.js. Instead, it will simply execute menudata.js.</li>
  </ul>
  
  <p>menudata.js could look like this:</p>
  
  <pre><code>spawnMenu({...});
  </code></pre>
  
  <p>Or the "spawnMenu" could be a dynamically chosen string based on the request parameters.
  If menudata.js executes on evil.com, the attackers running this site could provide a function with that name, and then "phone home" and steal the personalized menu data.</p>
  
  <p>Now the idea (point 2. of the initial question) was to do something like this instead in menudata.js:</p>
  
  <pre><code>if (secret_var === 'opijpoijpoizvnpoiq92823pjnfn') {
    spawnMenu({...});
  }
  </code></pre>
  
  <p>This looks quite ok at first. evil.com does not know the secret_var, so when menudata.js executes, it will do nothing.</p>
  
  <p>But then, I heard that there are some nasty tricks where you can "rewrite" quite basic parts of js. Such as, replace the usual way that stuff is cast to string. Maybe even replace comparison operators? This way, a script on evil.com could cheat on our nice little check.</p>